13
2025
04
01:12:58

Linux 网络速成课 4 :主路由表(rt_table)、内置路由表、ip route 输出详解、增删路由,路由优先级处理

本系列文章基于 A Crash Course in Linux Networking, 翻译、增删修改而成。原文作者 David Guyton
相比原文有相当多的精简及内容补充,不再单独标注。若感到困惑请参阅原文。其他参考内容将在文章末尾列出

Linux 系统下,可以使用 ip route 或 route 工具来管理路由。(虽然 route 已经过时了,但它在某些方面还能发挥独特的作用,而且所依赖的代码也还都在)

主路由表(Master Routing Table)

Linux RPDB 系统使用一个主路由表作为索引,实现间接使用至多 256 个相互独立的路由表,并能支持至多 32768 条与路由表交互的规则。

主路由表是一个文件,位于 /etc/iproute2/rt_tables ,其是一个包含最多 256 条记录的列表。每条记录都由一个整数和一个名称组成,表示对一个实际路由表的索引。Linux 内核使用规则来选择要用到的路由表。

该文件的内容大概是下面这样:

# 
# reserved values 
# 
255 local 
254 main 
253 default 
0 unspec 
# 
# local 
# 
#1 inr.ruhep

主路由表列出了当前主机中所有的路由表。在未进行修改的情况下,其中应包括下面这些表:

  • local:本地和广播地址。该路由表由内核维护,用户无法向该表中添加任何条目

  • main:由 route 或 ip route 管理(部分由内核管理),在不指定策略的时候会使用该表

  • default:为后处理规则(post-processing rules)保留

  • unspec:用于失效安全(failsafe),请勿修改和移除

  • inr.ruhep:这行是个例子,告诉用户可以这样以 <整数值 名称> 的方式来设置路由表。

该文件中的记录数值并不需要是有序的。确保数字、名称唯一即可。用户可以随时修改该文件,且修改可以立即生效。系统不会对该文件做缓存,每当一个规则引用某个路由表时,系统都会读一次该文件。

内置路由表

Ubuntu 系统内置了四个特殊的路由表:default, local, main 和 unspec。

  • default 路由表是空的,实际并不会被用到(所以这是个很糟糕的名字)

  • local 表用于处理主机内部(自己对自己)的 TCP/IP 流量,包括了回环(loopback)和广播(broadcast)流量

  • main 表是主要的路由表,是真正的 "default" 表。在不指定路由表时,route 和 ip route 命令操作的都是这个 main 表

  • unspec 包含一系列失效安全指令,用于告诉内核应该在所有路由路径都失效时做什么。

ip route 查看已有路由

查看 main 表的路由:

$ ip route list  # 列出默认路由表,和下面这句相同:
$ ip route show table main

在一个新安装的系统上,输出值应该和下面差不多:

default via 192.168.10.10 dev eth0 
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.11

每条路由条目的含义都是:若没有与目的地地址更相符的路由,则使用本条路由。

第一行是 default 路由条目。"default" 会在没有找到更具体的路由(数据包目的地地址与路由条目更匹配)时使用。"via 192.168.10.10" 指的是网关 IP 地址为 192.168.10.10,"dev eth0" 指使用 eth0 接口。

第二行是通过 eth0 接口到达 192.168.10.0/24 网络的路由。"proto kernel" 说明该条路由是内核在系统网络接口配置阶段添加的,而不是由管理员手动添加或由路由协议动态添加的。 "scope link" 的意思是说该路由直接连接在当前主机上,即处于同一局域网内。"src" 是指会使用该路由条目的数据包应有的源地址,也就是意味着本机在该局域网内的 IP 地址被设置为了 192.168.10.11。

路由记录的格式通常都是这样的:

<目的地> via <网关> dev <接口> proto <协议> src <源地址> <附加信息>

<目的地>:目的地网络或主机,可以是具体的 IP 地址(如 192.168.1.1)、网络地址 (如192.168.1.0/24)或 default 等。default 会在没有其他符合的路由条目时使用;

via <网关>:可选字段,指的是到达该目的地需要使用的网关的 IP 地址。发往这个路由条目对应的目的地的数据包,都会把这个网关设置为下一跳,经由此发往最终目的地;

dev <接口>:要发往本条目对应目的地时所需要使用的网络接口(设备);

proto <协议>:添加本条条目的协议。常见的值有:kernel(本条目由内核添加)、static(手动添加)、dhcp(通过 DHCP 添加)、boot (在启动时添加)、redirect (由 ICMP 重定向添加)。此外,该值还可以是 bgpospf 这类动态路由协议。该值可能是整数值或者一个字符串值,字符串值都可以在 /etc/iproute2/rt_protos 中找到;

src <源地址>:在使用本条路由,向目的地发送数据包时所需采用的 IP 地址;

<附加信息> 代表多个可选项,常见的有:

  • scope <scope>:定义这条路由的范围。global 表示有网关的单播(unicast)路由,link 表示直连的单播或广播(broadcast)路由,host 表示本地(local)路由。该值可能是一个整数值或者是字符串值,字符串值应该能在 /etc/iproute2/rt_scopes 中找到

  • metric <整数>:表示路由的优先级,数字越小优先级越高。最小值为 0 ,最大值为 65535

  • table <表名/数字>:如果一条路由不属于 main 表,则会在这里指出该路由所属的路由表

