试想一种情况,如果你拥有至少两条出网线路,分为电信、移动,此时最优的路由的方案应为目标IP为电信的走电信线路,目标IP为移动的走移动线路,如果是其他的则默认走电信。
基于此种情况,可以通过iptables+iproute2实现策略分流。
假设现在路由器有两块网卡,分别接入了电信和移动的网络:
eth0: 10.10.10.10/24 gateway: 10.10.10.1 电信
eth1: 20.20.20.20/24 gateway: 20.20.20.1 移动
eth2: 192.168.1.1/24 内网
第一步首先创建普通NAT规则,使得内网机器能正常访问外网
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE
第二步创建电信/移动路由规则
ip route add default via 10.10.10.1 table 100 #在名字为100的路由表中添加默认路由
ip route add default via 20.20.20.1 table 200 #在名字为200的路由表中添加默认路由
ip route add default via 10.10.10.1 table main #如无匹配则走电信线路
第三步创建目标网段集合
ipset create telecom hash:net #创建电信网段IP集合
ipset create cmcc hash:net #创建移动网段IP集合
ipset add telecom 1.1.1.0/24 #将1.1.1.0/24添加进电信集合
ipset add cmcc 2.2.2.0/24 #将2.2.2.0/24添加进电信集合
第四步通过iptables给目标数据包打上标记
iptables -t mangle -A PREROUTING -m set --match-set telecom dst -j MARK --set-mark 100 #给目标地址集合为telecom的数据包打上100标签
iptables -t mangle -A PREROUTING -m set --match-set cmcc dst -j MARK --set-mark 200 #给目标地址集合为cmcc的数据包打上200标签
第五步设置规则
ip rule add from all fwmark 100 lookup 100 #标记为100的数据包走名字为100的路由表
ip rule add from all fwmark 200 lookup 200 #标记为100的数据包走名字为100的路由表
完成上述所有配置之后,就能实现精准的策略路由啦!当然这种情况只适合从内网访问外网的,如果你需要在内网向外提供如WEB服务,这种方法可能就会不行。比如在电信的IP上配置443端口转发到内网的某台机器,如果对方是一个移动用户访问了这个端口,那么你的数据包就会通过移动线路发送回去,导致对方收到的数据包来源不匹配而无法建立连接。
针对这种情况,必须使用源进源出策略,使用iptables的CONNMARK模块即可
iptables -t nat -A PREROUTING -p tcp --dport 443 -d 10.10.10.10 -j DNAT --to-destination 192.168.1.6:443 #配置NAT转发
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark #对内网发向公网的数据包从Connection mark 恢复为Packet mark
iptables -t mangle -A PREROUTING -i eth0 -j MARK --set-mark 101 #从电信线路进来的数据包打上101标记
iptables -t mangle -A POSTROUTING -m mark --mark 101 -j CONNMARK --set-mark 100 #给从公网来的标记为101的数据包使用CONNMARK打上100标记
这样一来,变实现了源进源出