这篇文章阐述了在macOS与Windows系统上如何解决各种已知的Multipass网络问题
内容
在macOS上, QEMU驱动使用Hypervisor.framework来管理实例的网络栈.
在创建实例的时候, 主机上的Hypervisor.framework使用macOS的"网络共享"机制来:
据此, 根据"系统偏好" ->"共享"菜单, "网络共享"服务不再可用. 还好 - 在后台它仍然能支持实例运行.
sudo lsof -iUDP:67 -n -P
仅显示launchd & bootpd)multipass launch
失败
multipass shell
失败
multipass shell
可行但实例无法连接网络
无法决定IP地址一般意味着一些网络配置的不兼容, 或者是来自防火墙或VPN的干扰.
multipassd
是可以的.multipass launch -vvv
的时候出现未知错误
(Unknown error
), Little Snitch可能会干扰了multipassd
的网络连接(参见#1169)sudo lsof -iUDP:67 -n -P
应该有提到bootpd
)
sudo launchctl load -w /System/Library/LaunchDaemons/bootps.plist
来启动可以试试
sudo route -nv add -net 192.168.64.0/24 -interface bridge100
如果产生了"文件已存在"错误, 可以删除文件重试?
sudo route -nv delete -net 192.168.64.0/24
sudo route -nv add -net 192.168.64.0/24 -interface bridge100
也许-static
路由有用?
如果使用"Cisco AnyConnect" - 可试试"OpenConnect"(brew install openconnect
)替代, 因其对路由造成的混乱比较少(但你的公司系统管理员账号/政策可能不允许/不授权这些).
看你的VPN软件是否提供一个"分割连接"的选项 - 一个VPN系统管理员账号会指定一个不通过VPN的IP地址范围.
在/etc/pf.conf
文件的nat ...
行(如果有, 没有就在末尾)之后, 添加这行:
nat on utun1 from bridge100:network to any -> (utun1)
然后运行$ sudo pfctl -f /etct/pf.conf
重启PF
编辑/Library/Preferences/SystemConfiguration/com.apple.vmnet.plist
, 修改“Shared_Net_Address”的值为除了192.168.64.1 -
之外的值.
请注意
如果你改变了子网然后启动实例, 那就会从新的子网产生一个IP.但是如果你试着改回来, 下一次实例启动后变更就会撤销. 这表明了dhcp服务器读取的/var/db/dhcpd_leases
文件中最后的IP, 也因此决定了内网, 并更新Shared_Net_Address以匹配. 所以只有编辑/删除/var/db/dhcpd_leases
才是真正撤销变更的唯一办法.
你能ping通IP地址吗?
$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
^C
--- 1.1.1.1 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2030ms
注意macOS的防火墙会阻止ping
使用ICMP包, 也就是这次测试用到的. 请确保你只为了此次测试已经禁用了"系统偏好"->“安全与隐私”->“防火墙"中的"健康模式”.
如果你再试试:
multipass@x:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=53 time=7.02 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=53 time=5.91 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=53 time=5.12 ms
^C
--- 1.1.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2143ms
rtt min/avg/max/mdev = 5.124/6.020/7.022/0.781 ms
这意味着实例可以直接连接到网络, 但是DNS方案被断开了.
使用dig
工具测试DNS方案会显示断开:
multipass@x:~$ dig google.ie
; <<>> DiG 9.10.3-P4-Ubuntu <<>> google.ie
;; global options: +cmd
;; connection timed out; no servers could be reached
但是如果如下显示, 那就是全部可行:
multipass@x:~$ dig google.ie
; <<>> DiG 9.10.3-P4-Ubuntu <<>> google.ie
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48163
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;google.ie. IN A
;; ANSWER SECTION:
google.ie. 15 IN A 74.125.193.94
;; Query time: 0 msec
;; SERVER: 192.168.64.1#53(192.168.64.1)
;; WHEN: Thu Aug 01 15:17:04 IST 2019
;; MSG SIZE rcvd: 54
为了进一步测试, 试试提供一个显性的DNS服务器
multipass@x:~$ dig @1.1.1.1 google.ie
; <<>> DiG 9.10.3-P4-Ubuntu <<>> @1.1.1.1 google.ie
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11472
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1452
;; QUESTION SECTION:
;google.ie. IN A
;; ANSWER SECTION:
google.ie. 39 IN A 74.125.193.94
;; Query time: 6 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Thu Aug 01 15:16:27 IST 2019
;; MSG SIZE rcvd: 54
这意味着问题出在macOS的"网络共享"功能 - 因为某些原因它的内置DBS服务器断开了.
内置的DNS服务器应该是绑定到主机53端口的"mDNSResponder".
如果使用Lillter Snitch或者其他逐进程防火墙, 确保mDNSResponder能建立出站连接. MacOS的内置防火墙不应影响到它.
用以下命令检查一下主机上哪些绑定到那个端口:
$ sudo lsof -iTCP:53 -iUDP:53 -n -P
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mDNSRespo 191 _mdnsresponder 17u IPv4 0xa89d451b9ea11d87 0t0 UDP *:53
mDNSRespo 191 _mdnsresponder 25u IPv6 0xa89d451b9ea1203f 0t0 UDP *:53
mDNSRespo 191 _mdnsresponder 50u IPv4 0xa89d451b9ea8b8cf 0t0 TCP *:53 (LISTEN)
mDNSRespo 191 _mdnsresponder 55u IPv6 0xa89d451b9e2e200f 0t0 TCP *:53 (LISTEN)
以上输出显示了实例正在运行时候的正确状态. 如果无实例在运行(并且系统偏好中的网络共享被禁用了), 这条命令就会返回空.
任何其他出现在输出中的命令意味着进程与网络共享冲突了, 因此断开了实例中的DNS.
nameserver 1.1.1.1
"1.1.1.1"是CloudFlare提供的免费DNS服务, 但是你自己也可以用.
macOS通过Multipass过滤器包桥接, 这样分配给VM的原始IP地址就被允许通过. 如果你添加了额外的地址(例如IP别名)到VM, 那么ARP广播会通过但ARP相应会被过滤掉.
这意味着依赖额外IP地址的应用, 例如microk8s下的metallb, 将会不可用.
更新到MacOS12.4之后(然而这些也可能在更新到其他版本时发生), MacOS对防火墙做了更新. 如果在更新之后实例没有停止, 那很有可能实例的连接就会被MacOS防火墙阻止. 我们无法确切的知道防火墙的哪一更新导致的, 看来可能是苹果的bootpd
停止依赖DHCP请求. 有几个步骤能盲目的解决这个问题(看这个问题的讨论或者其他可替代方案). 你可以先试试:
Windows上, Multipass使用本地的"Hyper-V"模拟器, 并伴随着一起创建"默认开关". 因此, 实例根据DHCP(IP地址)和DNS(域名名称方案)使用"网络共享".
很不幸, 默认开关很诡异, Windows更新时常让它处于一个很奇怪的状态. 这些可能导致新实例启动失败, 现存实例启动超时.
这些断连状态在重启后依然存在. 一个已帮助过的解决办法是, 从默认开关和重启中移除网络共享:
PS> Get-HNSNetwork | ? Name -Like "Default Switch" | Remove-HNSNetwork
PS> Restart-Computer
Hyper-V会在下次启动时重新创建它.
另一个实例超时的原因可能是"过时的"IP地址被存储在特定的实例的`网络连接共享"主机文件中.
通过管理员权限, 编辑C:\WINDOWS\System32\drivers\etc\hosts.ics
并看看词条是否有你的实例名称. 如果词条不止1个, 那就移除除了第一条之外的所有词条. 再次保存文件并重试.
杀毒软件和网络安全软件一般不必支持虚拟化. 如果你连接有问题, 暂时测试禁用这些软件看看能不能有好的结果. 这些软件案例有Symantec, ESET, Kaspersky, Malware Bytes.
How to troubleshoot networking