VPN 出国启用负载均衡
•
VPN 现有两条出国线路,早先只是随机使用一条线路。现在使用 iptables statistic module 做了基于连接的负载均衡,实测连接比较平均地分布到了两条线路上。理论上,一条线路故障还能自动切换到另一条。
设源 IP 的范围为 source-ip-range(如果是自己用则省略 -s source-ip-range 这个参数)。
- 在 iptables PREROUTING 阶段,把基于 connection 的 mark 转化为基于 packet 的 mark。
- 如果还没有被 mark,则认为是一个新的连接,使用 statistic module 的 round robin 方式,打上1号或2号 mark。
- 把基于 packet 的 mark 转换回 connection mark。
- 在 policy routing 阶段,让 mark 1 先查 2000 号表再查 2001,mark 2 先查 2001 号表再查 2000,没有 mark 的查默认表。
- 在 2000 号表中让需要 VPN 的 IP range 走 tunnel 1,在 2001 号表中让同样一批 IP range 走 tunnel 2。
为便于理解,对配置做了些简化,贴在下面,供参考:
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -s source-ip-range -m mark --mark 0x0 -m statistic --mode nth --every 2 --packet 0 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -s source-ip-range -m mark --mark 0x0 -m statistic --mode nth --every 2 --packet 1 -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -j CONNMARK --save-mark
while read prefix comment; do
ip route replace $prefix via tunnel1-gateway table 1000
ip route replace $prefix via tunnel2-gateway table 2000
done <blocked-ip.txt
ip rule add fwmark 1 lookup 2000 pref 1000 # default
ip rule add fwmark 1 lookup 2001 pref 1001 # backup
ip rule add fwmark 2 lookup 2001 pref 1002 # default
ip rule add fwmark 2 lookup 2000 pref 1003 # backup
上述 routing policy 有如下特性:
- 正常情况下,连接会平均分配在两个 tunnel 上。
- 只要是内核 conntrack 模块能认出来的连接,比如 TCP 连接,一个连接内的 packet 会走同一个 tunnel。
- 不在这些 IP range 中的连接会走默认路由表。
- 如果一个 tunnel(比如 tunnel 1)挂了,相应的路由表项(2000 号表)会被内核自动清除,mark 1 就会查 2001 去走另一个 tunnel,mark 2 不受影响。
- 即使两个 tunnel 都挂了,也会走默认路由,总比完全中断好。
完整代码在 https://gitgeek.net/boj/smartproxy.git