基础知识
默认路由是一种特殊的静态路由,目的网段为 0.0.0.0/0,当不确定你的目的地址时(如互联网访问)可以配置一条默认路由。
路由器在选择路由条目时,如果有两条去往相同目的网络的路由,会比较路由条目的优先级,选择优先级高的进行转发(值越小,优先级越高)。默认优先级举例:直连路由优先级0;静态路由优先级60;OSPF路由优先级10。
当路由表中有多条目的地址相同的路由时,会选择子网掩码最长的进行转发,若子网掩码相同,就根据优先级(metric)进行选路。
在配置静态路由时一定要注意它的单向性, 也就是要使双方能相互访问,须同时配置往返路径的两条静态路由,也就是通常所说的必须同时有回程路由。
双网卡,指定应用走哪个网卡
如果PC主机上插了两块物理网卡且都启用状态,那么就会生成两条默认路由:
default via 192.168.4.1 dev enp4s0 proto static metric 100 default via 192.168.3.1 dev enp3s0 proto static metric 101
由于目的地址相同且第一条优先级高,因此主机上的所有应用都会走 192.168.4.1 网卡出去。
此时如何给主机内不同的应用分配不同的网卡?咨询了下网工,说控应用层要用专门的负载设备。后来结合具体场景发现不需要购买额外设备,设置下静态路由就好了。
配静态路由前,要先分析自己的场景,假设双网卡的服务器部署了2个Docker应用(A和B),A应用不对外提供服务只与阿里云固定IP的服务器通信(如访问数据库),B应用暴露服务器接口需要对外提供服务。
解决办法:由于A应用只会与固定外网IP通信,因此配置一条静态路由即可,无需用默认路由,将目的地址指向阿里云固定IP,网关地址两张网卡里随便选一个,配好后必须删除选择的那张网卡的默认路由(如果不删除,一旦另一张网卡的默认路由优先级低于这张时,数据包永远无法出去了,因为永远会选择这张错误的网卡的网关出去),这点很重要。对于B应用来说,由于要提供服务,因此目的地址是不固定的,数据可能会发送给任何互联网上的人,因此必须使用默认路由。
这种方式其实有个弊端,若A应用访问的固定IP改用CDN加速,或A应用有到第三方带域名的服务时(如OSS上传),由于CDN和OSS服务的IP不是固定的,也咨询了阿里云说没有一个大范围固定网段的,因此静态路由不适合这两种情况。解决办法就是使用策略路由,它可以根据源地址来选路。
静态路由的添加删除
# 1. 添加到主机的路由 route add –host 192.168.1.10 dev eth0 route add –host 192.168.1.10 gw 192.168.1.1 route add -host 192.168.1.3 gw 172.16.0.1 dev eth0 # 其中dev eth0可以省略,但 gw 不能省,省了测试下来会无法路由的 # 2. 添加到网络的路由 route add –net 192.168.1.0/24 gw 192.168.1.1 route add –net 192.168.1.0/24 dev eth1 route del -net 192.168.32.7/32 gw 172.18.0.200 # 删除路由 # 3. 添加默认路由 route add default gw 192.168.1.1 # 4. 删除路由 route del –host 192.168.1.10 dev eth0 route del default gw 192.168.1.1 route del -net 192.168.32.7/32 gw 172.18.0.200 # 删除路由 # 5. 第一种查看路由 route -n # 6. 第二种查看路由(结果可放 /etc/sysconfig/network-scripts/route-ethx 里,格式一样) ip route
小提示:静态路由配置好后,测试是否生效可以分别用 traceroute xxx
、traceroute yyy
两个命令来测试对比,其中 xxx 是静态路由的目的地址,yyy则不是,看他们经过的网关有何区别即可。
策略路由
对比传统的基于数据包目的地址的路由算法,基于策略的路由算法更加灵活。Linux是在内核2.1开始采用策略性路由机制的。
策略路由算法引入了多路由表以及规则的概念,支持按数据报属性(源地址、目的地址、协议、端口、数据包大小、内容等规则)选择不同路由表。
使用策略路由来配置双网卡的主机,让不同的Docker应用走不同的网卡,实在太有用了。
policy-route.sh:
#!/bin/bash # 配置策略路由,让 172.18.0.0/16 网段的 Docker 应用走 enp4s0 这张网卡 # 第一步:先在路由表 30000 上添加一条默认路由,指向 enp4s0 网关 ip route add 0/0 via 192.168.3.1 dev enp4s0 table 30000 ip route list table 30000 # 第二步:配置规则,172.18.0.2 是 Docker应用的IP,让它的包走路由表 30000,优先级设置的高于 main 表,设为 30001 吧 ip rule add from 172.18.0.2/32 table 30000 pref 30001 ip rule #注意: #(1)重启电脑后,策略路由的规则和 路由表 30000 都会丢失! #(2)添加、删除规则后,必须重启下Docker应用,否则Docker应用网络会出问题,若此脚本在Docker应用起来前执行就不需要重启了。 #(3)设好后,主机直连拨号路由器的Wifi似乎没有出现卡的现象了,若连作为交换机的二级路由器的Wifi网络就特别卡,把Wifi_5G关了仅保留Wifi_2.4G就好了。
ip rule:
删除策略路由:
# 删除路由表中的路由项: ip route del default table 30000 ip route del 192.168.8.0/24 table 30000 # 删除策略路由规则: ip rule del prio 30001 ip rule del from 172.18.0.0/16 ip rule del table 30000 ip rule del from 172.18.0.0/16 table 30000 prio 10
策略路由参考:
(1)Linux策略路由–原理、配置和应用
(2)Linux系列—策略路由、ip rule、ip route
路由重启持久化
个人推荐写一个开机启动服务,调用上面的 policy-route.sh 脚本即可实现持久化。
以 Ubuntu 22 为例,下面创建一个 rc-local.service 服务:
1. 创建 rc-local.service 文件
sudo cp /lib/systemd/system/rc-local.service /etc/systemd/system
然后修改 /etc/systemd/system/rc-local.service
,在文件最下方添加如下两行:
[Install] WantedBy=multi-user.target Alias=rc-local.service
2. 创建 rc.local 文件
创建 /etc/rc.local
,里边写自己想要运行的命令,例:
#!/bin/sh #echo "This is test" > /tmp/my.log /home/service/install/policy-route.sh exit 0
给 /etc/rc.local
加上可执行权限:sudo chmod +x /etc/rc.local
。
然后就可以重启电脑,此时输入 ip rule
就已经创建出策略路由规则了。
用 systemctl status rc-local.service 命令检查服务运行是否报错了:
命令参考:
systemctl enable rc-local.service systemctl start rc-local.service systemctl status rc-local.service
traceroute
# 安装 traceroute apt install traceroute # 查找到 baidu.com 的路由 traceroute baidu.com
traceroute 命令将跟踪发往远程系统的 IP 包所经过的路由。可以使用这个命令查找所有的路由配置错误以及路由路径错误。如果无法到达特定的主机,则可以使用 traceroute 来查看发往远程主机的包所经由的路径以及可能出现故障的位置。
traceroute 命令还显示在通向目标主机的路径上每个网关的往返时间。此信息对于分析两个主机之间何处出现通信缓慢非常有用。
参考
网络工程师入门,如何配置静态路由?
简析静态路由下一跳和出接口区别
Linux系统添加永久静态路由的方法
Linux 双网卡双IP配置
FAQ
在为接口分配IP地址时,为什么需要指定子网掩码?
(1)路由器使用接口上配置的IP地址和掩码来确定该接口所连接的网络。主机将使用掩码来确定目标地址是否与主机位于同一网络上。如果它在其他网络上,则主机必须将第2层的流量发送到配置的网关,而不是直接发送到目的地。例如接口地址 192.168.203.82/24 属于 192.168.203.0/24 这个网络(网段)。
(2)子网掩码可以分离出IP地址中的网络地址和主机地址,那为什么要分离呢?因为两台主机要通信,首先要判断是否处于同一网段,即网络地址是否相同。如果相同,那么可以把数据包直接发送到目标主机,否则就需要路由网关将数据包转发送到目的地。