为什么 ping 响应被发送到错误的网关?

为什么 ping 响应被发送到错误的网关?

在之前的问题,我试图确定为什么我的 OpenVPN 客户端无法 ping 通服务器 LAN,即使服务器 LAN 可以 ping 通客户端。

经过进一步调查,我确定,至少在其中一个服务器的情况下,问题是由于内核决定将包含 ping 回复的以太网帧转发到不知道如何路由数据包的 MAC 地址的方向而引起的。

例如:

10.11.11.7 de:ad:be:7f:45:72 
10.11.11.1 00:10:db:ff:70:01
10.11.11.2 de:ad:be:3b:24:48 

从 10.11.11.7 到 10.8.0.10 的 ping 操作成功。从 10.8.0.10 到 10.11.11.7 的 ping 请求按预期到达,但回复始终未到达 10.8.0.10,显然是因为回复被路由到 10.11.11.1 方向,而不是 10.11.11.2,后者包含可路由到 10.8.0.0/24 的 VPN 服务器。

例如:

当我尝试从 10.11.11.7 ping 10.8.0.10 时,请求从包含 10.11.11.2 的接口离开,该接口包含可以到达 10.8.0.10 的 VPN 网关。

01:46:39.973670 de:ad:be:7f:45:72 > de:ad:be:3b:24:48, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl  64, id 0, offset 0, flags [DF], proto: ICMP (1), length: 84) 10.11.11.7 > 10.8.0.10: ICMP echo request, id 49247, seq 6, length 64
0x0000:  4500 0054 0000 4000 4001 1b86 0a0b 0b07  E..T..@.@.......
0x0010:  0a08 000a 0800 37a4 c05f 0006 7ff8 5f4f  ......7.._...._O
0x0020:  0000 0000 53db 0e00 0000 0000 1011 1213  ....S...........
0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
0x0050:  3435 3637                                4567

预期的响应通过反向路径到达......

01:46:40.145368 de:ad:be:3b:24:48 > de:ad:be:7f:45:72, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl  63, id 53200, offset 0, flags [none], proto: ICMP (1), length: 84) 10.8.0.10 > 10.11.11.7: ICMP echo reply, id 49247, seq 6, length 64
0x0000:  4500 0054 cfd0 0000 3f01 8cb5 0a08 000a  E..T....?.......
0x0010:  0a0b 0b07 0000 3fa4 c05f 0006 7ff8 5f4f  ......?.._...._O
0x0020:  0000 0000 53db 0e00 0000 0000 1011 1213  ....S...........
0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
0x0050:  3435 3637                                4567

另一方面,当 10.8.0.10 ping 10.11.11.7 时,在预期接口上收到 ping 请求:

01:46:11.734359 de:ad:be:3b:24:48 > de:ad:be:7f:45:72, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl  63, id 0, offset 0, flags [DF], proto: ICMP (1), length: 84) 10.8.0.10 > 10.11.11.7: ICMP echo request, id 15635, seq 74, length 64
0x0000:  4500 0054 0000 4000 3f01 1c86 0a08 000a  E..T..@.?.......
0x0010:  0a0b 0b07 0800 c1ff 3d13 004a 65f8 5f4f  ........=..Je._O
0x0020:  0000 0000 7088 0400 0000 0000 1011 1213  ....p...........
0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
0x0050:  3435 3637                                4567

但它朝 10.11.11.1 方向离开,而不是 10.11.11.2:

01:46:11.734383 de:ad:be:7f:45:72 > 00:10:db:ff:70:01, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl  64, id 41757, offset 0, flags [none], proto: ICMP (1), length: 84) 10.11.11.7 > 10.8.0.10: ICMP echo reply, id 15635, seq 74, length 64
0x0000:  4500 0054 a31d 0000 4001 b868 0a0b 0b07  [email protected]....
0x0010:  0a08 000a 0000 c9ff 3d13 004a 65f8 5f4f  ........=..Je._O
0x0020:  0000 0000 7088 0400 0000 0000 1011 1213  ....p...........
0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223  .............!"#
0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233  $%&'()*+,-./0123
0x0050:  3435 3637                                4567

这是意料之外的,因为 10.11.11.7 上的路由表配置如下:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.11.11.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
10.8.0.0        10.11.11.2     255.255.255.0   UG    0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     0      0        0 eth0
0.0.0.0         10.11.11.2     0.0.0.0         UG    0      0        0 eth0

所以,我的问题是:为什么内核向 10.11.11.1 方向发送 ping 响应,即使网关定义为 10.11.11.2?

更新:

通过使用 10.11.11.1 的 mac 地址污染 10.11.11.7 中的 arp 缓存,该缓存实际上指向 10.11.11.2,例如:

sudo /sbin/arp -s 10.11.11.1 de:ad:be:3b:24:48

我能够按预期使从 10.8.0.10 到 10.11.11.7 的 ping 工作正常。

显然,这只是为了演示。为什么我的内核一开始就选择了错误的目标 MAC 地址?

更新 2:

根据 lsmod 显示网络驱动可能是:

virtio_net             48449  0 

这可能表明虚拟机正在 KVM 下运行。

更新 3:

ptman 建议在他的回答回答我的另一个问题。

谢谢你,ptman!

答案1

ptman 建议在回答我的问题时考虑策略和基于源的路由,以此来回答这个问题。

简而言之,问题是由适配器特定的默认静态路由引起的,该路由在主路由表(使用 /sbin/route 显示的规则)中的任何规则之前被解释。

此默认路由拦截并转移发往 10.8.0.0/24 的数据包,并将其定向到 10.11.11.1,而不是预定的 10.11.11.2 跳。因此,本应将这些数据包转移到 10.11.11.2 的规则从未被执行。

造成这种混淆的部分原因是 /sbin/route 没有显示适配器特定的静态路由。请注意此类路由,并熟悉以下内容:/sbin/ip 规则/sbin/ip 路由列表表全部

相关内容