其他分享
首页 > 其他分享> > 为何ARP请求非本地地址?

为何ARP请求非本地地址?

作者:互联网

我有一个带有2个NIC的Linux虚拟服务器.

eth0 <IP1>
eth1 <IP2>

打开arp_filter并将rp_filter设置为2(宽松模式).
策略路由配置如下:

table T1
default via <GW> dev eth0 src <IP1>
127.0.0.0/8 dev lo
<LAN> dev eth0 src <IP1>

table T2
default via <GW> dev eth1 src <IP2>
127.0.0.0/8 dev lo
<LAN> dev eth1 src <IP2>

ip rule add from <IP1> table T1
ip rule add from <IP2> table T2

之后,我可以ping通两个< IP1>的绑定浮动IP. < IP2>从外面.但是ping -I eth1< some_domain>没用. tcpdump显示,当我从eth1 ping到外部时,Linux直接询问外部地址的MAC,这是不正确的,因为它们不在同一LAN中.

这是tcpdump数据:

root@rm-2:~# tcpdump -i eth1 arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol     decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535     bytes
17:53:08.696191 ARP, Request who-has 172.30.250.119 tell 172.30.248.2, length 46
17:53:08.728482 ARP, Request who-has 172.30.251.144 tell 172.30.251.138, length 46
17:53:09.447252 ARP, Request who-has 61.135.169.125 tell 172.30.251.43, length 28
17:53:09.551514 ARP, Request who-has 172.30.250.127 tell 172.30.248.2, length 46
17:53:09.698076 ARP, Request who-has 172.30.250.119 tell 172.30.248.2, length 46
17:53:09.859046 ARP, Request who-has 172.30.248.246 tell 172.30.248.245, length 46
17:53:10.446009 ARP, Request who-has 61.135.169.125 tell 172.30.251.43, length 28
17:53:10.477104 ARP, Request who-has 172.30.250.128 tell 172.30.248.2, length 46

如您所见,61.135.169.125是一个外部地址,这是错误还是什么?

编辑
路由的输出:// GW为172.30.248.1

Destination     Gateway         Genmask         Flags Metric Ref    Use      Iface  
default         172.30.248.1    0.0.0.0         UG    0      0        0      eth0

解决方法:

回答:

除了ping之外,还需要添加输出接口规则(ip rule add oif …),因为ping绑定到接口,而不是IP.

例:

ip rule add from <IP1> table T1
ip rule add oif <eth0> table T1
ip rule add from <IP2> table T2
ip rule add oif <eth1> table T2

说明:

您问题中的ping示例是使用接口作为源(ping -I eth1< some domain>),它没有任何匹配的策略路由.因此,如果完全没有为该接口定义路由,则ping的行为将完全相同.

要测试/证明的示例(不带策略路由就开始):

使用我的电话USB电缆作为备用路由,我具有以下基本配置.

Linux desktop:
$ip addr show usb0
...
inet 192.168.42.1/32 ...
..

Android phone:
$ip addr show rndis0
...
inet 192.168.42.129/24 ...
...

由于为桌面usb0接口分配了/ 32地址,因此,如果我尝试ping 192.168.42.129 -I 192.168.42.1,它将失败,因为没有为该地址定义路由,并且该路由不在usb0的广播域内地址.但是,使用ping 192.168.42.129 -I usb0-我告诉ping使用接口本身,并且没有与接口匹配的路由(因此,没有广播域的概念),因此它将盲目地触发ARP请求任何不是它自己的IP.

让我们尝试使用接口(无路由)执行ping操作.即使它不在同一广播域内,这也会导致ARP请求发生:

desktop$ping 192.168.42.129 -I usb0
phone# tcpdump -i rndis0 -n icmp or arp
ARP, Request who-has 192.168.42.129 tell 192.168.42.1, length 28
ARP, Reply 192.168.42.129 is-at 3e:04:37:23:05:0e, length 28
IP 192.168.42.1 > 192.168.42.129: ICMP echo request, id 24641, seq 1, length 64
IP 192.168.42.129 > 192.168.42.1: ICMP echo reply, id 24641, seq 1, length 64

使用该接口的源IP(无路由),它不会发出ARP请求,因为该源不在广播域内:

desktop$ping 192.168.42.129 -I 192.168.42.1
phone# tcpdump -i rndis0 -n icmp or arp
... nothing comes over the wire, as expected ...

现在,如果我通过接口添加到主机的路由,则ping知道它可以对192.168.42.129地址发出ARP请求:

desktop$ip route add 192.168.42.129/32 dev usb0
desktop$ping 192.168.42.129 -I 192.168.42.1
phone# tcpdump -i rndis0 -n icmp or arp
ARP, Request who-has 192.168.42.129 tell 192.168.42.1, length 28
ARP, Reply 192.168.42.129 is-at 3e:04:37:23:05:0e, length 28
IP 192.168.42.1 > 192.168.42.129: ICMP echo request, id 24667, seq 1, length 64
IP 192.168.42.129 > 192.168.42.1: ICMP echo reply, id 24667, seq 1, length 64

