我有一台电脑(内核3.2.0-23-通用)已192.168.1.2/24
配置为eth0
接口,并且还使用接口的192.168.1.1
地址:192.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:~#
只有在删除tun0
接口( 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:~#
这是预期的行为吗?为什么内核忽略路由表?
答案1
确切地说,您的路由表并没有被忽略。它被更高优先级的路由表推翻。
这是怎么回事
您键入时看到的路由表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
表中找到了一条路线,因此我们不再搜索路线,也不再费心检查main
或default
表。
为什么要多表?
至少,能够打字ip route
并且不会看到所有那些“明显”的路线杂乱地显示是件好事(尝试route print
在 Windows 机器上打字)。它还可以作为一些针对错误配置的最小保护:即使主路由表已经混淆,内核仍然知道如何与自身对话。
(为什么首先要保留本地路由?因此内核可以使用与其他所有内容相同的查找代码来查找本地地址。这使内部的事情变得更简单。)
使用这个多表方案还可以做其他有趣的事情。特别是,您可以添加自己的表,并指定搜索它们的规则。这称为“策略路由”,如果您曾经想根据数据包的路由来路由数据包来源地址,这就是在 Linux 中的操作方法。
如果您正在做特别棘手或实验性的事情,您可以通过在命令中local
指定来自行添加或删除路由。但是,除非您知道自己在做什么,否则很可能会混淆内核。当然,内核仍然会继续添加和删除自己的路由,因此您必须注意确保您的路由不会被覆盖。table local
ip route
最后,如果您想一次查看所有路由表:
# ip route show table all
欲了解更多信息,请查看ip-rule(8)
手册页或iproute2 文档。您也可以尝试高级路由和流量控制 HOWTO有关您可以做什么的一些示例。
答案2
你的反向路径过滤配置可能是问题。RFC3704- 第 2.4 节
在企业 Linux 发行版(RHEL、CentOS、Scientific Linux 等)中,解决此问题的最佳方法可能是/etc/sysctl.conf
修改rp_filter = 2
当 RHEL 配置了多个 IP 时,只能从远程网络访问一个 IP。或者,当出站流量的路由与传入流量的路由不同时,为什么 RHEL 会忽略数据包?