本系列文章基于 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 重定向添加)。此外,该值还可以是 bgp
、ospf
这类动态路由协议。该值可能是整数值或者一个字符串值,字符串值都可以在 /etc/iproute2/rt_protos
中找到;
src <源地址>
:在使用本条路由,向目的地发送数据包时所需采用的 IP 地址;
<附加信息>
代表多个可选项,常见的有:
scope <scope>
:定义这条路由的范围。global
表示有网关的单播(unicast)路由,link
表示直连的单播或广播(broadcast)路由,host
表示本地(local)路由。该值可能是一个整数值或者是字符串值,字符串值应该能在/etc/iproute2/rt_scopes
中找到metric <整数>
:表示路由的优先级,数字越小优先级越高。最小值为 0 ,最大值为 65535table <表名/数字>
:如果一条路由不属于 main 表,则会在这里指出该路由所属的路由表
路由记录还可以有个表示路由类型的前缀,该字段能说明路由用途以及特性。类型有下面这些:
unicast(单播):标准类型,表示把数据发往一个特定的目的地 IP 地址。通常省略不显示;
unreachable(不可达):目的地不可达。发往该地址的数据包会被丢弃,ICMP 会返回
host unreachable
,发送代码会报错EHOSTUNREACH
;blackhole(黑洞):目的地不可达,数据包会被无声丢弃(discarded silently),发送代码会报错
EINVAL
;prohabit(禁止):目的地不可达,数据包会被丢弃,ICMP 会返回
communication administratively prohibited
。发送代码会报错EACCES
;local(本地):目的地是当前主机,数据包会回环发送;
broadcast(广播):目的地是广播地址,数据包作为链路广播发送,通常是向本地网络广播;
throw(抛弃):这是个特殊路由,如果策略规则选择了该路由的路由表,则系统会装作是没有找到对应路由。ICMP 会返回
net unreachable
,发送代码会报错ENETUNREACH
;nat(网络地址转换):该路由已在 2.6 内核后停止支持。这是个特殊的 NAT 路由。目的地地址是假地址(外部地址),需要在转发前转换为真实(内部)地址;
anycast(任播):尚未实现。目的地是本主机的
anycast
地址。和local
只有一个区别:该地址不能被用于任何数据包的源地址;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 进行比对,然后选择符合条件最多的一个,对比顺序为:
目的地地址和路由条目 prefix 的相符程度;
数据包和路由条目 ToS 的匹配;
选择 ToS=0 的路由
举例来说,如果数据包匹配到了多个可选路由,则按下面的顺序来选择出一个路由:
选择包含子网掩码在内的,prefix 匹配长度最长的路由;
如果有一个路由的 ToS 与数据包的 ToS 相符,则直接使用这个路由;
选择 ToS=0 的路由;
如果没有 ToS=0 的路由,返回一个错误(不可达 unreachable);
若仍有多个 ToS=0 的路由,则选择偏好值(preference value)最大的路由;
选择最新的路由
参考
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://hqyman.cn/post/10501.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~