我花了很多时间在这个奇怪的问题上,我创建了一个简单的主机和虚拟机配置来尝试隔离该问题。
本问题中的术语
- 主机:裸机服务器
- VM:KVM 客户虚拟机
- 到 ppp0 的传入连接:从具有不同互联网 IP 的单独互联网连接进行测试。
主机上已启用端口转发
root@host $ sysctl net/ipv4/conf/all/forwarding net.ipv4.conf.all.forwarding = 1
网络设置
- 主机 eth0:
10.0.0.155
- 主机 ppp0:(互联网 IP)
- VM 桥接适配器:
10.0.0.121
- VM NAT 适配器:
192.168.122.126
- 虚拟机正在监听 TCP
0.0.0.0:10003
我想解决哪些不起作用的问题(主要目标)
主机端口 10003 上的传入连接应从 ppp0 转发到 VM 的桥接适配器。iptables-save -c 显示所使用的配置和计数器。 http://codepad.org/SWzL5kEy
什么有效
主机可以通过其任一接口上的端口 10003 连接到虚拟机:
root@host $ nc -z 192.168.122.126 10003; echo $? 0 root@host $ nc -z 10.0.0.121 10003; echo $? 0
网络上的其他 PC 可以连接到虚拟机的桥接适配器
user@otherPConLAN $ nc -z 10.0.0.121 10003; echo $? 0
主机端口 10003 上的传入连接已成功从 ppp0 转发到 VM 的 NAT 适配器。iptables-save -c 显示所使用的配置和计数器。 http://codepad.org/fwd3R7rF
网络上的每个节点(包括主机、虚拟机和其他 PC)都可以相互 ping 通。
iptables-save -c 输出的区别
在显示 iptables-save -c 输出的两个浏览器选项卡之间切换,我看到配置是相同的。触发了相同的计数器。但主要的重要区别是,当成功建立与 NAT 适配器的连接时,第 32 行的 FORWARD 规则的计数高于与桥接适配器的连接失败时。
我的理论
我的理论是某种类型的 NAT 执行不正确,数据可能正在移动到 VM,但无法找到通过主机返回并从 ppp0 到客户端的路径。
VM 的 .xml 文件中的 NIC 配置
<interface type='bridge'> <mac address='11:11:11:11:11:11'/> <source bridge='br0'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> </interface> <interface type='network'> <mac address='22:22:22:22:22:22'/> <source network='default'/> <model type='virtio'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> </interface>
桥梁状态
root@host $ brctl show bridge name bridge id STP enabled interfaces br0 8000.(obfuscated) no eth0 vnet0 virbr0 8000.(obfuscated) yes vnet1
TRACE 输出
以下是两种场景的 TRACE 输出。为了使 TRACE 输出简短且匿名,主机的互联网 IP 已替换为“hi”,测试客户端的互联网 IP 已替换为“ci”。
为 TRACE 添加了以下 IPTABLES 规则
root@host $ iptables -t raw -A PREROUTING -p tcp --dport 10003 -j TRACE root@host $ iptables -t raw -A OUTPUT -p tcp --dport 10003 -j TRACE
客户端运行了这个命令
user@remoteClient $ nc -z (host's internet IP) 10003; echo $?
当客户端无法连接到桥接适配器时运行此跟踪输出 http://codepad.org/FC9BhF7y
当客户端成功连接到 NAT 适配器时,运行此跟踪输出 http://codepad.org/0uHpXXzZ