201706 月发表在 分享

08配置 Linux 策略路由以允许双网卡双地址访问

现有一台 Linux 网关,拥有两块网卡,一块接入百兆校园网(222.24.24.2/24),一块接入千兆专线(10.0.0.2/24)。因为专线带宽远高于校园网,所以默认路由指向了专线。路由表如下所示:

$ ip route
default via 10.0.0.1 dev eth1  proto static  metric 1024
10.0.0.0/24 dev eth1  proto kernel  scope link  src 10.0.0.2
222.24.24.0/24 dev eth0  proto kernel  scope link  src 222.24.24.2

由于保留了校园网地址,所以理论上可以同时使用校园网地址 222.24.24.2 和专线地址 10.0.0.2 访问到这个网关。然而实际情况却不一样。测试发现,222.24.24.2 地址只能通过同网段电脑正常访问。不同网段的地址并不能通过 222.24.24.2 登录到网关。原因十分简单:通过其它网段地址发往 222.24.24.2 的数据包,会通过网关 222.24.24.1 发到 eth0,然后返回的数据包会根据路由表选路通过 eth1 发往千兆专线网关 10.0.0.1,然而 10.0.0.1 是一个防火墙,防火墙由于没有完整地看到连接建立过程,对数据不予放行,于是无法正常建立 TCP 会话。
拓扑.png

知道了原因,下面就讲一讲如何解决这个问题。解决这个问题需要的是一条策略路由,通过 222.24.24.1 传入的连接,向外发送的数据包应当通过 222.24.24.1 转发。我使用 iptables 的 mangle 表以及 Linux 的路由策略系统。

先将 eth0 的地址保存到 shell 变量中:

INADDR_ETH0=$(ip -4 -o addr list eth0  | awk '{print $4}' | cut -d/ -f1)

来自 eth0,发往校园网地址的会话建立数据包,打上连接标记 222:

iptables -t mangle -A PREROUTING -i eth0 -d $INADDR_ETH0 -m state --state NEW -j CONNMARK --set-mark 222

从校园网地址发出的数据包,如果属于某个已知连接并有连接标记,则将连接标记设置为数据包标记:

iptables -t mangle -A OUTPUT -s $INADDR_ETH0 -j CONNMARK --restore-mark

创建一个新的路由表 222,指明所有数据通过 222.24.24.1 转发,并使用路由策略指定标记为 222 的数据包使用此路由表:

ip route add table 222 via 222.24.24.1
ip rule add fwmark 222 table 222

zyxwvu
UNDER CONSTRUCTION