虚拟机部署OpenWrt外部无法访问问题

前几天心血来潮,想尝试下使用VirtualBox部署OpenWrt充当旁路由。在配完OpenWrt后,手机的流量死活没有办法被旁路由转发。当时以为是OpenWrt设置问题,详细查阅了OpenWrt官网有关接口和防火墙的设置,折腾半天并没有解决。作为一个网工老司机,应用功能可以没有实现,网络绝不能不通。绝对无法忍受在我面前发生网络不通。于是又折腾两天,终于找到原因了。下面是排错(pò àn)过程

环境

物理拓扑如下,手机可正常通过无线路由器上网,笔记本无线连接至无线路由器。

OPENWRT PHY

其中,

  • 手机为iphone,无线连接至主路由器,自动获得来自主路由分配的IP为192.168.3.101/24,GW192.168.3.1

  • 主路由器为某普通家用无线路由器,LAN口地址192.168.3.1/24

  • 笔记本电脑内运行VirtualBox虚拟机桥接到无线网卡,开启混杂模式,虚拟机运行OpenWrt22.03.3;OpenWrt关键配置如下:

    • 网卡数:1张

    • 接口配置:静态地址,IP 192.168.3.2/24,GW 192.168.3.1;

    • 防火墙:INPUT,OUTPUT,FORWARD全通,开启MASQ(PAT)

预期结果

按照如上环境配置后,将手机网络设置为手动,GW改为192.168.3.2,DNS改为223.5.5.5。理论上来说手机应该可以正常上网,预想中的逻辑拓扑如下

OPENWRT LOG

各终端IP参数如下

MAC IP DHCP自动获取 IP手动配置
笔记本电脑 AAAA.AAAA.AAAA 192.168.3.102 192.168.3.102
手机 BBBB.BBBB.BBBB 192.168.3.101
OpenWrt虚拟机 CCCC.CCCC.CCCC 192.168.3.2
无线路由器 DDDD.DDDD.DDDD 192.168.3.1
win10虚拟机 EEEE.EEEE.EEEE 192.168.168.3.103

OpenWrt虚拟机,笔记本电脑和手机应当可以视作在同一二层局域网。预想中的通信过程如下:

首先,当手机连接WIFI后,发送ARP广播请求192.168.3.2(OpenWrt)的mac地址;OpenWrt回复ARP。

然后手机开始通信,假设ping 223.5.5.5,即发送icmp,源目地址如下

SMAC DMAC SIP DIP
BBBB.BBBB.BBBB CCCC.CCCC.CCCC 192.168.3.101 223.5.5.5

OpenWrt收到报文后做PAT转发,转发报文的源目地址如下:

SMAC DMAC SIP DIP
CCCC.CCCC.CCCC DDDD.DDDD.DDDD 192.168.3.2 223.5.5.5

然后无线路由器将OpenWrt的包当做某个终端正常的包进行转发,收到223.5.5.5的回复后转发给OpenWrt,OpenWrt再根据PAT转发表转发回给手机

故障排查

事实上安装上述环境配置后,手机无法上网。随后开始故障排查

确认OpenWrt收到来自手机的数据包

首先,怀疑OpenWrt没有收到手机的包,于是在OpenWrt上安装tcpdump,使用如下命令抓包

1
tcpdump -i eth0 icmp

发现OpenWrt有收到手机192.168.3.101的包,但是没有转发出去的包

确认OpenWrt配置

然后怀疑OpenWrt配置有问题,反复确认OpenWrt接口配置,防火墙配置。发现并没有问题,而且可以肯定:接口可以是桥接的接口,也可以是单独的接口防火墙转发设置可以配置MASQ IP地址伪装,也可以不配置,不影响ping结果

新建测试机

这就很奇怪了,明明OpenWrt配置正确,也受到了包,死活不转发。这样排除了OpenWrt的问题,只能怀疑是VirtualBox的问题。

后来,我尝试新建一台win 10虚拟机,网络也是桥接模式,使用这台win10配置OpenWrt作为网关居然可以正常上网。在OpenWrt上抓包,也能抓到全部过程。

比较win10和手机的包

按照之前的逻辑拓扑,如果添加了win10虚拟机,win10虚拟机 应该也是属于同一二层,不应该和手机有什么不一样的地方。但事实显示确实win10可以正常上网,手机不能。于是准备在OpenWrt上比较两个包,在OpenWrt上使用以下命令抓包并保存:

