我正在尝试在我的 Linux 主机(运行 Fedora 33)和 QEMU 实例(Xilinx 设备的分支)之间建立仅主机网络,更具体地说是在桥接接口(主机)和 tap 接口(QEMU)之间建立。
当尝试从主机 TCP 客户端连接到 QEMU TCP 服务器时,主机似乎忽略了来自 QEMU 的 SYN/ACK 数据包,或者至少这是我从桥接接口上的嗅探数据包中可以收集到的信息。
以下是我正在做的事情:
我正在创建一个桥接接口
br0
、一个分接接口tap0
、连接tap0
到br0
并192.168.2.210/24
为桥接接口分配一个静态地址。ip link add name br0 type bridge ip tuntap add name tap0 mode tap ip link set tap0 master br0 ip link set br0 up ip link set tap0 up ip addr add 192.168.2.210/24 dev br0
我正在使用目标平台的所有相关参数以及使 QEMU 连接到我创建的 tap 接口的参数来启动 QEMU 客户机。客户机操作系统上的接口也有一个静态 IP,位于主机地址的子网中:
192.168.2.215/24
。./qemu/build-v2020.1/arm-softmmu/qemu-system-arm \ -nic tap,ifname=tap0,script=no,downscript=no \ [PLATFORM_SPECIFIC_ARGUMENTS]
在主机上,我启动一个 Python 脚本来连接到客户机上的开放 TCP 端口。
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect(('192.168.2.215', 1275))
发生了什么:在客户机/TCP 服务器上,我可以看到第一个 SYN 数据包进来,SYN/ACK 数据包出去。在主机/TCP 客户端上,嗅探时br0
,我可以看到第一个 SYN 数据包出去,SYN/ACK 数据包进来,但看起来 SYN/ACK 数据包被忽略了,或者没有到达 Python 进程(我也尝试过使用 C++ 程序,结果相同)。客户端卡在了 中sock.connect()
,数据包捕获显示客户端正在重新传输 SYN 数据包,而服务器正在用更多 SYN/ACK 数据包对这些重新传输做出反应。
No. Time Source Destination Protocol Length Info
1 0.000000000 fe80::e083:d7ff:fe6e:5ce2 ff02::16 ICMPv6 150 Multicast Listener Report Message v2
2 0.000024907 192.168.2.210 224.0.0.22 IGMPv3 54 Membership Report / Join group 224.0.0.252 for any sources
3 0.331992771 192.168.2.210 224.0.0.22 IGMPv3 54 Membership Report / Join group 224.0.0.252 for any sources
4 0.707989061 fe80::e083:d7ff:fe6e:5ce2 ff02::16 ICMPv6 150 Multicast Listener Report Message v2
5 5.960512301 e2:83:d7:6e:5c:e2 Broadcast ARP 42 Who has 192.168.2.215? Tell 192.168.2.210
6 5.967187240 02:00:00:00:00:01 e2:83:d7:6e:5c:e2 ARP 60 192.168.2.215 is at 02:00:00:00:00:01
7 5.967225848 192.168.2.210 192.168.2.215 TCP 74 59130 → 1275 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1376754999 TSecr=0 WS=128
8 6.002308149 192.168.2.215 192.168.2.210 TCP 66 1275 → 59130 [SYN, ACK] Seq=0 Ack=1 Win=7300 Len=0 MSS=1460 WS=1 SACK_PERM=1
9 6.980032443 192.168.2.210 192.168.2.215 TCP 74 [TCP Retransmission] 59130 → 1275 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1376756019 TSecr=0 WS=128
10 6.981422696 192.168.2.215 192.168.2.210 TCP 66 [TCP Retransmission] 1275 → 59130 [SYN, ACK] Seq=0 Ack=1 Win=7300 Len=0 MSS=1460 WS=1 SACK_PERM=1
11 9.027996685 192.168.2.210 192.168.2.215 TCP 74 [TCP Retransmission] 59130 → 1275 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1376758067 TSecr=0 WS=128
12 9.029198423 192.168.2.215 192.168.2.210 TCP 66 [TCP Retransmission] 1275 → 59130 [SYN, ACK] Seq=0 Ack=1 Win=7300 Len=0 MSS=1460 WS=1 SACK_PERM=1
为什么我看到这些 SYN/ACK 数据包进入br0
,但却无法到达套接字?
一些想法:
- 我不认为这是一个 TCP 校验和错误:在 Wireshark 中启用校验和验证可确认传入数据包的校验和是正确的。
- 我也不认为这是由于缺少 ARP 表条目造成的:在数据包捕获中,我可以看到 ARP 请求和回复符合预期。此外,查看嗅探到的数据包,SYN 和 SYN/ACK 数据包的 MAC 层源地址和目标地址看起来是正确的。
- 这可能是防火墙问题吗?我试过了
systemctl stop firewalld.service
,但仍然出现同样的情况。
我的设置细节:
- 主机操作系统:Fedora 33
- 客户操作系统:带有 TCP 堆栈的裸机 FreeRTOS
- 适用于 Xilinx 设备的 QEMU 分支(https://github.com/Xilinx/qemu)
答案1
在对数据包捕获进行进一步分析后,我意识到 SYN/ACK 数据包br0
是以错误的 IP 校验和,我没费心去检查。这个错误校验和的原因是客户操作系统上的 TCP/IP 堆栈配置为卸载 IP 校验和计算,而默认的 QEMU 模拟 NIC 似乎不支持该计算。
在客户操作系统上禁用 IP 校验和卸载可解决该问题。