源策略路由打破了第 2 层域路由

源策略路由打破了第 2 层域路由

我有一台 Linux (Ubuntu 12.04) 机器 (c220-1),它有多个接口。这里感兴趣的两个是:

  • eth2:10.10.0.131/24
  • eth3:10.20.0.2/24

默认路由设置为 10.20.0.2。但是,我希望能够通过连接到 10.20.0.2 或 10.10.0.131 从单独的网络 (192.168.3.0/24) 来 ssh 进入此机器

为了能够通过 ssh 进入 10.10.0.131 并避免对称路由问题,我使用了源路由策略:

root@c220-1:~# ip route list table eth2
default via 10.10.0.1 dev eth2

我通过在 /etc/iproute2/rt_tables 中添加以下行来添加此规则

12 eth2

然后我就这么做了

root@c220-1:~# ip route add default via 10.10.0.1 table eth2
root@c220-1:~# ip rule add from 10.10.0.131 lookup eth2

这有效,我可以 ssh 到 10.10.0.131 或 10.20.0.2。但我无法再从 10.10.0.0/24 网络上的其他机器连接到 10.10.0.131。我可以双向 arping,并且可以从 c220-1 (10.10.0.131/24) ping 到 c220-2 (10.10.0.132/24)。但我无法从 c220-2 ping 到 c220-1。

如果我执行 tcpdump,我可以确认 c220-1 正在接收 ICMP 请求并发送回复:

root@c220-1:~# tcpdump -i eth2 icmp -vvv -n -e
tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes
23:15:11.455818 d4:8c:b5:4d:a5:3a > 60:73:5c:68:b4:b6, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.0.132 > 10.10.0.131: ICMP echo request, id 8805, seq 1, length 64
23:15:11.455877 60:73:5c:68:b4:b6 > 30:f7:0d:bc:bb:52, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 16273, offset 0, flags [none], proto ICMP (1), length 84)
    10.10.0.131 > 10.10.0.132: ICMP echo reply, id 8805, seq 1, length 64
23:15:12.463394 d4:8c:b5:4d:a5:3a > 60:73:5c:68:b4:b6, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.0.132 > 10.10.0.131: ICMP echo request, id 8805, seq 2, length 64
23:15:12.463451 60:73:5c:68:b4:b6 > 30:f7:0d:bc:bb:52, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 16274, offset 0, flags [none], proto ICMP (1), length 84)
    10.10.0.131 > 10.10.0.132: ICMP echo reply, id 8805, seq 2, length 64

你可以看到请求来自d4:8c:b5:4d:a5:3a,但答复将发往30:f7:0d:bc:bb:52

正如预期的那样,ICMP 回复没有出现在 c220-2 上:

root@c220-2:~#  tcpdump -i eth2 icmp -vvv -n -e
tcpdump: listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes
23:16:19.944225 d4:8c:b5:4d:a5:3a > 60:73:5c:68:b4:b6, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.0.132 > 10.10.0.131: ICMP echo request, id 9380, seq 1, length 64
23:16:20.952497 d4:8c:b5:4d:a5:3a > 60:73:5c:68:b4:b6, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.0.132 > 10.10.0.131: ICMP echo request, id 9380, seq 2, length 64
23:16:21.960458 d4:8c:b5:4d:a5:3a > 60:73:5c:68:b4:b6, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
    10.10.0.132 > 10.10.0.131: ICMP echo request, id 9380, seq 3, length 64

回复的目标 MAC 地址与网关的 MAC 地址 10.10.0.1 匹配:

root@c220-2:~# arping -i eth2 10.10.0.1
ARPING 10.10.0.1
60 bytes from 30:f7:0d:bc:bb:52 (10.10.0.1): index=0 time=214.100 usec

如果我完全删除源策略路由规则,那么我就能够从 c220-2 连接,但无法从 192.168.3.1/24 连接到 10.10.0.131。

我如何指定规则,以便源策略路由不会将数据包发送到 10.10.0.1,而这些数据包应该发送到本地网络上的另一台机器?

答案1

我刚刚遇到了同样的问题,发现问题在于路由表的应用操作顺序。

如果您在应用策略路由之前发出以下命令:

[root@c220-1 ~]# ip rule show
0:      from all lookup 255
32766:  from all lookup main
32767:  from all lookup default

然后:

[root@c220-1 ~]# ip rule show
0:      from all lookup 255
32765:  from 10.10.0.131 lookup eth2
32766:  from all lookup main
32767:  from all lookup default

恕我直言,我希望任何新的路由表都能应用于包含所有第 2 层转发语句的“主”路由表和“默认”路由表之间的某个位置。

我发现有两个方法可以解决这个问题

  • 重新排序路由规则,使“主”表在任何自定义路由表之前应用,或者
  • 将第 2 层转发语句添加到命名路由表

我们采用了第二种方法,首先手动将路由添加到命名路由表中,并验证连接是否按预期工作:

ip route add 10.10.0.0/24 dev eth2 src 10.10.0.131 table eth2

接下来,使上述更改在重启后仍然有效

创建路线文件:

[root@c220-1 ~]# vi /etc/sysconfig/network-scripts/route.eth2

10.10.0.0/24 dev eth2 src 10.10.0.131 table eth2
default table eth2 via 10.10.0.1

创建路由规则文件:

[root@c220-1 ~]# vi /etc/sysconfig/network-scripts/rule.eth2

from 10.10.0.131 table eth2

重新启动主机并验证路由策略是否持续

[root@c220-1 ~]# ip rule show
[root@c220-1 ~]# ip route show table eth2

附加信息 我通常不会推荐一堆静态路由,但是由于基础设施的限制,我们的场景在上述基础上进行了扩展,还需要通过辅助接口(在本例中为 eth2)路由出一个额外的子网

假设我们需要通过 eth2 到达 10.10.1.0/24,我们对上述配置进行了以下更改。

更新的路线文件:

[root@c220-1 ~]# vi /etc/sysconfig/network-scripts/route.eth2

10.10.0.0/24 dev eth2 src 10.10.0.131 table eth2
10.10.1.0/24 dev eth2 via 10.10.0.1 table eth2
default table eth2 via 10.10.0.1

更新的策略路由规则:

[root@c220-1 ~]# vi /etc/sysconfig/network-scripts/rule.eth2

from 10.10.0.131 table eth2
to 10.10.1.0/24 table eth2

重新启动网络并验证路由策略:

[root@c220-1 ~]# service networking restart

[root@c220-1 ~]# ip rule show
0:      from all lookup 255
32764:  from all to 10.10.1.0/24 lookup eth2
32765:  from 10.10.0.131 lookup eth2
32766:  from all lookup main
32767:  from all lookup default

[root@c220-1 ~]# ip route show table eth2
10.10.0.0/24 dev eth2 src 10.10.0.131 scope link
10.10.1.0/24 via 10.10.0.1 dev eth2
default via 192.168.152.1 dev eth2

然后我们重新启动主机以验证所有路由策略是否持久

答案2

我没有任何 Linux 机器可以测试,但我认为你应该这样做:

root@c220-1:~# ip rule add from 192.168.3.0/24 table c2202
root@c220-1:~# ip route add default via 10.10.0.1 table c2202

我将表名从 eth2 更改以避免与接口名称混淆。

相关内容