Linux 路由和多网卡网关的路由出口设置

时间:2024-03-10 09:06:34

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 的脚本也可以的。