0%

Linux策略路由

Linux 策略路由是一种高级路由机制。相比于传统路由,策略路由允许用户配置多张路由表,根据源地址、目的地址等选择不同路由表,提供了更灵活的路由控制能力。

路由表(Routing Table)

路由表是存储路由规则的集合,Linux 支持配置多张路由表。

rt_tables 文件

/etc/iproute2/rt_tables 是 Linux 中用于定义路由表名称和编号映射的文件。

其中的每一行定义了一个路由表,包括其编号(1~255)和名称,编号和名称都不能重复。

Linux 发行版中,/etc/iproute2/rt_tables 的默认内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
root@ubuntu2404:/# cat /etc/iproute2/rt_tables
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep

Linux 默认路由表

Linux 初始的默认状态下,包含下面四个路由表:

  • local

    • 编号:255
    • 存储本地接口地址和广播地址
    • 内核自动维护,用户通常不需要修改
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root@ubuntu2404:/# ip route show table local
    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
    local 172.16.19.129 dev ens160 proto kernel scope host src 172.16.19.129
    local 172.16.19.133 dev ens256 proto kernel scope host src 172.16.19.133
    broadcast 172.16.19.255 dev ens160 proto kernel scope link src 172.16.19.129
    broadcast 172.16.19.255 dev ens256 proto kernel scope link src 172.16.19.133
    local 172.17.0.1 dev docker0 proto kernel scope host src 172.17.0.1
    broadcast 172.17.255.255 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
  • main

    • 编号:254
    • 主路由表,传统路由使用的表
    • 通过 ip route 命令配置或展示的都是此表
    1
    2
    3
    4
    5
    6
    root@ubuntu2404:/# ip route show table main
    default via 172.16.19.2 dev ens160 proto dhcp src 172.16.19.129 metric 100
    default via 172.16.19.2 dev ens256 proto dhcp src 172.16.19.133 metric 101
    172.16.19.0/24 dev ens160 proto kernel scope link src 172.16.19.129 metric 100
    172.16.19.0/24 dev ens256 proto kernel scope link src 172.16.19.133 metric 101
    172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
  • default

    • 编号:253
    • 默认路由表,通常用于存储默认路由
    • 初始时为空
  • unspec

    • 编号:0
    • 未指定路由表,用于表示未指定或无效的路由表

自定义路由表

修改 /etc/iproute2/rt_tables 文件,可添加自定义路由表。

1
<编号>	<路由表名>

建议:编号虽然可以从 1 开始取,但是为了避免与未来系统可能保留的编号冲突,通常选择从 100 开始分配编号

1
2
100   custom1
101 custom2

也可以分段分配编号,以方便管理不同类型的路由表

1
2
100   custom1
200 custom2

路由规则(Rule)

路由规则:数据包如何匹配并选择路由表的规则,根据特定的条件(如源地址、目的地址、入接口等)选择不同的路由表。

查看路由规则

1
2
3
4
root@ubuntu2404:/# ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default

路由规则的组成

每一条路由规则包含 3 个信息:

  • 优先级:数字越小,优先级越高。自定义规则的优先级通常设置在 1 到 32765 之间。
  • 条件:匹配数据包的条件,如源地址、目的地址、入接口等
  • 动作:通常规定选择哪个路由表

按照优先级,从小到大匹配规则,如果匹配到,则选择规定的路由表。

增/删路由规则

  • 增加路由规则(优先级可缺省,缺省时取低优先级)

    1
    ip rule add <条件> lookup <表名> priority <优先级>
  • 删除路由规则

    1
    ip rule del <条件> lookup <表名>

匹配条件

路由规则的匹配条件支持以下字段:

  • 匹配数据包的源地址

    • from <PREFIX>

    • 示例:

      1
      2
      # 来自 192.168.1.0/24 的流量使用 custom1 表
      ip rule add from 192.168.1.0/24 lookup custom1
  • 匹配数据包的目的地址

    • to <PREFIX>

    • 示例:

      1
      2
      # 去往 8.8.8.8 的流量使用 custom2 表
      ip rule add to 8.8.8.8 lookup custom2
  • 匹配数据包的入网卡

    • iif <网卡>

    • 示例:

      1
      2
      # 从 eth1 接口进入的流量使用 custom3 表
      ip rule add iif eth1 lookup custom3
  • 匹配数据包的协议

    • ipproto <PROTOCOL>

    • 示例:

      1
      2
      # TCP 协议的流量使用 custom4 表
      ip rule add proto tcp lookup custom4
  • 等等,详细见 help

