为什么 ARP 请求非本地地址?

2024-03-16

我有一个带有 2 个网卡的 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都绑定了 floatips<IP1> and <IP2>从外面。然而ping -I eth1 <some_domain>不起作用。tcpdump显示当我从eth1到外面,Linux直接询问MAC外部地址,这是不正确的,因为它们不在同一地址LAN.

Here is tcpdump data:

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是一个国外地址,这是一个错误还是什么?

EDIT
输出route: // 172.30.248.1 是GW

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

Answer:

您需要添加输出接口规则(ip rule add oif ...) 此外ip rule add from ...,因为 ping 绑定到界面,而不是IP。

Example:

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 的行为与没有为该地址定义路由时的情况完全相同界面 at all.

测试/证明示例(在没有策略路由的情况下开始):

使用我的手机 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 的广播域内address。然而,随着ping 192.168.42.129 -I usb0-- 我告诉 ping 使用界面本身,并且没有与该接口匹配的路由(因此,没有广播域的概念),因此它会盲目地对任何不属于自己的IP触发ARP请求。

让我们尝试使用以下命令进行 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 网络外的某些内容时,同样的概念也适用;如果我使用以下命令 ping 8.8.8.8界面作为源,它会盲目地发出没有任何匹配路由的 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

使用界面时address,路由表中缺少任何类型的下一跳路由都会导致其失败并且无法发出 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

它有效,因为我们正在使用address,它正确匹配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

我相信,一般来说,缺少接口路由不会对正常的、非接口绑定的传出连接的实现产生负面影响。大多数(不是全部)应用程序绑定到address对于出站 TCP/UDP 连接,并且仅绑定到界面用于传入连接(侦听)。 ping 实用程序是一个特例。

为了证明这一点,如果我从路由策略中删除接口规则,在指定绑定时我仍然可以使用正常的出站套接字address。在下面的示例中,我使用 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 没有得到答复。希望这能澄清一切。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 ARP 请求非本地地址? 的相关文章

随机推荐

  • 强制 UIImagePickerController 裁剪方形图像

    我们如何强制 UIImagePickerController 裁剪方形图像 我到处寻找 但没有找到可靠的解决方案 谢谢 var imagePickerController UIImagePickerController UIImagePic
  • 为什么 char 数组必须以空字符结尾?

    为什么 chararray必须以空字符结尾 有什么理由我必须将空字符添加到每个char array 看来他们受到的待遇是一样的 char 数组不必以 null 终止 不依赖于此的标准库函数包括memcpy memmove strncpy 最
  • 数据表删除导出到 pdf 和 excel 时的列

    我在导出到 pdf excel 之前删除列时遇到问题 第二个问题是由于该列 该列的反向部分无法正常工作 这是我使用的代码 document ready function var arrayCol new Array var table ex
  • Python sqlite3在本地成功,但在Github Action上失败

    相同的 python 版本 相同的 sqlite3 版本和相同的文件 但我只是无法传递 Github Action 这是我的 github 操作 https github com CloudAurora Blog blob master g
  • Cassandra (CQL) 中的结果分页

    我想知道如何使用 Cassandra 实现分页 假设我有一个博客 该博客每页最多列出 10 篇帖子 要访问下一篇文章 用户必须单击分页菜单才能访问第 2 页 第 11 20 篇文章 第 3 页 第 21 30 篇文章 等 在 MySQL 下
  • 创建ECDSA公钥给定曲线和公共点?

    我正在努力从公钥的字符串表示形式创建 ECDSA 公钥 即 string devicePublicKey 86FB5EB3CA0507226BE7197058B9EC041D3A3758D9D9C91902ACA3391F4E58AEF13
  • 实现系统管理的ConnectionService

    我想实现此功能以添加来电和对正在进行的通话进行不同的操作 例如保持拒绝等 我已经查看并实施了以下内容 但得到了 致命异常 java lang SecurityException 未为此用户启用此 PhoneAccountHandle And
  • mysql 根据第三个字段的值从两个字段中选择任意一个字段

    我想针对名为 nosale 的字段中的值选择价格或 sale price 其中 price sale price 和 nosale 是产品表的字段 nosale 字段要么为真 要么为假 据此 我想要价格或 sale price 的值 而不是
  • R 中没有从 Zeroinfl 对象预测零?

    我创建了一个零膨胀负二项式模型 并想要研究有多少零被划分为采样零或结构零 我如何在 R 中实现这一点 zeroinfl 页面上的示例代码我不清楚 data bioChemists package pscl fm zinb2 lt zeroi
  • 我如何要求 Hibernate 在外键(JoinColumn)上创建索引?

    这是我的模型 class User CollectionOfElements JoinTable name user type joinColumns JoinColumn name user id Column name type nul
  • 如何使用 Ajax、Json 和 Node.js 刷新表数据

    我使用 Node js 作为服务器端 并使用 Express 和 Twitter Bootstrap 作为前端 该页面有一个带有表单和提交按钮的对话框 该表单是通过 Jquery Ajax 调用提交的 在 Node js 服务器响应后不要重
  • 如何在 Win XP 上查找所有“SVN 工作副本”

    我有Windows XP 我想升级我的TortoiseSVN 至版本 1 7 http tortoisesvn net tsvn 1 7 releasenotes html 为此 我需要确保可以在我的 PC 上找到所有 SVN 工作副本 所
  • 子级的 CSS 缩放变换不影响父级大小

    我有一个太大的组件 我想缩小它 我可以通过缩放变换来做到这一点 但父容器不会缩小以适应 在我的真实代码中 带有 SHRINK ME 类的 div 实际上是一个 Angular 日历组件 但这简化了repo https codepen io
  • VB.Net 中的匿名类初始化

    我想在 vb net 中创建一个匿名类 如下所示 var data new total totalPages page page records totalRecords rows new new id 1 cell new 1 7 Is
  • OpenCV:Flann 匹配器崩溃

    我正在尝试运行一个检测图像中特征的应用程序 但是当我运行以下代码时BRISK特征 BRIEF描述符和FlannBased匹配器 它崩溃并说 OpenCV Error Unsupported format or combination of
  • Mongodb 因地址无效访问而崩溃 - 分段错误信号 11 - 版本 2.6

    我正在尝试在 MongoDB 中插入文档 我当前的版本是 2 6 生产版本 我的应用程序能够插入一些文档 但在某个时间点后开始出现以下错误 我每次都会遇到同样的错误 我正在从 cmd 提示符运行 mongod 我在 2 6 0 rc 和 2
  • 服务器上 GetThumbnailImage 中的 C# 内存不足异常

    当用户向我们发送图像时 我正在运行以下代码来创建缩略图 public int AddThumbnail byte originalImage File parentFile File tnFile null try System Drawi
  • MySQL 查询中省略分号有什么不好吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我最近在 MySQL 查询末尾省略了分号 我想到这可能会在服务器高负载 缓存等情况下产生负面影响 是否有这样的影响 如果系统能够在不使用分号的情
  • 如何在重写方法中表示调用基类方法?

    我有一个子类想要向基类函数添加更多功能 我如何表示它也执行基类函数而不仅仅是新添加的功能 有趣的问题 我用 Enterprise Architect 尝试过 它确实让我选择了父级的操作 但图中的显示没有改变 看来您需要为此使用注释 如你看到
  • 为什么 ARP 请求非本地地址?

    我有一个带有 2 个网卡的 Linux 虚拟服务器 eth0