ARP协议返回IP并不匹配的MAC地址?
在一个多网卡的计算机中(Linux),假设网卡为 A
和 B
同时联入同一个子网,每个网卡具有唯一的 MAC 地址(MAC_A
和 MAC_B
)和 IP 地址(IP_A
和IP_B
)。
当同一子网的主机发起 ARP 请求,询问IP_A
的MAC是谁的时候,这个主机该如何应答?
按照正常情况应该是返回MAC_A
是吧,但是可能事实并不是这样。
实验1:
主机有两个网卡:
1
2
3
4
5
6
7
8
9
10
11
enp2s0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
inet 192.168.2.125 netmask 255.255.255.0 broadcast 192.168.2.255
ether fc:aa:14:5b:48:8c txqueuelen 1000 (以太网)
.....
enp4s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.2.174 netmask 255.255.255.0 broadcast 192.168.2.255
inet6 fe80::c62f:6221:bb0:5bba prefixlen 64 scopeid 0x20<link>
ether 08:1f:71:0b:36:71 txqueuelen 1000 (以太网)
......路由表如下:
1
2
30.0.0.0 192.168.2.1 0.0.0.0 UG 0 0 0 enp2s0
0.0.0.0 192.168.2.1 0.0.0.0 UG 100 0 0 enp4s0
192.168.2.0 0.0.0.0 255.255.255.0 U 100 0 0 enp4s0注意子网的网段 为
192.168.2.0/24
, 并且所有包仅通过enp4s0
。此时另一个主机
192.168.2.112
发起ping 192.168.2.125
(125 的 IP 分配给了enp2s0
,参考上面打印的信息👆)
首先112
的主机会发起 ARP 请求,按照理论应该是返回enp2s0
的mac
:fc:aa:14:5b:48:8c
.
但是通过抓包发现1
2
3
4
5└[~]> tcpdump arp -i enp7s0 and '(src 192.168.2.125 or dst 192.168.2.125)' -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:21:34.968758 ARP, Request who-has 192.168.2.125 tell 192.168.2.112, length 28
21:21:34.968906 ARP, Reply 192.168.2.125 is-at 08:1f:71:0b:36:71, length 46可以看出
112
的 ARP 请求125
的MAC地址,接收到了08:1f:71:0b:36:71
,此MAC地址正是enp4s0
,而非期望的enp2s0
。
原因
其实这是一个正常并且正确的现象,注意在路由表中,我们设置了子网的所有 IP 通信都是通过 enp4s0
的,所以返回enp4s0
的 MAC 地址,更加“符合”我们的设置,也提高了通信的成功率。也就是说默认情况下,ARP
如何返回 MAC 地址是根据路由表情况决定的。
那如何改变这一规则让其返回 “正确”(和 IP匹配)的 MAC 地址呢?答案是修改 arp_filter 参数。
arp_filter - BOOLEAN
1 - Allows you to have multiple network interfaces on the same
subnet, and have the ARPs for each interface be answered
based on whether or not the kernel would route a packet from
the ARP’d IP out that interface (therefore you must use source
based routing for this to work). In other words it allows control
of which cards (usually 1) will respond to an arp request.
—
0 - (default) The kernel can respond to arp requests with addresses
from other interfaces. This may seem wrong but it usually makes
sense, because it increases the chance of successful communication.
IP addresses are owned by the complete host on Linux, not by
particular interfaces. Only for more complex setups like load-
balancing, does this behaviour cause problems.
默认情况下设置为 0, 所以想要恢复“正确”的行为只需要修改为 1 即可。如何修改请参考 Preventing incorrect ARP entries。
实验2
为了验证上面的说法,我们试着改变路由表规则,重新重复实验1
。
增加路由表,让
192.168.2.112
的路由通过enp2s0
:1
ip route add 192.168.2.112 dev enp2s0
此时路由表增加一条到
192.168.2.112
的规则:1
2
3
4
5
6内核 IP 路由表
目标 网关 子网掩码 标志 跃点 引用 使用 接口
0.0.0.0 192.168.2.1 0.0.0.0 UG 0 0 0 enp2s0
0.0.0.0 192.168.2.1 0.0.0.0 UG 20100 0 0 enp4s0
192.168.2.0 0.0.0.0 255.255.255.0 U 100 0 0 enp4s0
192.168.2.112 0.0.0.0 255.255.255.255 UH 0 0 0 enp2s0由
192.168.2.112
发起ping 192.168.2.125
, 并查看 ARP 协议包:1
2
3
4
5└[~]> sudo tcpdump arp -i enp7s0 and '(src 192.168.2.125 or dst 192.168.2.125)' -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp7s0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:44:12.289258 ARP, Request who-has 192.168.2.125 tell 192.168.2.112, length 28
21:44:12.289406 ARP, Reply 192.168.2.125 is-at fc:aa:14:5b:48:8c, length 46正确返回了
enp2s0
的 MAC 地址fc:aa:14:5b:48:8c
。
建议保持默认配置,非必要请不要修改网络参数
参考:
[1]. Unix & Linux Stack Exchange. 《sysctl parameter for correct ARP response》. 见于 2021年4月14日. https://unix.stackexchange.com/questions/31096/sysctl-parameter-for-correct-arp-response.
[2]. Server Fault. 《ethernet - Multi-NIC Linux machine’s NICs are responding to each other’s ARPs regardless of arp_filter setting》. 见于 2021年4月14日. https://serverfault.com/questions/314522/multi-nic-linux-machines-nics-are-responding-to-each-others-arps-regardless-of.
[3]. Server Fault. 《linux - Adding a route to specific host go out a specific interface》. 见于 2021年4月14日. https://serverfault.com/questions/466152/adding-a-route-to-specific-host-go-out-a-specific-interface.
[4]. ip-sysctl. 《IBM Docs》, 2014年10月24日. https://www.ibm.com/docs/en/linux-on-systems.
[5].《ip-sysctl》. 见于 2021年4月14日. https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt.
Author: DongSheng
Link: http://ehds.github.io/2021/04/14/arp-return-not-match-ip/
License: 知识共享署名-非商业性使用 4.0 国际许可协议