如果请求的IP地址与另一个(禁用的)接口相关联,Linux不会回复ARP请求消息


9

我有一台PC(内核3.2.0-23-generic),它已192.168.1.2/24配置为eth0接口,并且还使用接口的地址192.168.1.1192.168.1.2地址tun0

root@T42:~# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:16:41:54:01:93 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 scope global eth0
    inet6 fe80::216:41ff:fe54:193/64 scope link
       valid_lft forever preferred_lft forever
3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN
    link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
4: irda0: <NOARP> mtu 2048 qdisc noop state DOWN qlen 8
    link/irda 00:00:00:00 brd ff:ff:ff:ff
5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:13:ce:8b:99:3e brd ff:ff:ff:ff:ff:ff
    inet 10.30.51.53/24 brd 10.30.51.255 scope global eth1
    inet6 fe80::213:ceff:fe8b:993e/64 scope link
       valid_lft forever preferred_lft forever
6: tun0: <POINTOPOINT,MULTICAST,NOARP> mtu 1500 qdisc pfifo_fast state DOWN qlen 100
    link/none
    inet 192.168.1.1 peer 192.168.1.2/32 scope global tun0
root@T42:~# ip route show dev eth0
192.168.1.0/24  proto kernel  scope link  src 192.168.1.2 
root@T42:~# 

如上所示,tun0在管理上被禁用(ip link set dev tun0 down)。现在,当我收到的ARP请求时192.168.1.2,PC不会回复这些请求:

root@T42:~# tcpdump -nei eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
15:30:34.875427 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:36.875268 00:1a:e2:ae:cb:b7 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 60: Request who-has 192.168.1.2 tell 192.168.1.1, length 46
15:30:39.138651 00:1a:e2:ae:cb:b7 > 00:1a:e2:ae:cb:b7, ethertype Loopback (0x9000), length 60:
^C
3 packets captured
3 packets received by filter
0 packets dropped by kernel
root@T42:~#

只有删除了tun0interface(ip link del dev tun0)之后,PC才会回复接口192.168.1.2上的ARP请求eth0

路由表之前和之后看起来完全一样ip link del dev tun0

root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# ip link del dev tun0
root@T42:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         10.30.51.254    0.0.0.0         UG        0 0          0 eth1
10.30.51.0      0.0.0.0         255.255.255.0   U         0 0          0 eth1
192.168.1.0     192.168.1.2     255.255.255.0   UG        0 0          0 eth0
root@T42:~# 

下面的路由条目已通过ip link set dev tun0 down命令删除:

Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.1.2     0.0.0.0         255.255.255.255 UH        0 0          0 tun0

但是,尽管路由表在ip link del dev tun0命令前后完全相同,但是内核将做出的实际路由决策不是:

T42:~# ip route get 192.168.1.1
local 192.168.1.1 dev lo  src 192.168.1.1 
    cache <local> 
T42:~# ip link del dev tun0
T42:~# ip route get 192.168.1.1
192.168.1.1 dev eth0  src 192.168.1.2 
    cache  ipid 0x8390
T42:~# 

这是预期的行为吗?为什么内核会忽略路由表?


两种情况下都可以粘贴netstat -rn的输出吗?路由表通常是查找此类错误的第一位。
Clarus

@Claris我更新了最初的帖子。
马丁

在两个接口上使用相同的IP可能会造成问题,最好避免这种情况,也就是说,您应该能够找出问题所在。下一步是查看arp缓存,arp -a是否显示有用的东西?
Clarus

@Claris看起来根本原因tun0是禁用接口但存在接口时内核会忽略路由表。请参阅ip route get我更新的初始文章中的命令输出。但是,为什么内核会这样?
马丁

Answers:


17

路由表确实不会被忽略。它被更高优先级的路由表所取代。

这是怎么回事

键入时看到的路由表ip route show不是内核使用的唯一路由表。实际上,默认情况下有三个路由表,并且按照命令显示的顺序搜索它们ip rule

# ip rule show
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

