总目录
1. 概览
2. 教程
3. 使用指引
3.1 安装Multipass - 基于Linux / 基于macOS / 基于Windows
3.2 管理实例 - 创建实例 / 修改实例 / 使用实例 / 使用实例命令别名 / 与实例共享数据 / 移除实例
3.3 管理Multipass - 设置驱动 / 使用Multipass服务授权代理 / 远程使用Multipass / 提高挂载性能 / 使用Packer打包Multipass镜像 / 设置图像界面 / 使用不同的macOS终端 / 配置Multipass外部储存位置
3.4 问题排查 - 连接日志 / 网络问题处理 👈
这篇文章阐述了在macOS与Windows系统上如何解决各种已知的Multipass网络问题
内容
macOS网络问题处理
架构
在macOS上, QEMU驱动使用Hypervisor.framework来管理实例的网络栈.
在创建实例的时候, 主机上的Hypervisor.framework使用macOS的"网络共享"机制来:
- 创建一个虚拟切换开关, 然后让每个实例都连接到这个开关(子网 192.168.64.*)
- 给这个切换开关于地址192.168.64.1提供DHCP和DNS解决方案(经由运行在主机上的bootpd & mDNSResponder服务); 一个自动生成的文件/etc/bootpd.plist会配置好上述网络 - 编辑它将会徒劳无益, 因为macOS会按照自己的想法重新生成这个文件.
据此, 根据"系统偏好" ->"共享"菜单, "网络共享"服务不再可用. 还好 - 在后台它仍然能支持实例运行.
已知的Multipass关联工具
- VPN软件对于管理路由有时候过于激进, 它可能会将192.168.64子网路由到VPN接口, 而不是让它在本地可用.
- 潜在罪犯: OpenVPN, F5, Dell SonicWall, Cisco AnyConnect, Citrix/Netscaler Gateway, Jupiter Junos Pulse / Pulse Secure
- Tunnelblick不会造成上述问题
- Cisco Umbrella Roaming Client绑定了localhost:53地址, 就与网络共享冲突了, 打断了实例的DNS(参见: Umbrella Roaming Client OS X与网络共享
- dnscrypt-proxy/dnscrypt-wrapper/cloudflared-proxy
默认配置都是绑定locahost端口53, 与网络共享冲突 - 另一个dnsmasq进程绑定了localhost端口53
- 自定义的DHCP服务器绑定到端口67?(
sudo lsof -iUDP:67 -n -P
仅显示launchd & bootpd) - MacOS更新会让防火墙产生变更并让实例处于未知的状态(如下)
问题类别
multipass launch
失败multipass shell <instance>
失败multipass shell <instance>
可行但实例无法连接网络- 实例间的其他IP无法访问
普通网络问题
无法决定IP地址一般意味着一些网络配置的不兼容, 或者是来自防火墙或VPN的干扰.
问题处理(拓展部分)
- 防火墙
- 防火墙是否启用着?
- 如果开着就不要"阻止所有入站连接"
- 阻止所有入站连接不会让DHCP服务器本地化运行, 就可以给实例一个IP.
- 然而阻止所有入站连接到
multipassd
是可以的.
- VPN
- Little Snitch - 默认就好, 应该允许mDNSResponder和bootpd连接到BPF
如果你在下载图片有问题, 且/或在尝试multipass launch -vvv
的时候出现未知错误
(Unknown error
), Little Snitch可能会干扰了multipassd
的网络连接(参见#1169) - 网络共享 - 一般不会冲突
- bootpd DHCP服务器是否活跃?(
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地址范围.
- Cisco如此做
- Pulse Secure / Jupiter Junos Pulse这么做
VPN冲突的潜在替代方案
在/etc/pf.conf
文件的nat ...
行(如果有, 没有就在末尾)之后, 添加这行:
nat on utun1 from bridge100:network to any -> (utun1)
然后运行$ sudo pfctl -f /etct/pf.conf
重启PF
可能的其他选项 - 给Multipass配置不同的子网?
编辑/Library/Preferences/SystemConfiguration/com.apple.vmnet.plist
, 修改“Shared_Net_Address”的值为除了192.168.64.1 -
之外的值.
- 如果编辑了plist文件并且处于192.168的范围内就可行, 因为Multipass会对此硬编码
请注意
如果你改变了子网然后启动实例, 那就会从新的子网产生一个IP.但是如果你试着改回来, 下一次实例启动后变更就会撤销. 这表明了dhcp服务器读取的/var/db/dhcpd_leases
文件中最后的IP, 也因此决定了内网, 并更新Shared_Net_Address以匹配. 所以只有编辑/删除/var/db/dhcpd_leases
才是真正撤销变更的唯一办法.
DNS问题
你能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.
可能的替代方案
- 配置实例中的NDS以使用外部网络DNS服务器. 在/etc/resolv.conf文件末尾手动加入这行就可以:
nameserver 1.1.1.1
"1.1.1.1"是CloudFlare提供的免费DNS服务, 但是你自己也可以用.
- 在第一次启动的时候使用设置/etc/resolv.conf以自定义云启动
ARP问题
macOS通过Multipass过滤器包桥接, 这样分配给VM的原始IP地址就被允许通过. 如果你添加了额外的地址(例如IP别名)到VM, 那么ARP广播会通过但ARP相应会被过滤掉.
这意味着依赖额外IP地址的应用, 例如microk8s下的metallb, 将会不可用.
macOS更新导致的问题
更新到MacOS12.4之后(然而这些也可能在更新到其他版本时发生), MacOS对防火墙做了更新. 如果在更新之后实例没有停止, 那很有可能实例的连接就会被MacOS防火墙阻止. 我们无法确切的知道防火墙的哪一更新导致的, 看来可能是苹果的bootpd
停止依赖DHCP请求. 有几个步骤能盲目的解决这个问题(看这个问题的讨论或者其他可替代方案). 你可以先试试:
- 重启电脑
- 禁用, 然后重新启用网络共享和/或防火墙
- 在防火墙允许驱动(QEMU)和multipass的入站连接
Windows网络问题处理
架构
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.