help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
root@ubuntu2404:/# ip rule help
Usage: ip rule { add | del } SELECTOR ACTION
ip rule { flush | save | restore }
ip rule [ list [ SELECTOR ]]
SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ]
[ fwmark FWMARK[/MASK] ]
[ iif STRING ] [ oif STRING ] [ pref NUMBER ] [ l3mdev ]
[ uidrange NUMBER-NUMBER ]
[ ipproto PROTOCOL ]
[ sport [ NUMBER | NUMBER-NUMBER ]
[ dport [ NUMBER | NUMBER-NUMBER ] ]
ACTION := [ table TABLE_ID ]
[ protocol PROTO ]
[ nat ADDRESS ]
[ realms [SRCREALM/]DSTREALM ]
[ goto NUMBER ]
SUPPRESSOR
SUPPRESSOR := [ suppress_prefixlength NUMBER ]
[ suppress_ifgroup DEVGROUP ]
TABLE_ID := [ local | main | default | NUMBER ]

路由(Route)

每张路由表里都可以配置自己的路由。

ip route 命令

ip route 命令如果没有指定路由表,则默认指定 main 表。

查看路由表

1
ip route show table <路由表名>

help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
root@ubuntu2404:/# ip route help
Usage: ip route { list | flush } SELECTOR
ip route save SELECTOR
ip route restore
ip route showdump
ip route get [ ROUTE_GET_FLAGS ] ADDRESS
[ from ADDRESS iif STRING ]
[ oif STRING ] [ tos TOS ]
[ mark NUMBER ] [ vrf NAME ]
[ uid NUMBER ] [ ipproto PROTOCOL ]
[ sport NUMBER ] [ dport NUMBER ]
ip route { add | del | change | append | replace } ROUTE
SELECTOR := [ root PREFIX ] [ match PREFIX ] [ exact PREFIX ]
[ table TABLE_ID ] [ vrf NAME ] [ proto RTPROTO ]
[ type TYPE ] [ scope SCOPE ]
ROUTE := NODE_SPEC [ INFO_SPEC ]
NODE_SPEC := [ TYPE ] PREFIX [ tos TOS ]
[ table TABLE_ID ] [ proto RTPROTO ]
[ scope SCOPE ] [ metric METRIC ]
[ ttl-propagate { enabled | disabled } ]
INFO_SPEC := { NH | nhid ID } OPTIONS FLAGS [ nexthop NH ]...
NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]
[ dev STRING ] [ weight NUMBER ] NHFLAGS
FAMILY := [ inet | inet6 | mpls | bridge | link ]
OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]
[ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]
[ window NUMBER ] [ cwnd NUMBER ] [ initcwnd NUMBER ]
[ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]
[ rto_min TIME ] [ hoplimit NUMBER ] [ initrwnd NUMBER ]
[ features FEATURES ] [ quickack BOOL ] [ congctl NAME ]
[ pref PREF ] [ expires TIME ] [ fastopen_no_cookie BOOL ]
TYPE := { unicast | local | broadcast | multicast | throw |
unreachable | prohibit | blackhole | nat }
TABLE_ID := [ local | main | default | all | NUMBER ]
SCOPE := [ host | link | global | NUMBER ]
NHFLAGS := [ onlink | pervasive ]
RTPROTO := [ kernel | boot | static | NUMBER ]
PREF := [ low | medium | high ]
TIME := NUMBER[s|ms]
BOOL := [1|0]
FEATURES := ecn
ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 | xfrm ]
ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR | XFRMINFO ]
SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]
SEGMODE := [ encap | encap.red | inline | l2encap | l2encap.red ]
SEG6LOCAL := action ACTION [ OPTIONS ] [ count ]
ACTION := { End | End.X | End.T | End.DX2 | End.DX6 | End.DX4 |
End.DT6 | End.DT4 | End.DT46 | End.B6 | End.B6.Encaps |
End.BM | End.S | End.AS | End.AM | End.BPF }
OPTIONS := OPTION [ OPTIONS ]
OPTION := { flavors FLAVORS | srh SEG6HDR | nh4 ADDR | nh6 ADDR | iif DEV | oif DEV |
table TABLEID | vrftable TABLEID | endpoint PROGNAME }
FLAVORS := { FLAVOR[,FLAVOR] }
FLAVOR := { psp | usp | usd | next-csid }
IOAM6HDR := trace prealloc type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size IOAM6_TRACE_SIZE
XFRMINFO := if_id IF_ID [ link_dev LINK ]
ROUTE_GET_FLAGS := [ fibmatch ]