Ubuntu 22.04下适配systemd-resolve到resolvectl后无法上网的问题求助
问题背景
我把Ubuntu升级到22.04后,用来路由工作VPN流量的脚本出问题了——原来脚本里用的systemd-resolve命令在22.04里被resolvectl替代了。
我的使用流程是:手动执行vpn.sh连接VPN,这个脚本会调用vpn_routes.sh(就是出问题的那个),让客户的特定在线工具流量走VPN,其他流量直接走外网。
我试了两种适配方案,但都会导致VPN连接成功后无法上网:
- 给
resolvectl加软链接到systemd-resolve:sudo ln -s /usr/bin/resolvectl /usr/bin/systemd-resolve - 直接把命令改成
resolvectl:sudo resolvectl dns gxxx 11.xxx.x.xx 22.xxx.x.xxx sudo resolvectl domain xxxxx.com
原systemd-resolve命令是:
sudo systemd-resolve --interface gxxx --set-dns 11.xxx.x.xx --set-dns 22.xxx.x.xxx --set-domain xxxxx.com
完整的vpn_routes.sh脚本:
#!/bin/bash GW=$(route -n | grep gxxx | grep 0.0.0.0 | awk '{print $2}') echo "Gateway: ${GW}" sudo route del -net 0.0.0.0 dev gxxx sudo route add -net xx.x.xx.x gw ${GW} netmask 255.255.254.0 dev gxxx sudo route add -net xx.x.xx.0 gw ${GW} netmask 255.255.254.0 dev gxxx sudo systemd-resolve --interface gxxx --set-dns 11.xxx.x.xx --set-dns 22.xxx.x.xxx --set-domain xxxxx.com
补充网络状态信息(已脱敏)
执行ip a的输出:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu xxx qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/XXX scope host valid_lft forever preferred_lft forever 2: wlpxxxxx: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu xxx qdisc noqueue state UP group default qlen 1000 link/ether 64:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff inet xxx.xxx.x.x/xx brd xxx.xxx.x.xx scope global dynamic noprefixroute wlpxxxxx valid_lft 68xxxsec preferred_lft 68xxxsec inet6 2803:xxxx:98c4:xxxx:xxxx:efc5:xxxx:xxxx/64 scope global temporary dynamic valid_lft 58xxxxsec preferred_lft 6xxxxsec inet6 2803:xxxx:xxxx:8853:xxxx:ee6d:xxxx:xxxx/64 scope global dynamic mngtmpaddr noprefixroute valid_lft 114xxxxxsec preferred_lft 11xxxxxxsec inet6 fe80::xxxx:xxxx:xxxxx:64d5/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: gxxx: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu xxxx xxxx xxxxx state UP group default qlen xxx link/none inet 10.xxx.xx.xxx/xx scope global gxxx valid_lft forever preferred_lft forever 4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff inet 172.xx.x.x/xx brd 172.xx.xxx.xxx scope global docker0 valid_lft forever preferred_lft forever inet6 xxxxxxxxxxx/64 scope link valid_lft forever preferred_lft forever 27: br-xxxxxxxxxxx: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu xxxx qdisc noqueue state DOWN group default link/ether 02:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff inet 172.xx.x.x/xx brd 172.xx.xxx.xxx scope global br-xxxxxxxxxxx valid_lft forever preferred_lft forever inet6 xxxxxxxxxxxxxx/64 scope link valid_lft forever preferred_lft forever
执行ip route的输出(示例):
default via xxx.xxx.x.x dev wlpxxxxx proto dhcp metric 600 xxx.xxx.xx.xx/xx via xxx.xxx.x.x dev wlpxxxxx xxx.xxx.xx.xx/xx via xxx.xxx.x.x dev wlpxxxxx xxx.xxx.xx.xx/xx via xxx.xxx.x.x dev wlpxxxxx xxx.xxx.xx.xx/xx dev wlpxxxxx scope link metric 1000 172.xx.x.x/xx dev docker0 proto kernel scope link src 172.17.0.1 linkdown 172.xx.x.x/xx dev br-xxxxxxxxxxx proto kernel scope link src 172.xx.x.x linkdown xxx.xxx.xx.xx/xx dev wlpxxxxx proto kernel scope link src xxx.xxx.xx.x metric 600 xxx.xxx.xx.x/xx via xxx.xxx.x.x dev wlpxxxxx xxx.xxx.xx.x/xx via xxx.xxx.x.x dev wlpxxxxx 10.x.xx.x/xx via 10.xxx.xx.xxx dev gpd0 10.x.xx.x/xx via 10.xxx.xx.xxx dev gpd0 10.xx.x.x/xx via 10.xxx.xx.xxx dev gpd0
执行resolvectl status的输出:
Global Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: foreign Current DNS Server: 11.xxx.x.xx DNS Servers: 11.xxx.x.xxx 22.xxx.x.xxx DNS Domain: xxxxx.com Link 2 (wlpxxxxx) Current Scopes: DNS Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported DNS Servers: xxx.xxx.x.x fexxxxxxxxxx Link 3 (gxxx) Current Scopes: DNS Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported Current DNS Server: 11.xxx.x.xxx DNS Servers: 11.xxx.x.xxx 22.xxx.x.xxx DNS Domain: xxxxx.com Link 4 (docker0) Current Scopes: none Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported Link 27 (br-xxxxxxxxxxx) Current Scopes: none Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
问题分析与解决方案
从你的resolvectl status输出能看出问题:VPN接口gxxx被设置了+DefaultRoute,这会让所有DNS请求都优先走VPN的DNS服务器,但你的VPN DNS大概率只能解析内部的xxxxx.com域名,外部域名解析失败,自然就无法上网了。
原systemd-resolve命令的作用是只为指定接口的特定域名绑定DNS服务器,换成resolvectl时需要注意语法细节:
正确的命令应该是:
sudo resolvectl dns gxxx 11.xxx.x.xx 22.xxx.x.xxx sudo resolvectl domain gxxx '~xxxxx.com'
这里的~是关键——它表示只有xxxxx.com及其所有子域名的DNS请求才会使用gxxx接口的DNS服务器,其他域名依然用无线接口wlpxxxxx的DNS,这样就能同时兼顾内网工具和外网访问了。
修改后的完整vpn_routes.sh脚本:
#!/bin/bash GW=$(route -n | grep gxxx | grep 0.0.0.0 | awk '{print $2}') echo "Gateway: ${GW}" sudo route del -net 0.0.0.0 dev gxxx sudo route add -net xx.x.xx.x gw ${GW} netmask 255.255.254.0 dev gxxx sudo route add -net xx.x.xx.0 gw ${GW} netmask 255.255.254.0 dev gxxx # 替换为正确的resolvectl命令 sudo resolvectl dns gxxx 11.xxx.x.xx 22.xxx.x.xxx sudo resolvectl domain gxxx '~xxxxx.com'
执行完脚本后,再用resolvectl status检查gxxx接口的DNS Domain应该显示为~xxxxx.com,并且DefaultRoute应该变为-,这样就能正常访问内外网了。
备注:内容来源于stack exchange,提问作者Naxxio

