
Linux的网络功能异常强大,包含了完整的路由功能,一台Linux主机配置多个网卡连上不同的网络,经过配置就能当路由器使用。
路由表
路由表是一组路由规则,通常以表格格式查看,用于确定通过网络传输的数据包将被定向到何处。
Linux系统支持多张路由表,可以使用策略选择使用不同的路由表。
路由表的编号
路由表都有一个数字编号,取值范围1 到 2^32-1,如果想用字符串引用,可以在 /etc/iproute2/rt_tables中定义(路由表是否存在与此文件无关,只是数字编号和字符的对应关系定义),Linux系统中一般已经预定义了一些路由表及名称:
这里几个编号是保留的,我们自定义路由表不应使用。
local表由系统内核管理和生成,我们不应编辑。
main表是主要的路由表,一般的配置就在这里。
default表一般为空,是历史原因为兼容某些程序保留的。
查看系统中有哪些路由表:
# 显示出所有的表名或表ID
# 支持-P perl正则表达式的环境
ip -d route show table all | grep -Po 'table \K[^\s]+' | sort -u
# 支持-E 参数,扩展正则表达式的环境
ip -d route show table all | grep -Eo 'table [^\s]+' | awk '{print $2}' | sort -u
# 只显示表ID加-N参数,并不是所有ip命令都支持
ip -d -N route ......如图所示,有个编号200的路由表,它并没有名字。
参数解释:
ip参数 -d detail 显示细节;-N number 数字化显示,不进行易读翻译,就显示路由表ID而不是名称了
grep参数 -P PCRE格式的正则;-o 只显示匹配的部分,而不显示整行;
perl格式正则 \K 代表重置匹配的起点,也就是前边要有'table '但其并不出现在结果中;[^\s]+匹配至少一个非空白字符
sort参数 -u unique,去重;
路由表的内容
查看:ip -d route show table main
(table main可以省略,默认就是它)
上图所展示信息的意义可以通过man ip-route查看,这里做简单的介绍。
第1列 指记录类型(Type)
unicast 指单播路由,按前缀最长匹配。除此之外可能的值还有local、broadcast、anycast、multicast、throw、unreachable、blackhole、 prohibit等。
第2列
目标IP或网络。default指默认路由0.0.0.0/0; 带掩码的指一个网段的路由;还有到特定IP的路由。
后边的是成对出现的配置项和配置值:
via 指定下一级路由器的地址,也就是网关地址;
dev 指发送数据的设备名;
proto 指配置的路由的协议或方法,dhcp是由dhcp服务配置的,kernel是由内核配置的,static是手工配置的等;
scope 指到目标的距离,globle代表到目标需要至少一个路由器(hop)中转、link代表目标在本地网络上,也就是在一个网段是直连的、host代表目标在本机上;
src 发往目标时,如果程序没有手动绑定源IP,则使用路由条目的src值;
metric 到目标的成本,值低的优先选择,成本可能由跳数,延迟,带宽,稳定性等相关数据生成。
下边解释下这几条记录:
unicast default via 172.29.127.253 dev eth0 proto dhcp scope global src 172.29.114.8 metric 100
这是个单播路由,default表明其为默认路由,也就是如果匹配不上表里的其他记录,就按这条走;数据会通过eth0接口发给网关 172.29.127.253 ,如果是本机生成的数据包,源IP建议为172.29.114.8;此条路由是DHCP服务生成的,走这条路的成本是100。
unicast 172.29.112.0/20 dev eth0 proto kernel scope link src 172.29.114.8
单播路由,目标IP属于172.29.112.0/20的走此配置;如果是本机生成的数据包,源IP建议为172.29.114.8;通过eth0设备发出;内核生成的此记录;
删除路由条目
首先ip route show table <table_name> 查看条目
然后ip route del <对应条目复制过来> 即可
多路径路由
如果设备有多个出口,可以使用多路径路由(Multipath Routing):
ip route add default scope global nexthop via 172.16.0.2 dev enp0s8 weight 1 nexthop via 10.0.2.1 dev enp0s3 weight 2
注:但这并不能让流量按weight比重分配,因为这个是基于路由的,且路由是有缓存的,只是在查路由表的时候起作用。
策略路由
路由表只是根据目标IP来选择路由。而Linux支持依据源地址、ToS(Type of Service)标签, fwmark (firewall mark,数据包在内核中的数据结构上的一个标签), 还有数据包传入的接口名等选择路由表,这就是策略路由。
这些策略被保存在 routing policy database(RPDB)中,查看当前的策略:
ip rule show
第一条策略,从任意地址过来的数据包,查local路由表,没有匹配的记录就查下一条策略;下一条策略也是所有的数据包查main路由表,main路由表一般会有默认路由肯定会匹配上,所以下一跳default路由表的策略一般就没机会了。
上边这个策略是Linux默认的初始策略,如果有特殊需要我们可以添加自定义策略。
添加删除策略
命令的格式是 ip rule { add | del } SELECTOR ACTION
SELECTOR用于筛选流量,ACTION用于执行动作。
SELECTOR最前边可以加not取反。
容易理解的筛选参数有:from(源IP),to(目的IP)、iif(输入网卡)、sport(源端口)、dport(目的端口)、ipproto(协议类型tcp、udp)等。
fwmark,是firewall mark的意思。通过iptables或nftable等防火墙工具,用一定的规则给数据打标签,然后路由规则使用这个标签区分流量,也就是说防火墙能区分的流量,路由就能区分。
uidrange,使用用户ID范围匹配流量。不过要注reverse path filter参数要配置散模式 net.ipv4.conf.tun1.rp_filter=2。
tos(type of service)或 dsfield TOS
IP数据包头有一组Differentiated Services Code Point (DSCP)标记,此项就是根据这个标记来区分数据流量。这个Service类型简单来说就是标记此流量承载的服务是低延迟的,高吞吐的,高可靠的等等。
ACTION主要是:
table, 指定路由表名。
protocol, 谁安装的此规则。比如zebra
nat, 指定nat地址
realm,为此流量打上realm编号标签(SRC/DST),用法不详。
goto , 跳转到某个规则
还有两个 SUPPRESSOR 抑制器用于ACTION:
suppress_prefixlength NUMBER
拒绝前缀长度小于等于NUMBER的。
suppress_ifgroup GROUP
拒绝使用属于接口组group的设备的路由决策。
其他参数:
type, 指定类型,默认是unicast
priority, 指定规则优先级编号,设置或查询rule用。
删除策略
ip rule show
ip rule del <对应条目复制过来>
或
ip rule del priority 32764 # 按优先级编号删除示例:
如果上图,服务器有两个接口eth1、eth2,通过两个ISP连接到互联网,我们想让ISP1过来的流量从eth1返回,ISP2过来的流量从eth2返回。过来好说,关键是返回。返回的时候,目标IP是对方的IP,并不能提前按目的IP写好路由,这时候就需要按源IP写路由了。
首先给ISP1和ISP2对应两个路由表id:
echo -e "100 ISP1\n200 ISP2" >> /etc/iproute2/rt_tablesISP1路由表配置ISP1为默认出口:
ip route add default via 100.0.0.1 table ISP1
ip route add 100.0.0.0/24 dev eth1 src 100.0.0.109 table ISP1ISP2路由表配置ISP2为默认出口:
ip route add default via 200.0.0.1 table ISP2
ip route add 200.0.0.0/24 dev eth2 src 200.0.0.209 table ISP2然后写策略路由:
ip rule add from 100.0.0.109 table ISP1
ip rule add from 200.0.0.209 table ISP2总结:
Linux系统可以使用IP数据包的各种信息生成策略,选择不同的路由表,不同的路由表按目的地址做不同的出口规划,最终实现了对路由的精准的自定义规划。
参考资料:
https://lartc.org/lartc.html
http://linux-ip.net/html/routing-tables.html
http://www.embeddedlinux.org.cn/linux_net/0596002556/understandlni-CHP-30.html