以下是我建立设置所采取的步骤:
- 我有两台电脑(均为 x86,运行 Ubuntu 14.04 LTS)。
- 我安装了 2 台虚拟机 (VM) - 每台机器上一台。
- 两个虚拟机都是 Ubuntu Server 14.04 LTS。
- 在一台 x86 上,我使用 kvm 运行一台 VM。在另一台 x86 上,我使用 VirtualBox 运行另一台 VM。
- 我通过路由器连接两个 x86。
====================================================
(ubuntu1)[虚拟机](X86,1)------{路由器}------(X86,2)[虚拟盒](ubuntu2)
====================================================
现在,我允许在所有 4 台机器上进行 IPv4 转发(更改为/etc/sysctl.conf
,并使用sysctl -p
),并将所有 4 台机器设置为具有单个 NIC(eth0),然后将其设置/etc/network/interfaces
为手动)。
接下来,我首先为两个 x86 的 NIC 分配地址,设置默认网关等ping
。一切正常。之后,我为一个 VM 分配一个地址(而不是运行该 VM 的 x86)。同样,效果很好。最后,为第二台 VM 设置一个 IP 地址(同样,而不是运行第二台 VM 的 x86)。
在某个时候 -ping
不起作用。当我检查数据包时,我可以看到一个虚拟机响应,而另一个没有响应。我通过以下方式检查了这一点:
- 我选择一台虚拟机(假设为 ubuntu1),然后
ping
在tcpdump
这台机器上(ping [IP_ADDRESS_ubuntu2] &
接着tcpdump -i eth0
) - 将 x86 之间的线路连接到集线器(复制数据包)并将
wireshark
其连接起来。
结果总是相同的 - 我可以看到一个虚拟机向另一个虚拟机注册 ICMP 数据包的回声(这是回复的虚拟机),而另一个虚拟机注册来自另一个虚拟机的回声和回复。
因此 - ICMP 数据包实际上机器到了,却ping
什么都不显示!
以下是最后设置的示例:
====================================================
(55.55.55.55)[虚拟机]-----------{路由器}-----------[虚拟盒](22.22.22.22)
====================================================
正在运行ping
并tcpdump
处于 55.55.55.55 状态:
[email protected]:/home# ping 22.22.22.22 &
[email protected]:/home# PING 22.22.22.22 (22.22.22.22) 56(84) bytes of data.
[email protected]:/home# tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
07:10:11.758872 IP 55.55.55.55 > 22.22.22.22: ICMP echo request, id 5499, seq 6, length 64
07:10:12.758785 IP 55.55.55.55 > 22.22.22.22: ICMP echo request, id 5499, seq 7, length 64
07:10:13.766994 IP 55.55.55.55 > 22.22.22.22: ICMP echo request, id 5499, seq 8, length 64
07:10:14.767637 IP 55.55.55.55 > 22.22.22.22: ICMP echo request, id 5499, seq 9, length 64
正在运行ping
并tcpdump
于 22.22.22.22 运行:
[email protected]:/home# ping 55.55.55.55 &
[email protected]:/home# PING 55.55.55.55 (55.55.55.55) 56(84) bytes of data.
[email protected]:/home# tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:58:01.883915 IP 22.22.22.22 > 55.55.55.55: ICMP echo request, id 4099, seq 8, length 64
15:58:01.884390 IP 55.55.55.55 > 22.22.22.22: ICMP echo reply, id 4099, seq 8, length 64
15:58:02.885795 IP 22.22.22.22 > 55.55.55.55: ICMP echo request, id 4099, seq 9, length 64
15:58:02.886298 IP 55.55.55.55 > 22.22.22.22: ICMP echo reply, id 4099, seq 9, length 64
但请注意,机器“知道”另一台机器在哪里:
[email protected]:/home/rad# ip route get 22.22.22.22
22.22.22.22 via 55.55.55.1 dev eth2 src 55.55.55.55
cache
有想法吗?
更新 1
各种命令的输出:
[email protected]:/home# iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
[email protected]:/home# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
[email protected]:/home# netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 55.55.55.1 0.0.0.0 UG 0 0 0 eth0
55.55.55.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
更新2
一侧的 IP 地址更改(55.55.55.55 --> 55.55.55.54)会收到 ICMP 回复 - 意味着ping
有效。
另一端的 IP 地址更改没有任何区别。
[email protected]:/home/rad# ifconfig eth0 55.55.55.54/24
[email protected]:/home/rad# ping 22.22.22.22
PING 22.22.22.22 (22.22.22.22) 56(84) bytes of data.
64 bytes from 22.22.22.22: icmp_seq=1 ttl=63 time=1.05 ms
64 bytes from 22.22.22.22: icmp_seq=2 ttl=63 time=0.568 ms
64 bytes from 22.22.22.22: icmp_seq=3 ttl=63 time=0.692 ms
64 bytes from 22.22.22.22: icmp_seq=4 ttl=63 time=0.597 ms
切换回 55.55.55.55 IP 地址,再次拒绝 ICMP 回复。
路线
我正在思考几个方向,但仍然没有找到答案:
- 邻居机器的硬件地址列在某处并与 IP 地址相关联,从而阻止数据包路由到正确的位置
- arp 缓存值特雷什1,特雷什2和特雷什3没有正确设置,导致 iproute2 的垃圾收集无法清理注册表 - 从而导致 arp 缓存被替换
- 与路由相关的一些内核功能会转储数据包,造成主机和客户机之间的混淆