Linux中的路由表与路由策略管理

Linux中数据包的传输主要是路由和iptables参与的,前者决定怎样传输数据包,后者可以在路由基础上增加一些限定条件或标识(fwmark),比如iptables可以拒绝传输数据包。这次主要介绍一下路由表和路由策略管理,路由表大家接触的会比较多,但是路由策略会接触的少一些。

路由表

路由表通常由ip route命令管理,也通过使用route -nnetstat -nr来管理与查看,不过routenetstat已经是过去式了,现在及以后都要用由iproute2软件包提供的ip命令来管理。

$ ip route show
default via 192.168.249.1 dev wlp1s0 proto dhcp src 192.168.249.68 metric 600
192.168.249.0/24 dev wlp1s0 proto kernel scope link src 192.168.249.68 metric 600

以上是我电脑上的路由表信息,可以看到包含两条路由。在前面添加ip route addip route del就是添加或删除路由了,如下:

ip route add 10.0.0.0/8 via 192.168.249.1

ip route del 10.0.0.0/8 via 192.168.249.1

其实以上只是管理机器上的「主路由表」,默认情况下机器上有三张路由表的分别是localmaindefault,而这些路由表配合路由策略共同决定了数据包应该怎样传输。

平时大家操作的都是main路由表,以上命令后面都是省略了table main,比如:

ip route show table main

查看数据包路由规则:

ip route get 1.1.1.1

ip route get 223.5.5.5 dport 53

路由策略

上面说了默认情况下主机上有三张路由表,当然用户也可以自主创建路由表,那么要实现路由表的优先级及更精细化的路由控制就需要路由策略了。简单来说路由策略可以按端口、协议、用户UID区间、fwmark等来控制数据包路由。

路由策略由ip rule命令进行管理,默认情况下机器上有三条路由策略:

$ ip rule list
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

第一列为优先级,后面是路由策略,就是控制什么样的数据包走哪张路由表。下面举例说明:

  1. 创建一个路由表及路由规则:

    ip route add 10.0.0.0/8 via 192.168.249.1 table 12345
    
    ip route show table 12345
  2. 创建一个路由策略,使其优先级高于「主路由表」:

    ip rule add from all priority 5555 table 12345
    
    ip rule list

使用场景

路由策略的一个使用场景就是VPN做数据包分流,拿Clash来举例(WireGuard也类似),开启Tun及Auto Route功能后,会在系统中添加相应的路由表与路由策略。

主路由表会增加fake-ip网段走utun设备的路由规则:

$ ip route show
default via 192.168.249.1 dev wlp1s0 proto dhcp src 192.168.249.68 metric 600
192.168.249.0/24 dev wlp1s0 proto kernel scope link src 192.168.249.68 metric 600
198.18.0.0/16 dev utun proto kernel scope link src 198.18.0.1

路由策略会增加四条优先级分别为9500951095209530

$ ip rule list
0:      from all lookup local
9500:   not from all dport 53 lookup main suppress_prefixlength 0
9510:   not from all iif lo lookup 1970566510
9520:   from 0.0.0.0 iif lo uidrange 0-4294967294 lookup 1970566510
9530:   from 198.18.0.1 iif lo uidrange 0-4294967294 lookup 1970566510
32766:  from all lookup main
32767:  from all lookup default

由路由策略可以看出还会增加一个路由表1970566510,内容就是数据包默认走utun设备:

$ ip route show table 1970566510
default dev utun proto static

下面讲解一下Clash新增的这四条路由策略:

  1. 9500: not from all dport 53 lookup main suppress_prefixlength 0

    所有目的端口不是53的数据包都走main路由表,但不包含main路由表中的默认路由。

    解释一下,53是DNS服务端口,目的端口不是53表示「非DNS查询数据包」;suppress_prefixlength 0意思是忽略prefix长度为0的数据包,就是忽略0.0.0.0/0的数据包,0.0.0.0/0表示所有IP。本机内网路由一般都显式指定,所以综合以上,该规则的意思是:所有非DNS查询并且非内网的数据包都走「主路由表」,就是内网流量照常路由

  2. 9510: not from all iif lo lookup 1970566510

    所有输入网卡不是lo的数据包都走1970566510路由表,即排除掉本地生成的包含源地址的数据包之外的数据包都走路由表1970566510。当本机作为网关时,其他机器的内网流量不走Clash。

  3. 9520: from 0.0.0.0 iif lo uidrange 0-4294967294 lookup 1970566510

    from 0.0.0.0 iif lo意思是本地生成的不包含源地址的数据包,在Linux中当客户端生成的数据包没到达网卡前是没法包含源地址的,这条策略的意思就是本机数据包要走Clash。

  4. 9530: from 198.18.0.1 iif lo uidrange 0-4294967294 lookup 1970566510

    所有从198.18.0.1过来的数据包都走路由表1970566510198.18.0.1fake-ip网段的网关,该条策略和「主路由表」中的那条fake-iputun设备的路由一起配合工作。

Reference