路由相关的一些概念

路由器连接着多个网络并且内部存储着到达各个网络的路径信息(路由表),当网络中的数据包想要跨网络传输时,需要经过路由器的查表转发才能到达目的地。

路由的构成

最基础的路由查表流程就是根据报文前缀为报文找到合适的下一跳地址以及出口设备,不难想到路由最基础的组成元素中包含前缀、下一跳信息,但不仅如此,路由还包含其它的组成元素,通过ip route help命令的输出可以发现路由组成非常复杂,稍稍简化一下,路由的组成元素可以简单归纳如下:

[prefix] [table] [tos] [priority] [scope] [type] [nexthop]

上述几个组成元素中prefix/table/tos/priority/scope/type在路由查表过程中将作为匹配条件,而nexthop将作为查找结果。为了确保匹配结果的唯一性,系统中(确切的说是同一网络命名空间中)不会也不允许存在prefix/table/tos/priority/scope/type完全相同的两条路由。

路由如何生成

通常公网中的那些大型路由器或者一些企业级的路由器都是运行了路由协议的,路由协议会根据网络拓扑的变化动态的更新路由表。而写者工作中常见的家用路由器通常不运行路由协议,它们通常只连接着两个网络(一个内网,一个通向公网的外网),路由表的维护工作不是那么复杂,通常由路由器上的网络进程来维护(比如openwrt中常用的netifd)。

ip route命令的使用方法

路由表存储于内核,应用进程可以通过ip routeroute命令或者route netlink socket来添加、删除、更新路由表,route命令是老版本的工具,推荐使用ip route来操作路由,ip route功能更加丰富。
ip route的参数有很多,写者将常见的一些参数及用法归纳如下:

ip route <action> <prefix> [table] [tos] [priority] [scope] [src] [type] <nexthop [dev] [via]>

action: 可取值为 add(新增) | del(删除)| replace(替换)| change(替换)| append(追加)
prefix: 前缀和前缀长度,用于指示该路由可通向哪个目的网络,比如192.168.1.0/24
table: 路由表id,用于指定路由所属路由表,系统在不支持多路由表时仅有local/main两张表,支持多路由表时则有local/main/default以及其它客制化表,取值0~(maxval(u32)-1)
tos: 若路由指定了tos,则路由查找时,会根据报文ip报头中的TOS字段或者ip socket option (IP_TOS)来匹配路由,取值0x00~0xff
priority|metric|preference: priority会影响路由表插入路由表的先后顺序,同理会影响到路由查找时的先后顺序, 取值0~(maxval(u32)-1)
scope: 路由scope指示到达目的网络的`距离`,取值0~255
src: 在包输出路径上,若没有指定源地址(比如socket 绑定anyaddr),则可能会使用src指定的地址作为源地址
type: 路由的类型,该类型影响路由查找后对报文的处理行为,可取值unicast | local | broadcast | multicast | throw | unreachable | prohibit | blackhole | nat
nexthop: 指示下一跳的信息,dev用于指示出口设备,via用于指定网关地址,若目的网络不需要通过网关就能到达,则可以不传递via

上述的参数中仅`action`,`prefix`和`nexthop`是必要的,其它参数不传递时`ip route`会采用默认值

系统中不允许存在prefix/table/tos/priority/scope/src/type完全相同的两条路由,故我们使用ip route往系统中添加路由规则时,需要注意传递给ip route的参数不能与已存在的路由存在冲突,若存在冲突则会添加失败,写者简单总结了ip route的一些规律,如下:

  • 使用ip route add时需要确保[prefix table tos priority]这部分参数与系统中已有路由的参数不能完全相同,否则无法添加成功。
  • 使用ip route append时,允许[prefix table tos priority]这部分参数与系统中已有路由的参数相同,但需要确保[scope src type nexthop]这部分参数与系统中已有路由的参数不完全相同,否则无法追加成功。
  • 使用ip route replace/change时,系统通过[prefix table tos priority]来查找路由,并将老路由的[scope src type nexthop]替换,当未查找到匹配的路由时,replace指令会导致新的路由生成,而change指令则会报错。

