通过配置不同的策略路由,让每个报文在寻找路由时,首先让它寻找它所匹配的策略,根据策略所指定的路由表,在对应的路由表再查找路由条目。可见,真正意义的策略路由,需要多路由表的支持,否则如果只有两个路由表,没有什么意义。不过理解策略路由的意义比较重大。
和路由表条目一样,策略同样是由用户操作,同样是通过路由netlink套接字,如下图:
策略在内核中由结构体structfib_rule描述,它包括普遍适用的需要匹配的内容,其实就是两个内容,入接口和skb标记(mark),在策略匹配过程中,还需要根据具体的L3协议去做具体协议的匹配,比如IPV4需要调用函数fib4_rule_match,匹配源目IP地址及其掩码和tos,在上面的匹配都通过后,可以认为该报文匹配此策略成功,并在该策略指定的路由表中查找路由条目,所以策略路由的目的是找到该报文应该查找的路由表,所以说在只有2个路由表的情况下策略路由的意义不大。
下图普遍适用的需要匹配的结构体struct fib_rule的描述图:普遍适用的需要匹配的内容,其实就是两个内容,入接口和skb标记(mark),其余是具体协议自身需要匹配的内容,下图是策略匹配的实现:
skb标记是策略路由中最灵活的内容,它实现了可通过传输层协议甚至应用层协议字段选择不同的路由,对于输入报文,通过使用iptable工具,使报文在进入网络层寻找路由之前的netfilter中被打上相应的标记,使报文在策略匹配时匹配到不同的策略,进而匹配到不同的路由表,同样的对于输出报文,在socket层通过setsockopt接口使报文在传输层之前即打上相应的标记,进而匹配到不同的策略的不同的路由表。
比如使用iptable工具输出如下:
iptables -tmangle -A PREROUTING -p udp --dport 53 -s 10.89.9.0/24 -j MARK --set-mark2
这条命令是将来自10.89.9.0/24的UDP目的端口是53的数据包分别标记为2;
然后使用iproute2工具输出如下:
ip rule addfwmark 2 table XXX
加入一条路由策略,标记为2的报文进入路由表XXX,进而可以在路由表XXX中加入路由条目,控制该报文的下一跳。
对于IPV4协议,所需做的匹配由结构体fib4_rule描述及其匹配操作如下图:
可见其实需匹配的就是源目IP及其掩码、tos。
若匹配策略成功,则在该策略指定的路由表中查找路由条目,即调用该路由表的tb_lookup方法。
在默认情况下,内核会在初始化时创建三个默认的策略,这三个策略没有任何匹配条件即所有报文还是按部就班的查找路由表,即首先查找本地路由表,然后查找转发路由表,下图是由iproute2工具查看的默认创建的三个策略