您最熟悉的表是main,但是优先级最高的路由表是local。该表由内核管理以跟踪本地和广播路由:换句话说,该local表告诉内核如何路由到其自己的接口的地址。看起来像这样:

# ip route show table local
broadcast 127.0.0.0 dev lo  proto kernel  scope link  src 127.0.0.1
local 127.0.0.0/8 dev lo  proto kernel  scope host  src 127.0.0.1
local 127.0.0.1 dev lo  proto kernel  scope host  src 127.0.0.1
broadcast 127.255.255.255 dev lo  proto kernel  scope link  src 127.0.0.1
broadcast 192.168.1.0 dev eth0  proto kernel  scope link  src 192.168.1.2
local 192.168.1.1 dev tun0  proto kernel  scope host  src 192.168.1.1
local 192.168.1.2 dev eth0  proto kernel  scope host  src 192.168.1.2
broadcast 192.168.1.255 dev eth0  proto kernel  scope link  src 192.168.1.2

查看该行引用tun0。这就是造成您来自的奇怪结果的原因route get。它说192.168.1.1是一个本地地址,这意味着如果我们要向192.168.1.1发送ARP回复,就很容​​易了。我们将其发送给自己。而且,由于我们在local表中找到了一条路线,因此我们不再搜索路线,也不必费心检查mainor default表。

为什么要多个表?

至少,能够键入ip route而不看到所有那些“明显的”路由使显示混乱(最好route print在Windows计算机上键入)是一件很不错的事情。它也可以作为防止配置错误的最低限度保护措施:即使主路由表混淆了,内核仍然知道如何与自己对话。

(为什么首先要保留本地路由?所以内核可以对本地地址使用与对其他所有地址相同的查找代码。这使内部处理变得简单。)

您可以使用此多表方案执行其他有趣的操作。特别是,您可以添加自己的表,并指定搜索规则。这称为“策略路由”,如果您曾经想根据数据包的地址来路由数据包,这就是在Linux中的处理方法。

如果您正在做特别棘手或实验性的事情,则可以local通过table localip route命令中指定自己添加或删除路由。但是,除非您知道自己在做什么,否则很可能会混淆内核。当然,内核仍然会继续添加和删除其自己的路由,因此您必须注意确保不会被覆盖。

最后,如果您想一次查看所有路由表:

# ip route show table all

有关更多信息,请查看ip-rule(8)手册页或iproute2文档。您也可以尝试“ 高级路由和流量控制” HOWTO,以获取有关您可以执行的操作的一些示例。


谢谢!之后,ip link set dev tun0 downlocal 192.168.1.1 dev tun0 proto kernel scope host src 192.168.1.1规则确实仍然存在于local路由表中。执行ip link del dev tun0完上述规则后,该规则即被删除。还有一个问题-我是否纠正所有现代Linux内核(2.6.x,3.x,4.x)都使用RPDB进行路由查找,从而使用多个表的情况?
马丁

2
是的,您是正确的,还有更多。RPDB太老了! “ RPDB本身是在Linux内核2.2中重写网络堆栈的组成部分。” 摘自ip(8):“ ip由Alexey N. Kuznetsof编写,并在Linux 2.2中添加。”
詹德(Jander)2015年

这是我见过的多个内核路由表的最佳解释之一。谢谢!
djluko

1

您的反向路径过滤配置可能是问题所在。RFC3704-第2.4节

在Enterprise Linux发行版(RHEL,CentOS,Scientific Linux等)中,解决此问题的最佳方法是/etc/sysctl.conf使用rp_filter = 2

当RHEL配置了多个IP时,从远程网络只能访问一个IP。还是当出站流量的路由与传入流量的路由不同时,为什么RHEL会忽略数据包?


如果我使用宽松的RPF检查(2)甚至完全禁用RPF检查(0),for rp_filter_file in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > "$rp_filter_file"; done则内核将不会使用该eth0接口将数据包路由到192.168.1.1。仅当我删除tun0带有ip link del dev tun0内核的接口后,才开始使用该eth0接口。
马丁
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.