1
tcpdump -i eth0 -w cap.cap

在抓包期间,用手机和win10都发起对223.5.5.5的ping包。终于得到了很有趣的结果:

手机包

SMAC DMAC SIP DIP
BBBB.BBBB.BBBB AAAA.AAAA.AAAA 192.168.3.101 223.5.5.5

win10 ping包

SMAC DMAC SIP DIP
EEEE.EEEE.EEEE CCCC.CCCC.CCCC 192.168.3.103 223.5.5.5

很明显,win10的包是符合预期的;手机包源目ip符合预期,但MAC居然是笔记本的MAC。这有点搞糊涂了,颠覆了我对桥接的认知;这说明,手机请求OpenWrt 即192.168.3.2的MAC地址,收到的回复确是笔记本的MAC(后来使用另一台电脑做客户端验证了这一点,arp表项确实是这样显示的)。但这个现象确实反应了手机无法上网的本质原因,由于之前tcpdump抓包默认只显示ip地址,忽略了二层mac地址;看来问题就出在这里:手机包发过来的目的MAC是笔记本即宿主机,而win10虚拟机则为OpenWrt的MAC

手机ping OpenWrt

既然是这样,那是不是手机ping OpenWrt 192.168.3.2也不通呢,尝试了一下,发现是通的。而手机ping OpenWrt时,OpenWrt收到的MAC却是自己并不是笔记本的MAC。这十有八九是VirtualBox如何处理桥接包的问题了。

坑爹的VirualBox桥接机制

一切矛头指向VirutualBox,最后去查看VirutualBox文档,找到了官方对桥接的解释

原文是:

Note

Bridging to a wireless interface is done differently from bridging to a wired interface, because most wireless adapters do not support promiscuous mode. All traffic has to use the MAC address of the host’s wireless adapter, and therefore Oracle VM VirtualBox needs to replace the source MAC address in the Ethernet header of an outgoing packet to make sure the reply will be sent to the host interface. When Oracle VM VirtualBox sees an incoming packet with a destination IP address that belongs to one of the virtual machine adapters it replaces the destination MAC address in the Ethernet header with the VM adapter’s MAC address and passes it on. Oracle VM VirtualBox examines ARP and DHCP packets in order to learn the IP addresses of virtual machines.

翻译过来意思大概是

注意

桥接到一个无线网会和桥接到有线网卡有些不同,因为大多数无线适配器不支持混杂模式。所有流量都要使用主机的无线适配器的MAC地址,所以Oracle VirutualBox需要替换出去的以太头的源MAC地址来确保回复会被送到主机接口。当Oracle VirtualBox看到一个进来的包目的IP属于某个虚拟机的适配器时,它替换目的以太头MAC地址为VM虚拟机的适配器MAC地址并传到改虚拟机适配器。Oracle VirutualBox检查ARP和DHCP包以用来学习虚拟机的IP地址

总结

我们一开始的预期在有线网卡的情况下都是对的,无线网卡不支持混杂模式,即不接受目的MAC不为自己的报文,所以就有上述官方文档转换MAC的机制。但这种机制只是转换目的IP为虚拟机的报文,我们由于使用虚拟机做转发,所以目的IP并不是虚拟机的IP,导致不通。
最后我们对目的地址不为自己时的处理方式做个总结:

对于一台主机(不运行虚拟机)来说:

  • 收到mac地址不为自己的包,都会直接丢弃;

  • 收到IP地址不为自己但mac为自己的包,如果系统开启了ip转发功能则会转发此包,否则丢弃

对于宿主机(桥接模式)来说

  • 收到mac或IP不为自己的包,交由虚拟机管理程序处理
    无线网卡:

    • 若mac不为宿主机,则丢弃(无线网卡不支持混杂模式)

    • 若IP不是任何一台虚拟机的IP,mac为宿主机IP,交由宿主机处理(但是抓包看的到,因为混杂模式可以监听到宿主机物理网卡的数据包)

    • 若IP是其中某台虚拟机IP,mac为宿主机IP,转发到此虚拟机

    有线网卡(开启混杂模式):

    • 若mac是宿主机,交由宿主机处理;

    • 若mac不是任何一台虚拟机的mac,也不是宿主机mac,丢弃;

    • 若mac是其中一台虚拟机的mac,转发到此虚拟机

解决方案

将无线改为有线,完美解决。。。。