路由查找的方式

路由查找的过程简单分为三段:查找路由表,匹配前缀,匹配其它参数
路由查找时会使用数据包携带的参数(比如IP报头中的源/目的IP、tos、入口设备以及经过netfilter时打上的mark信息等)与路由表中的路由进行匹配,匹配时会先根据策略路由确定路由表,然后在特定路由表中匹配prefix,随后再匹配tos/scope/type等参数。

匹配前缀的方式

在进行prefix匹配时使用的是最长前缀匹配法,比如说路由表中有如下三条路由:

1:	192.0.0.0/8 dev nbif1  scope link 
2:	192.168.0.0/16 dev br0  scope link 
3:	192.168.6.0/24 dev nbif0  scope link 

当目的地址为192.168.6.1的报文进入系统时,光从前缀的角度看,上述三条路由都是能够匹配上的。但根据最长前缀匹配法内核会优先查找3号路由,若3号路由的tos/scope/type参数全都匹配则命中该路由,若没有匹配上则内核会尝试查找2号路由,2号路由匹配不上再查找1号路由。

路由的 priority

通过ip route添加路由时可以指定priority,而priority可以影响路由的查找顺序,比如有如下两条路由:

// metric即是priority
1:	192.168.0.0/16 dev br0  scope link  metric 2 
2:	192.168.0.0/16 dev nbif0  scope link  metric 3 

当目的地址为192.168.6.1的报文进入系统时,内核会根据priority值从低到高来查找,先查找1号再查找2号。
需要注意的是,priority仅在前缀值相同时才有意义,前缀不同时会先按照最长前缀匹配法匹配前缀,在前缀相同的路由中再根据priority来决定查找顺序。
其实在内核中,前缀相同的路由会被放入同一链表中,而priority的值将决定路由在链表中的位置,值越小越靠前,在查找路由时也就越先被匹配。

策略路由

当linux不支持策略路由时,系统中仅有mainlocal两张路由表,路由查找仅在两张表中进行。当linux支持策略路由时(打开内核编译选项CONFIG_IP_MULTIPLE_TABLES),则系统允许存在RT_TABLE_MAX(0xFFFFFFFF)张路由表(网络上大多描述的是linux最多支持255张路由表,这个值可能与内核版本相关,写者阅读的5.4.225版本内核对路由表id的最大值是0xFFFFFFFF)路由查找可以在多张表中进行,同时系统管理员可以向系统配置更加丰富的策略用以控制路由查找的行为,进而达到分流的目的。
在应用层可以通过ip rule指令来操作路由策略,ip rule相较于ip route更为简单清晰,可直接通过ip rule help查看使用方式,ip rule的两个核心参数便是SELECTORACTION

#ip rule help
Usage: ip rule [ list | add | del | flush | save ] SELECTOR ACTION
       ip rule restore
SELECTOR := [ not ] [ from PREFIX ] [ to PREFIX ] [ tos TOS ] [ fwmark FWMARK[/MASK] ]
            [ iif STRING ] [ oif STRING ] [ pref NUMBER ]
ACTION := [ table TABLE_ID ]
          [ realms [SRCREALM/]DSTREALM ]
          [ goto NUMBER ]
          SUPPRESSOR
SUPPRESSOR := [ suppress_prefixlength NUMBER ]
              [ suppress_ifgroup DEVGROUP ]
TABLE_ID := [ local | main | default | NUMBER ]

