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