因此,当我尝试对网络外的内容执行ping操作时,同样的概念也适用.如果我使用该接口作为源对8.8.8.8进行ping操作,它将在没有任何匹配路由的情况下盲目发出ARP请求:

desktop$ping 8.8.8.8 -I usb0
phone# tcpdump -i rndis0 -n icmp or arp
ARP, Request who-has 8.8.8.8 tell 192.168.42.1, length 28

使用接口地址时,路由表中缺少任何类型的下一跳路由都会导致其失败,并且不会发出ARP请求:

desktop$ping 8.8.8.8 -I 192.168.42.1
phone# tcpdump -i rndis0 -n icmp or arp
... nothing ...

因此,让我们为192.168.42.1地址添加策略路由(使用“来自…的IP规则”),以将192.168.42.129作为下一跳默认值,方法与您的问题示例相同:

desktop$sudo ip rule add from 192.168.42.1 lookup T1
desktop$sudo ip route add default via 192.168.42.129 dev usb0 table T1
desktop$ping 8.8.8.8 -I 192.168.42.1
PING 8.8.8.8 (8.8.8.8) from 192.168.42.1 : 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=28.6 ms
...
phone# tcpdump -i rndis0 -n icmp or arp
IP 192.168.42.1 > 8.8.8.8: ICMP echo request, id 24969, seq 1, length 64
IP 8.8.8.8 > 192.168.42.1: ICMP echo reply, id 24969, seq 1, length 64

之所以有效,是因为我们使用的是地址,它正确地匹配了ip规则.

现在,我们使用界面再次尝试相同的ping操作:

desktop$ping 8.8.8.8 -I usb0
PING 8.8.8.8 (8.8.8.8) from 192.168.42.1 usb0: 56(84) bytes of data.
^C
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
...
phone# tcpdump -i rndis0 -n icmp or arp
ARP, Request who-has 8.8.8.8 tell 192.168.42.1, length 28

它失败;下一跳没有接口路由,因此它将再次发出ARP请求,该请求永远不会得到答复.因此,我们需要为接口添加一条IP规则,以将192.168.42.129用作下一跳:

desktop$sudo ip rule add oif usb0 lookup T1
desktop$ping 8.8.8.8 -I usb0
PING 8.8.8.8 (8.8.8.8) from 192.168.42.1 usb0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=10.7 ms

--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 10.791/10.791/10.791/0.000 ms
...
phone# tcpdump -i rndis0 -n icmp or arp
IP 192.168.42.1 > 8.8.8.8: ICMP echo request, id 24979, seq 1, length 64
IP 8.8.8.8 > 192.168.42.1: ICMP echo reply, id 24979, seq 1, length 64

我相信,一般而言,缺少接口路由不会对您的常规非接口绑定输出连接的实现产生负面影响.大多数(不是全部)应用程序都绑定到出站TCP / UDP连接的地址,而只绑定到传入连接的接口(侦听). ping实用程序是一种特殊情况.

为了证明这一点,如果我从路由策略中删除接口规则,则在指定绑定地址时仍可以使用普通的出站套接字.在下面的示例中,我使用telnet和netcat,在两种情况下都指定了绑定地址(-b 192.168.42.1),并且它正确匹配了T1表,因此使用了网关.

# remove the interface route, keep the address route
desktop$sudo ip rule del from all oif usb0 lookup T1
desktop$nc -zv 8.8.8.8 443 -s 192.168.42.1
google-public-dns-a.google.com [8.8.8.8] 443 (https) open

phone# tcpdump -i rndis0 -n host 8.8.8.8
IP 192.168.42.1.40785 > 8.8.8.8.443: Flags [S], seq 1678217252, win 29200, options [mss 1460,sackOK,TS val 20223895 ecr 0,nop,wscale 6], length 0
IP 8.8.8.8.443 > 192.168.42.1.40785: Flags [S.], seq 86178051, ack 1678217253, win 28400, options [mss 1432,sackOK,TS val 1937335284 ecr 20223895,nop,wscale 8], length 0
....
desktop$telnet 8.8.8.8 53 -b 192.168.42.1
...
phone# tcpdump -i rndis0 -n host 8.8.8.8
IP 192.168.42.1.57109 > 8.8.8.8.53: Flags [.], ack 1, win 457, options [nop,nop,TS val 20288983 ecr 4154032957], length 0
IP 8.8.8.8.53 > 192.168.42.1.57109: Flags [F.], seq 1, ack 1, win 111, options [nop,nop,TS val 4154033968 ecr 20288983], length 0

我在测试策略路由实现时遇到了同样的问题,这使我有些犹豫,为什么我的接口ping无法得到答复.希望这可以清除它.

标签:tcp-ip,arp,linux
来源: https://codeday.me/bug/20191028/1949850.html