参数释义如下
SELECTOR:SELECTOR用于指定匹配参数,包转发和输出路径上查找路由时会传递报文相关参数到路由子系统(比如目的、源ip,tos,输出输入设备等),当报文相关参数与SELECTOR指定的参数匹配时才会执行ACTION
	from: 该参数指定的前缀将用于与报文的源ip进行匹配
	to: 该参数指定的前缀将用于与报文的目的ip进行匹配
	tos: 该参数与ip报头携带的tos字段或者IP_TOS(socket ip option)进行匹配
	fwmark: 该参数与sk_buff携带的mark(多来自于iptables PREROUTING mark)或者SO_MARK (socket option)进行匹配
	iff/oif: 用以匹配报文的输入输出设备
	pref: 用于指定路由策略的 priority, 它将决定策略路由被查找时的优先级,若不指定则系统默认选择一个priority
	
ACTION: 该参数描述SELECTOR匹配上后的行为
	table: 表示查找某号路由表
	goto: 表示跳转到另一条路由策略(比如goto 2,会跳转到pref为2的策略)

策略路由的pref

系统以链表的形式组织所有路由策略,每条策略都可以配置一个优先级pref,优先级将决定策略在系统链表中的位置, pref取值范围0-0xFFFFFFFF,pref值可以重复,系统根据pref值从小到大的顺序来组织所有策略,pref相同的策略则根据插入时间来决定排列顺序,先插入的策略排前面。0,0x7FFE,0x7FFF三个值对应的策略由系统默认添加, 分别通向local, main,default表,默认的策略路由如下:

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

在查找路由时,内核会遍历所有的路由策略,pref越小的策略先匹配,若在某条路由策略指定路由表中查找到了合适的路由,则不再匹配剩余策略。

添加路由策略时若不指定pref, 则系统会根据系统现有策略的优先级来确定一个pref值,确定规则为:第二高优先级的策略的pref - 1。

路由的scope

路由的scope表示:通过该路由到达目的网络的’距离’是多少。
路由的scope可以通过ip route指令配置,如果不指定,则ip route会根据路由的类型以及是否指定网关等因素来选择一个合适的scope。scope取值0~255,值越大表示距离越近,内核对某些scope值赋予了特定含义,如下:

/* rtm_scope

   Really it is not scope, but sort of distance to the destination.
   NOWHERE are reserved for not existing destinations, HOST is our
   local addresses, LINK are destinations, located on directly attached
   link and UNIVERSE is everywhere in the Universe.

   Intermediate values are also possible f.e. interior routes
   could be assigned a value between UNIVERSE and LINK.
*/
enum rt_scope_t {
	RT_SCOPE_UNIVERSE=0,
/* User defined values  */
	RT_SCOPE_SITE=200,
	RT_SCOPE_LINK=253,
	RT_SCOPE_HOST=254,
	RT_SCOPE_NOWHERE=255
};

linux内核查找路由时,会向查找函数传递参数scope_in,查找函数遍历路由的过程中会忽略那些scope值小于scope_in的路由。

nexthop的scope

nexthop的scope表示本机到达下一跳的’距离’是多少。

nexthop的scope由内核自动配置,它的值受路由的scope以及是否使用via参数来指定nexthop的地址(网关地址)等因素的影响,大体规则如下:

  • 路由的scope为RT_SCOPE_HOST,则nexthop的scope为RT_SCOPE_NOWHERE
  • 未使用via指定网关,路由的scope小于等于RT_SCOPE_LINK,则nexthop的scope为 RT_SCOPE_LINK
  • 使用via指定网关,路由的scope等于RT_SCOPE_LINK,使用via指定的地址去路由表中查找scope大于等于RT_SCOPE_HOST的路由,nexthop的scope由查找到的路由决定
  • 使用via指定网关,路由的scope小于RT_SCOPE_LINK,使用via指定的地址去路由表中查找scope大于等于RT_SCOPE_LINK的路由,nexthop的scope由查找到的路由决定

multiple nexthop

使用ip route添加路由时,可以为单条路由指定多个下一跳(需要内核使能multipath, CONFIG_IP_ROUTE_MULTIPATH)
指定多个下一跳时,下一跳信息需要使用nexthop关键词来配置,参考如下示例

ip route add 192.168.0.1 table 12345 nexthop dev ens33 nexthop dev ens37
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值