我的 Linux 服务器是一台连接了 1 个 nic(带有 ip 192.168.20.43
)的虚拟机,使用以下ip a
命令进行观察:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:f5:e5:67 brd ff:ff:ff:ff:ff:ff
inet 192.168.20.43/24 brd 192.168.20.255 scope global noprefixroute enp1s0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fef5:e567/64 scope link noprefixroute
valid_lft forever preferred_lft forever
其默认网关192.168.20.254
如下ip route
命令观察:
default via 192.168.20.254 dev enp1s0 proto static metric 100
192.168.20.0/24 dev enp1s0 proto kernel scope link src 192.168.20.43 metric 100
从上面我们还可以看出,网络掩码是合理的24位。
由此我们可以看出 IPv4 地址192.168.30.66
是外部定义的子网,因此只能通过默认网关访问。
那么为什么我可以在请求来自的流量时使用on并tcpdump
观察enp1s0
来自的 arp 请求?192.168.20.43
192.168.30.66
192.168.30.66
tcpdump 命令如下tcpdump -nnni enp1s0 host 192.168.30.66
,我们观察到:
11:54:53.130897 IP 192.168.30.66.443 > 192.168.20.43.40862: Flags [.], seq 12922:14320, ack 917, win 227, options [nop,nop,TS val 3119187172 ecr 2528097971], length 1398
11:54:53.131013 IP 192.168.20.43.40862 > 192.168.30.66.443: Flags [.], ack 37962, win 835, options [nop,nop,TS val 2528101021 ecr 3119184135,nop,nop,sack 1 {12922:14320}], length 0
11:54:55.247778 ARP, Request who-has 192.168.30.66 tell 192.168.20.43, length 28
11:54:55.248505 ARP, Reply 192.168.30.66 is-at e0:db:55:70:db:75, length 46
我的印象是,不应对子网外的 IP 地址发出 ARP 请求,不管两个子网是否位于同一个第 2 层以太网段(这就是发生回复的原因)。
答案1
原因在于路由器。但是OPtcpdump的过滤器错过了要捕获的相关数据包:ICMP 重定向来自路由器,告诉每台主机它可以直接访问另一台主机。
由于路由器是单臂路由器,其在同一接口上具有 IP LAN 192.168.20.0/24 和 192.168.30.0/24,因此具有相同的以太网广播域,因此它正确推断出从使用 192.168.20.0/24 的主机到使用 192.168.30.0/24 的对等端的 IPv4 通信可以直接完成,不需要路由器工作。
考虑如下配置的Linux路由器:
# ip route
default via 192.0.2.1 dev wan0 metric 100
192.0.2.0/24 dev wan0 proto kernel scope link src 192.0.2.2 metric 100
192.168.20.0/24 dev eth0 proto kernel scope link src 192.168.20.254 metric 100
192.168.30.0/24 dev eth0 proto kernel scope link src 192.168.30.254 metric 100
当两台主机之间通过路由器进行此类通信时,它会以缓慢的速率发送如下 ICMP 重定向:
17:35:35.317159 IP 192.168.30.254 > 192.168.30.66: ICMP redirect 192.168.20.43 to host 192.168.20.43, length 92
17:35:36.329965 IP 192.168.20.254 > 192.168.20.43: ICMP redirect 192.168.30.66 to host 192.168.30.66, length 92
当对等端收到此类信息时,它们将(懒惰地,可能在收到多个 ICMP 重定向后)安装临时路由缓存以覆盖正常路由(即使正常路由缓存在 Linux 3.6 中已经消失,特殊用途的路由缓存(如重定向或 PMTUD 相关路由)仍然存在)。可以这样找到它(在 192.168.20.43 主机上运行它后已收到多个 ICMP 重定向):
# ip route show cache
192.168.30.66 via 192.168.30.66 dev eth0
cache <redirected> expires 296sec
然后它只需按照这条路由,触发对 192.168.30.66 的 ARP 请求即可到达该主机。