路由记录还可以有个表示路由类型的前缀,该字段能说明路由用途以及特性。类型有下面这些:

  1. unicast(单播):标准类型,表示把数据发往一个特定的目的地 IP 地址。通常省略不显示;

  2. unreachable(不可达):目的地不可达。发往该地址的数据包会被丢弃,ICMP 会返回 host unreachable,发送代码会报错 EHOSTUNREACH ;

  3. blackhole(黑洞):目的地不可达,数据包会被无声丢弃(discarded silently),发送代码会报错 EINVAL ;

  4. prohabit(禁止):目的地不可达,数据包会被丢弃,ICMP 会返回 communication administratively prohibited。发送代码会报错 EACCES

  5. local(本地):目的地是当前主机,数据包会回环发送;

  6. broadcast(广播):目的地是广播地址,数据包作为链路广播发送,通常是向本地网络广播;

  7. throw(抛弃):这是个特殊路由,如果策略规则选择了该路由的路由表,则系统会装作是没有找到对应路由。ICMP 会返回 net unreachable,发送代码会报错 ENETUNREACH ;

  8. nat(网络地址转换):该路由已在 2.6 内核后停止支持。这是个特殊的 NAT 路由。目的地地址是假地址(外部地址),需要在转发前转换为真实(内部)地址;

  9. anycast(任播):尚未实现。目的地是本主机的 anycast 地址。和 local 只有一个区别:该地址不能被用于任何数据包的源地址;

  10. multicast(多播):用于多播路由的特殊路由。不会在普通的路由表中出现。

ip route 添加新路由

本节中我们将了解如何向默认(main)路由表、已有的其他路由表中添加路由,以及如何创建一个新路由表并添加指向该路由表的规则。

创建新路由需要使用 ip route 命令,命令结构如下:

ip route add [type] [prefix] via [下一跳(网关)] dev [接口名] table [路由表名/ID] src [源地址]

这里的每一个字段都在前一节中有说明,可以搭配阅读。

若不指定 type ,则使用默认值 unicast (绝大多数的路由都是 unicast 的)。下一跳(网关)就是能够帮你转发数据的下一跳设备,一般指的就是当前网络的网关。

prefix 指的就是目的地 IP 地址,可以是精确的主机地址(具体的 IP,例如 192.168.1.101),也可以是包含子网掩码的网络地址(例如 192.168.1.0/24)。若 prefix 设置为 default 则代表所有地址,等效于 0.0.0.0/0 。

向指定路由表添加路由

下面这条命令可以向指定路由表 custom 中添加路由。

ip route add default via 192.168.1.100 dev eth1 table custom

该路由会将无法匹配到更精确路由的流量都通过 eth1 网卡发送到网关路由器 192.168.1.100。

可以用下面的命令查看添加后的结果:

ip route show table custom

注意:所有的 RPDB 规则都是在系统启动时加载进内核内存的,因此还需要 flush 缓存。这会强制内核重新加载规则和路由数据库

ip route flush cache

向默认路由表添加路由

和上面类似,只需要省略 table 即可。例如:

ip route add default via 192.168.1.100 dev eth1

删除路由

ip route delete <路由信息>

路由信息足够匹配到路由条目即可,最简单的方式就是把整个路由条目全都写上去,比如:

ip route delete default via 192.168.1.100 dev eth1

最后记得 flush 一下

ip route flush cache

路由优先级处理

netfilter 是如何从路由表中选择路由的?如果一个数据包匹配到超过一个路由条目该怎么办?大型网络的路由表可能包含数百条路由条目,RPDB 会在何时、如何选择合适的路由条目?

系统会使用数据包的目的地地址和 ToS 值(如果有)来和每个路由条目的 prefix 进行比对,然后选择符合条件最多的一个,对比顺序为:

  1. 目的地地址和路由条目 prefix 的相符程度;

  2. 数据包和路由条目 ToS 的匹配;

  3. 选择 ToS=0 的路由

举例来说,如果数据包匹配到了多个可选路由,则按下面的顺序来选择出一个路由:

  1. 选择包含子网掩码在内的,prefix 匹配长度最长的路由;

  2. 如果有一个路由的 ToS 与数据包的 ToS 相符,则直接使用这个路由;

  3. 选择 ToS=0 的路由;

  4. 如果没有 ToS=0 的路由,返回一个错误(不可达 unreachable);

  5. 若仍有多个 ToS=0 的路由,则选择偏好值(preference value)最大的路由;

  6. 选择最新的路由

参考

  1. 4.8. Routing Tables (linux-ip.net)

  2. ip-route(8) - Linux manual page (man7.org)




推荐本站淘宝优惠价购买喜欢的宝贝:

image.png

本文链接:https://hqyman.cn/post/10501.html 非本站原创文章欢迎转载,原创文章需保留本站地址!

分享到:
打赏





休息一下~~


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

请先 登录 再评论,若不是会员请先 注册

您的IP地址是: