Linux 路由和多网卡网关的路由出口设置
刚刚见到一个网络方面的要求,有个 Linux 服务器接了两条线,一条连接内网 192.168.0.0/24 ,一条连接电信的网 192.168.1.0/24 。这两个网络网关分别为 192.168.0.1 和 192.168.1.1, 都是可以上互联网的,但是要求服务器上的应用使用不同的 IP 访问不同的网,进行流量分离。在路由层面是可以实现这些功能的,需要略微复杂的路由设置。
路由规则和路由表
Linux 中的路由由路由规则和路由表组成。路由规则指定当数据包满足规则时,应转交到哪个路由表;路由表根据数据包的信息,选择下一跳。
可通过 ip rule
看当前的路由策略,如 ::
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
这里也可以看出在内核中最多支持 32768 条路由规则。这里的 main 表是系统主要的路由表,所有的路由规则都写在这个表中。查看这个表 ip route list table main
::
default via 192.168.0.1 dev eth0
192.168.0.1 dev eth0 proto kernel scope link src 192.168.0.100
192.168.1.1/24 dev eth1 proto kernel scope link src 192.168.1.100
Linux 中支持 256 个表,编号为 0 到 255 ,可直接使用编号操作,也可使用编号的别名操作,编号和其别名的对应关系在 /etc/iproute2/rt_tables
文件中。
多网关路由设置
由 main 路由表可见,当前默认的网关是 192.168.0.1
,为内网的网关。如果要为 192.168.1.0/24
这个网络上的应用设置默认网关,就需要建立特定的路由规则和路由表。
现在使用 200 编号的路由表,先建立一个规则让 192.168.1.0/24
这个网络所有应用的流量进入 200 表 ::
# 先清理掉这个 200 表的所有规则
ip rule del table 200 || :
# 直接用 192.168.1.0/24 整个子网,也可用当前 IP 来过滤
ip rule add from 192.168.1.0/24 table 200
然后对 200 表设立路由表规则 ::
# 默认规则网关 192.168.1.1 网卡 eth1
ip route add default via 192.168.1.1 dev eth1 table 200
验证一下从 192.168.1.100 的包的路由选择
ip route get 8.8.8.8 from 192.168.1.100
# 结果为
8.8.8.8 via 192.168.1.1 dev eth1 src 192.168.1.100
cache
ip route get 8.8.8.8 from 192.168.0.100
# 结果为
8.8.8.8 via 192.168.0.1 dev eth0 src 192.168.0.100
cache
设置成功。
保存设置
以上的路由设置会在开机后被清理,因此需要将它保存下来。ip route save
可保存表的信息,如果表的项非常多,这个操作起来非常简单;ip rule
没有专门的保存命令,可自己写点脚本。
先保存 200 表的信息 ::
ip route save table 200 > /root/route-200.rules
恢复时可使用 ::
sudo ip route flush table 200 && sudo ip route restore table 200 < /root/route-200.rules
对规则的保存可使用以下的小脚本 ::
#!/bin/sh
# ip-rule-dump.sh
# 参数: table 编号或别名,无参数时 dump 除 local 之外的全部规则
# 获取 table 别名
if [ -n "$1" ]; then
name=$(grep -v \'^[[:blank:]]*#\' /etc/iproute2/rt_tables |\
grep "[[:blank:]]*$1[[:blank:]]" | head -n 1 | awk \'{print $2}\')
[ -z "$name" ] && name="$1"
fi
[ -z "$name" ] && name=".*"
# 获取并使用别名过滤规则
ip rule show | grep -v "^0:" | grep -oP "from.*[[:blank:]]$name[[:blank:]]$" |\
sed -e \'s/lookup/table/g\'
然后保存 rule ::
./ip-rule-dump.sh 200 > /root/rule-200.rules
对规则的恢复可使用以下的小脚本 ::
#!/bin/sh
# ip-rule-restore.sh
# 参数: dump 文件路径
if [ -n "$1" ] && [ -f "$1" ]; then
cat $1 | while read line; do
sudo ip rule add $line
done
fi
那么恢复时使用 ::
sudo ip rule del table 200 >/dev/null 2>&1 || :
sudo ./ip-rule-restore.sh /root/rule-200.rules
开机加载
如果需要在网卡准备完成就加载,就需要在 /etc/network/interfaces
的对应网卡上,加上 post-up 的操作了,如 ::
iface eth1
...
post-up ( ip rule del table 200 >/dev/null 2>&1 || : ) && \
bash /root/ip-rule-restore.sh /root/rule-200.rules && \
ip route flush table 200 && \
ip route restore table 200 < /root/route-200.rules
或者写成 upstart 或 systemd 的脚本也可以的。