通过 linux 路由 table Ping 不工作 [或] 这是怎么回事?
Ping via linux routing table not working [OR] how is this expected?
长题简而言之:
Ping over r1-r4-r2
path works using 10.0.1.*
or 10.0.2.*
IP addresses, but fails if we alter the path to r1-r3-r2
using 1.0.0.*
or 1.0.1.*
IP addresses for the exactly same packets (except for the fact that packets' src
and dst
IP fields are changed from 10.*
to 1.*
and vice-versa at s1
and s2
respectively). Why?
问题详细:
我有一个小拓扑如下
h1 -- s1 -- r1 -- r4 -- r2 -- s2 -- h2
\ /
\ /
\ /
r3
s
是 OpenvSwitch 实例,而 r
是 Ubuntu 16 Linux 台机器。
IP 地址是:
h1-eth0 - 10.0.1.10/24
s1 - 10.0.1.50/24
h2-eth0 - 10.0.2.10/24
s2 - 10.0.2.50/24
r1-eth0 - 10.0.1.1/24
r1-eth1 - 10.0.11.2/24
r1-eth2 - 10.0.12.2/24
r2-eth0 - 10.0.2.1/24
r2-eth1 - 10.0.13.1/24
r2-eth2 - 10.0.5.1/24
r3-eth0 - 10.0.12.1/24
r3-eth1 - 10.0.5.2/24
r4-eth0 - 10.0.11.1/24
r4-eth1 - 10.0.13.2/24
可以看到,r1和r2之间有两条相似的路径。我添加以下静态条目。
r1
sudo ip route add 10.0.2.0/24 via 10.0.11.1
r2
sudo ip route add 10.0.1.0/24 via 10.0.13.2
r4
sudo ip route add 10.0.1.0/24 via 10.0.11.2
sudo ip route add 10.0.2.0/24 via 10.0.13.1
h1 和 h2 之间的 ping 正常。现在,由于交换机是 OVS(因此启用了 OpenFlow),我在 s1 中安装条目以 将目标 IP 映射到不同的子网 .
i.e. the IP 10.0.1.10 would be mapped to 1.0.0.10 while the IP 10.0.2.10 would be mapped to 1.0.1.10 when such a packet is received at s1, while the destination IPs would be mapped back to original at s2.
(我检查过这些条目确实正确并且按预期工作。另外我添加此条目只是为了匹配 ICMP 数据包)。当 h1 发送 ping 回复时,将执行类似的过程。
除此之外,我还在路由器中安装了静态路由来路由这些 IP。
r1
sudo ip route add 1.0.0.0/24 via 10.0.1.50
sudo ip route add 1.0.1.0/24 via 10.0.12.1
r2
sudo ip route add 1.0.0.0/24 via 10.0.5.2
sudo ip route add 1.0.1.0/24 via 10.0.2.50
r3
sudo ip route add 1.0.0.0/24 via 10.0.12.2
sudo ip route add 1.0.1.0/24 via 10.0.5.1
现在,如果我从 h2 ping h1,数据包以目标 IP 10.0.1.10 开始,在 s2 映射到 1.0.0.10,r2 路由它并将其发送到 r3,r3 路由它并发送到 r1。 但是 r1,即使在一个接口接收到数据包并在 Linux 路由 table 中具有匹配条目后,也不会路由和转发数据包。
甚至 ip route get
输出数据包应该转发到的正确端口。 ip tables
中也没有防火墙条目。
一些附加信息:
如果我把新添加的路由条目改成使用原来的路径
r1-r4-r2
(即,我们使用映射的 ip 在这条路径上路由),它的行为符合预期并且 ping 按预期工作。
或者,如果我在 r1 和
中更改 10.0.2.0/24 的旧路由条目
r2 中的 10.0.1.0/24(现在理想情况下甚至不必与新的匹配
数据包,因为它们的目标 IP 在 1.0.0.* 范围内或仅在 1.0.1.* 范围内)以使用
新路径 r1-r3-r4
以及此映射的 IP 数据包,之间的 ping
r2 和 r1 按预期工作。
可能需要的详细信息:
最终路由table如下:
r1
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.11.1 0.0.0.0 UG 0 0 0 eth1
1.0.0.0 10.0.1.10 255.255.255.0 UG 0 0 0 eth0
1.0.1.0 10.0.12.1 255.255.255.0 UG 0 0 0 eth2
10.0.1.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
10.0.2.0 10.0.11.1 255.255.255.0 UG 0 0 0 eth1
10.0.11.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
10.0.12.0 0.0.0.0 255.255.255.0 U 1 0 0 eth2
r2
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.13.2 0.0.0.0 UG 0 0 0 eth1
1.0.0.0 10.0.5.2 255.255.255.0 UG 0 0 0 eth1
1.0.1.0 10.0.2.50 255.255.255.0 UG 0 0 0 eth0
10.0.1.0 10.0.13.2 255.255.255.0 UG 0 0 0 eth1
10.0.2.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
10.0.5.0 0.0.0.0 255.255.255.0 U 1 0 0 eth2
10.0.13.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
r3
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.5.1 0.0.0.0 UG 0 0 0 eth1
1.0.0.0 10.0.12.2 255.255.255.0 UG 0 0 0 eth0
1.0.1.0 10.0.5.1 255.255.255.0 UG 0 0 0 eth1
10.0.1.0 10.0.12.2 255.255.255.0 UG 0 0 0 eth0
10.0.2.0 10.0.5.1 255.255.255.0 U 1 0 0 eth1
10.0.5.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
10.0.12.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
r4
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth4
1.0.0.0 10.0.11.2 255.255.255.0 UG 0 0 0 eth0
1.0.1.0 10.0.13.1 255.255.255.0 UG 0 0 0 eth1
10.0.1.0 10.0.11.2 255.255.255.0 UG 0 0 0 eth0
10.0.2.0 10.0.13.1 255.255.255.0 UG 0 0 0 eth1
10.0.11.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
10.0.13.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
192.168.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth4
注意:192.168.0.* 是连接到外部 Internet 的子网。
你觉得问题出在哪里?看着这个问题我完全莫名其妙。
首先,您的拓扑详细信息不完整,您缺少 r3 和 r4 详细信息,但可以推断出它们。
我不会尝试解决您的问题,而是会尝试解释需要发生的事情。但是,如果您只使用像 OSPF 这样的路由协议,它会更容易,因为它旨在使这变得容易,所以您不必手动完成。
每个正在路由的设备都需要知道如何到达每个其他子网,如果它是可访问的。所以这意味着您可以添加默认路由(即匹配 0.0.0.0/0 的路由),或者您可以在每个子网中输入相应的 next-ip 到每个路由器(见下文)。通常你不需要为连接的子网添加路由(即你在那个子网的那个路由器上有一个 ip)
R1 路线
10.0.13.0/24 -> 10.0.11.1
10.0.5.0/24 -> 10.0.11.1
10.0.2.0/24 -> 10.0.11.1
R2 路线
10.0.1.0/24 -> 10.0.13.2
10.0.12.0/24 -> 10.0.13.2
10.0.11.0/24 -> 10.0.13.2
R3 路线
10.0.1.0/24 -> 10.0.12.2
10.0.11.0/24 -> 10.0.12.2
10.0.13.0/24 -> 10.0.5.1
10.0.2.0/24 -> 10.0.5.1
R4 路线
10.0.1.0/24 -> 10.0.11.2
10.0.12.0/24 -> 10.0.11.2
10.0.2.0/24 -> 10.0.13.1
10.0.5.0/24 -> 10.0.13.1
对于设备 H1、S1、H2 和 S2,它们应该有一个指向网关 10.0.1.1 和 10.0.2.1 的默认路由。
此处 Linux 路由的行为符合预期。
反向路径过滤器的标志
即默认情况下 /proc/sys/net/ipv4/conf/<interfacename>/rp_filter
已打开(通过将值设置为 1)。
反向路径过滤器作为 Linux 内核的一项安全功能提供。
一个常见的例子是私有 IP space 逃逸到互联网上。如果您有一个路由为 195.96.96.0/24 的接口,您不希望来自 212.64.94.1 的数据包到达那里。因此,如果标志设置为 1,内核将丢弃这样的数据包。
更正式地说,
Reverse path filtering is a mechanism adopted by the Linux kernel to
check whether the source IP address of the packet that is been
received is routable.
So in other words, when a machine with reverse path filtering enabled
receives a packet, the machine will first check whether the source of
the received packet is reachable through the interface it came in.
- If it is routable through the interface which it came, then the machine will accept the packet.
- If it is not routable through the interface, which it came, then the machine will drop that packet.
Latest kernels provide one more option value of 2. This option is slightly
more liberal in terms of accepting traffic.
If the received packet's source address is routable through any of the
interfaces on the machine, the machine will accept the packet.
要让它工作,请在所有机器上使用它:
# for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
> echo 0 > $i
> done
或者在您的 /etc/sysctl.conf
中输入以下内容
net.ipv4.conf.all.rp_filter = 0
rp_filter 将以三种模式过滤数据包:0 禁用、1 严格和 2 松散。
例子
Client A - 192.168.2.10 - connected to router via eth0
Router
eth0 - 192.168.2.150
routes - 192.168.2.0/24
eth1 - 10.42.43.1
routes - 10.42.43.0/24
注:无默认路由
Client C - 10.42.43.50 - connected to router via eth1
使用此设置并将路由器上的 rp_filter 设置为“松散模式”(2) eth0 上从 1.2.3.4 到 10.42.43.50 的数据包将被阻止。
路由器上的 rp_filter 设置为“严格模式”(1) 来自源地址 10.42.43.2 的 eth0 上的数据包将被阻止。
当设置为“禁用”(0) 时,两个数据包都会通过。
长题简而言之:
Ping over
r1-r4-r2
path works using10.0.1.*
or10.0.2.*
IP addresses, but fails if we alter the path tor1-r3-r2
using1.0.0.*
or1.0.1.*
IP addresses for the exactly same packets (except for the fact that packets'src
anddst
IP fields are changed from10.*
to1.*
and vice-versa ats1
ands2
respectively). Why?
问题详细:
我有一个小拓扑如下
h1 -- s1 -- r1 -- r4 -- r2 -- s2 -- h2
\ /
\ /
\ /
r3
s
是 OpenvSwitch 实例,而 r
是 Ubuntu 16 Linux 台机器。
IP 地址是:
h1-eth0 - 10.0.1.10/24
s1 - 10.0.1.50/24
h2-eth0 - 10.0.2.10/24
s2 - 10.0.2.50/24
r1-eth0 - 10.0.1.1/24
r1-eth1 - 10.0.11.2/24
r1-eth2 - 10.0.12.2/24
r2-eth0 - 10.0.2.1/24
r2-eth1 - 10.0.13.1/24
r2-eth2 - 10.0.5.1/24
r3-eth0 - 10.0.12.1/24
r3-eth1 - 10.0.5.2/24
r4-eth0 - 10.0.11.1/24
r4-eth1 - 10.0.13.2/24
可以看到,r1和r2之间有两条相似的路径。我添加以下静态条目。
r1
sudo ip route add 10.0.2.0/24 via 10.0.11.1
r2
sudo ip route add 10.0.1.0/24 via 10.0.13.2
r4
sudo ip route add 10.0.1.0/24 via 10.0.11.2
sudo ip route add 10.0.2.0/24 via 10.0.13.1
h1 和 h2 之间的 ping 正常。现在,由于交换机是 OVS(因此启用了 OpenFlow),我在 s1 中安装条目以 将目标 IP 映射到不同的子网 .
i.e. the IP 10.0.1.10 would be mapped to 1.0.0.10 while the IP 10.0.2.10 would be mapped to 1.0.1.10 when such a packet is received at s1, while the destination IPs would be mapped back to original at s2.
(我检查过这些条目确实正确并且按预期工作。另外我添加此条目只是为了匹配 ICMP 数据包)。当 h1 发送 ping 回复时,将执行类似的过程。
除此之外,我还在路由器中安装了静态路由来路由这些 IP。
r1
sudo ip route add 1.0.0.0/24 via 10.0.1.50
sudo ip route add 1.0.1.0/24 via 10.0.12.1
r2
sudo ip route add 1.0.0.0/24 via 10.0.5.2
sudo ip route add 1.0.1.0/24 via 10.0.2.50
r3
sudo ip route add 1.0.0.0/24 via 10.0.12.2
sudo ip route add 1.0.1.0/24 via 10.0.5.1
现在,如果我从 h2 ping h1,数据包以目标 IP 10.0.1.10 开始,在 s2 映射到 1.0.0.10,r2 路由它并将其发送到 r3,r3 路由它并发送到 r1。 但是 r1,即使在一个接口接收到数据包并在 Linux 路由 table 中具有匹配条目后,也不会路由和转发数据包。
甚至 ip route get
输出数据包应该转发到的正确端口。 ip tables
中也没有防火墙条目。
一些附加信息:
如果我把新添加的路由条目改成使用原来的路径
r1-r4-r2
(即,我们使用映射的 ip 在这条路径上路由),它的行为符合预期并且 ping 按预期工作。或者,如果我在 r1 和
中更改 10.0.2.0/24 的旧路由条目 r2 中的 10.0.1.0/24(现在理想情况下甚至不必与新的匹配 数据包,因为它们的目标 IP 在 1.0.0.* 范围内或仅在 1.0.1.* 范围内)以使用 新路径r1-r3-r4
以及此映射的 IP 数据包,之间的 ping r2 和 r1 按预期工作。
可能需要的详细信息:
最终路由table如下:
r1
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.11.1 0.0.0.0 UG 0 0 0 eth1
1.0.0.0 10.0.1.10 255.255.255.0 UG 0 0 0 eth0
1.0.1.0 10.0.12.1 255.255.255.0 UG 0 0 0 eth2
10.0.1.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
10.0.2.0 10.0.11.1 255.255.255.0 UG 0 0 0 eth1
10.0.11.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
10.0.12.0 0.0.0.0 255.255.255.0 U 1 0 0 eth2
r2
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.13.2 0.0.0.0 UG 0 0 0 eth1
1.0.0.0 10.0.5.2 255.255.255.0 UG 0 0 0 eth1
1.0.1.0 10.0.2.50 255.255.255.0 UG 0 0 0 eth0
10.0.1.0 10.0.13.2 255.255.255.0 UG 0 0 0 eth1
10.0.2.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
10.0.5.0 0.0.0.0 255.255.255.0 U 1 0 0 eth2
10.0.13.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
r3
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.5.1 0.0.0.0 UG 0 0 0 eth1
1.0.0.0 10.0.12.2 255.255.255.0 UG 0 0 0 eth0
1.0.1.0 10.0.5.1 255.255.255.0 UG 0 0 0 eth1
10.0.1.0 10.0.12.2 255.255.255.0 UG 0 0 0 eth0
10.0.2.0 10.0.5.1 255.255.255.0 U 1 0 0 eth1
10.0.5.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
10.0.12.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
r4
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth4
1.0.0.0 10.0.11.2 255.255.255.0 UG 0 0 0 eth0
1.0.1.0 10.0.13.1 255.255.255.0 UG 0 0 0 eth1
10.0.1.0 10.0.11.2 255.255.255.0 UG 0 0 0 eth0
10.0.2.0 10.0.13.1 255.255.255.0 UG 0 0 0 eth1
10.0.11.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
10.0.13.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
192.168.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth4
注意:192.168.0.* 是连接到外部 Internet 的子网。
你觉得问题出在哪里?看着这个问题我完全莫名其妙。
首先,您的拓扑详细信息不完整,您缺少 r3 和 r4 详细信息,但可以推断出它们。
我不会尝试解决您的问题,而是会尝试解释需要发生的事情。但是,如果您只使用像 OSPF 这样的路由协议,它会更容易,因为它旨在使这变得容易,所以您不必手动完成。
每个正在路由的设备都需要知道如何到达每个其他子网,如果它是可访问的。所以这意味着您可以添加默认路由(即匹配 0.0.0.0/0 的路由),或者您可以在每个子网中输入相应的 next-ip 到每个路由器(见下文)。通常你不需要为连接的子网添加路由(即你在那个子网的那个路由器上有一个 ip)
R1 路线
10.0.13.0/24 -> 10.0.11.1
10.0.5.0/24 -> 10.0.11.1
10.0.2.0/24 -> 10.0.11.1
R2 路线
10.0.1.0/24 -> 10.0.13.2
10.0.12.0/24 -> 10.0.13.2
10.0.11.0/24 -> 10.0.13.2
R3 路线
10.0.1.0/24 -> 10.0.12.2
10.0.11.0/24 -> 10.0.12.2
10.0.13.0/24 -> 10.0.5.1
10.0.2.0/24 -> 10.0.5.1
R4 路线
10.0.1.0/24 -> 10.0.11.2
10.0.12.0/24 -> 10.0.11.2
10.0.2.0/24 -> 10.0.13.1
10.0.5.0/24 -> 10.0.13.1
对于设备 H1、S1、H2 和 S2,它们应该有一个指向网关 10.0.1.1 和 10.0.2.1 的默认路由。
此处 Linux 路由的行为符合预期。
反向路径过滤器的标志
即默认情况下 /proc/sys/net/ipv4/conf/<interfacename>/rp_filter
已打开(通过将值设置为 1)。
反向路径过滤器作为 Linux 内核的一项安全功能提供。 一个常见的例子是私有 IP space 逃逸到互联网上。如果您有一个路由为 195.96.96.0/24 的接口,您不希望来自 212.64.94.1 的数据包到达那里。因此,如果标志设置为 1,内核将丢弃这样的数据包。
更正式地说,
Reverse path filtering is a mechanism adopted by the Linux kernel to check whether the source IP address of the packet that is been received is routable.
So in other words, when a machine with reverse path filtering enabled receives a packet, the machine will first check whether the source of the received packet is reachable through the interface it came in.
- If it is routable through the interface which it came, then the machine will accept the packet.
- If it is not routable through the interface, which it came, then the machine will drop that packet.
Latest kernels provide one more option value of 2. This option is slightly more liberal in terms of accepting traffic.
If the received packet's source address is routable through any of the interfaces on the machine, the machine will accept the packet.
要让它工作,请在所有机器上使用它:
# for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
> echo 0 > $i
> done
或者在您的 /etc/sysctl.conf
net.ipv4.conf.all.rp_filter = 0
rp_filter 将以三种模式过滤数据包:0 禁用、1 严格和 2 松散。
例子
Client A - 192.168.2.10 - connected to router via eth0
Router
eth0 - 192.168.2.150
routes - 192.168.2.0/24
eth1 - 10.42.43.1
routes - 10.42.43.0/24
注:无默认路由
Client C - 10.42.43.50 - connected to router via eth1
使用此设置并将路由器上的 rp_filter 设置为“松散模式”(2) eth0 上从 1.2.3.4 到 10.42.43.50 的数据包将被阻止。
路由器上的 rp_filter 设置为“严格模式”(1) 来自源地址 10.42.43.2 的 eth0 上的数据包将被阻止。
当设置为“禁用”(0) 时,两个数据包都会通过。