我有一个新的 VPN 连接(使用 openvpn),可以绕过一些 ISP 限制。虽然它运行正常,但需要全部通过 vpn 的流量。这导致我下载时出现问题(我的互联网连接速度比 vpn 允许的快很多),并且无法进行远程访问。我运行一个 ssh 服务器,并且有一个守护进程正在运行,允许我通过手机安排下载。
我在 eth0 上有现有的以太网连接,在 tun0 上有新的 VPN 连接。
我认为我需要设置默认路由以使用 192.168.0.0/24 网络上的现有 eth0 连接,并将默认网关设置为 192.168.0.1(我的知识不太清楚,因为我已经很多年没有这样做了)。如果这是正确的,那么我不太清楚该怎么做!我当前的路由表是:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface MSS Window irtt
0.0.0.0 10.51.0.169 0.0.0.0 UG 0 0 0 tun0 0 0 0
10.51.0.1 10.51.0.169 255.255.255.255 UGH 0 0 0 tun0 0 0 0
10.51.0.169 0.0.0.0 255.255.255.255 UH 0 0 0 tun0 0 0 0
85.25.147.49 192.168.0.1 255.255.255.255 UGH 0 0 0 eth0 0 0 0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 eth0 0 0 0
192.168.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0 0 0 0
修复路由后,我认为我需要使用 iptables 配置预路由或伪装,以强制通过 tun0 进行所有目标端口 80 或 443 的操作。同样,我不太清楚该怎么做!
我在互联网上找到的所有内容都在尝试做一些更为复杂的事情,并且尝试从树木中筛选出木材被证明是困难的。
任何帮助将非常感激。
更新
到目前为止,我从各种来源拼凑了以下内容:
#!/bin/sh
DEV1=eth0
IP1=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 192.`
GW1=192.168.0.1
TABLE1=internet
TABLE2=vpn
DEV2=tun0
IP2=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
GW2=`route -n | grep 'UG[ \t]' | awk '{print $2}'`
ip route flush table $TABLE1
ip route flush table $TABLE2
ip route show table main | grep -Ev ^default | while read ROUTE ; do
ip route add table $TABLE1 $ROUTE
ip route add table $TABLE2 $ROUTE
done
ip route add table $TABLE1 $GW1 dev $DEV1 src $IP1
ip route add table $TABLE2 $GW2 dev $DEV2 src $IP2
ip route add table $TABLE1 default via $GW1
ip route add table $TABLE2 default via $GW2
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
ip rule add from $IP1 lookup $TABLE1
ip rule add from $IP2 lookup $TABLE2
ip rule add fwmark 1 lookup $TABLE1
ip rule add fwmark 2 lookup $TABLE2
iptables -t nat -A POSTROUTING -o $DEV1 -j SNAT --to-source $IP1
iptables -t nat -A POSTROUTING -o $DEV2 -j SNAT --to-source $IP2
iptables -t nat -A PREROUTING -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark
iptables -t nat -A PREROUTING -i $DEV1 -m state --state NEW -j CONNMARK --set-mark 1
iptables -t nat -A PREROUTING -i $DEV2 -m state --state NEW -j CONNMARK --set-mark 2
iptables -t nat -A PREROUTING -m connmark --mark 1 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -m connmark --mark 2 -j MARK --set-mark 2
iptables -t nat -A PREROUTING -m state --state NEW -m connmark ! --mark 0 -j CONNMARK --save-mark
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 80 -j CONNMARK --set-mark 2
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 443 -j CONNMARK --set-mark 2
route del default
route add default gw 192.168.0.1 eth0
现在这个似乎可以工作。但事实并非如此!
连接到被屏蔽的网站是正在通过,不在端口 80 和 443 上的连接是使用非VPN连接。
然而端口 80 和 443 连接不是被阻止的网站也使用非 VPN 连接!
因为总体目标已经达成,我比较开心,但知道它为什么不能正常工作就好了。
有任何想法吗?
作为参考,我现在有 3 个路由表,主路由表、互联网路由表和 vpn 路由表。路由表列表如下...
主要的:
default via 192.168.0.1 dev eth0
10.38.0.1 via 10.38.0.205 dev tun0
10.38.0.205 dev tun0 proto kernel scope link src 10.38.0.206
85.removed via 192.168.0.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1000
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.73 metric 1
互联网:
default via 192.168.0.1 dev eth0
10.38.0.1 via 10.38.0.205 dev tun0
10.38.0.205 dev tun0 proto kernel scope link src 10.38.0.206
85.removed via 192.168.0.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1000
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.73 metric 1
192.168.0.1 dev eth0 scope link src 192.168.0.73
VPN:
default via 10.38.0.205 dev tun0
10.38.0.1 via 10.38.0.205 dev tun0
10.38.0.205 dev tun0 proto kernel scope link src 10.38.0.206
85.removed via 192.168.0.1 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1000
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.73 metric 1
答案1
因此,大部分内容如上所述,但整个解决方案如下:
编辑 /etc/iproute2/rt_tables 并在底部添加两行:
101 internet
102 vpn
您可以为这些表赋予其他更有意义的名称,只要保持一致即可。
然后你需要在 /etc/init.d 中创建一个脚本(我称之为 rt_setup)
#!/bin/sh
DEV1=eth0
IP1=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 192.`
GW1=192.168.0.1
TABLE1=internet
TABLE2=vpn
DEV2=tun0
IP2=`ifconfig|perl -nE'/dr:(\S+)/&&say$1'|grep 10.`
GW2=`route -n | grep 'UG[ \t]' | awk '{print $2}'`
ip route flush table $TABLE1
ip route flush table $TABLE2
ip route show table main | grep -Ev ^default | while read ROUTE ; do
ip route add table $TABLE1 $ROUTE
ip route add table $TABLE2 $ROUTE
done
ip route add table $TABLE1 $GW1 dev $DEV1 src $IP1
ip route add table $TABLE2 $GW2 dev $DEV2 src $IP2
ip route add table $TABLE1 default via $GW1
ip route add table $TABLE2 default via $GW2
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
ip rule add from $IP1 lookup $TABLE1
ip rule add from $IP2 lookup $TABLE2
ip rule add fwmark 1 lookup $TABLE1
ip rule add fwmark 2 lookup $TABLE2
iptables -t nat -A POSTROUTING -o $DEV1 -j SNAT --to-source $IP1
iptables -t nat -A POSTROUTING -o $DEV2 -j SNAT --to-source $IP2
iptables -t nat -A PREROUTING -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark
iptables -t nat -A PREROUTING -i $DEV1 -m state --state NEW -j CONNMARK --set-mark 1
iptables -t nat -A PREROUTING -i $DEV2 -m state --state NEW -j CONNMARK --set-mark 2
iptables -t nat -A PREROUTING -m connmark --mark 1 -j MARK --set-mark 1
iptables -t nat -A PREROUTING -m connmark --mark 2 -j MARK --set-mark 2
iptables -t nat -A PREROUTING -m state --state NEW -m connmark ! --mark 0 -j CONNMARK --save-mark
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 80 -j CONNMARK --set-mark 2
iptables -t mangle -A PREROUTING -i $DEV2 -m state --state NEW -p tcp --dport 443 -j CONNMARK --set-mark 2
route del default
route add default gw 192.168.0.1 eth0
然后,显然,从 /etc/rc2.d 链接它(我使用 ubuntu,运行级别可能与你不同)。确保给它一个 S 号更高比 openvpn 链接!
该脚本执行多项操作。上半部分设置变量,使用一些 perl 和 awk 语句来获取动态 IP 和网关地址。第二部分清理您在 ipruote2 中设置的表,并将当前路由表复制到这些表。然后,它为它们创建两个新路由和两个默认网关,其中 VPN 路由通过 VPN,互联网路由通过我的本地网络。
我并不确信接下来的两行是必要的,但是它们可以启用 ip 转发以便在 iptables 中使用。
接下来,脚本会创建一些规则,确定在哪里查找来自相关 IP 地址的流量,以及在哪里查找流量是否被特别标记。
POSTROUTING 和 PREROUTING 确保来自某个地址的流量得到答复!
最后的 iptables PREROUTING 是标记流量的部分,并确保任何到端口 80 或 443 的内容都被标记为使用表 2(VPN)
最后两行从默认路由表中删除 VPN 网关,并重新添加我的本地网络网关。
目前看来,这个过程非常出色。VPN 在机器启动时启动,几秒钟后运行此脚本(我可能会添加一个 sleep 语句,以确保在运行此脚本之前 VPN 已完全初始化)。我的远程访问连接(ssh 等)运行良好。我的连接(不去往端口 80 或 443)使用我的本地连接,但所有网络流量都通过 VPN,并绕过我的 ISP 设置的控制!
正如我在问题下的评论中所说,如果没有 @anttir 的建议,我根本不会开始考虑这条路线。根据这个建议,这些网站http://blog.khax.net/2009/11/28/multi-gateway-routing-with-iptables-and-iproute2/和http://linux-ip.net/html/adv-multi-internet.html非常有用(即使代码不是 100% 完成!)
答案2
每个协议的路由有点复杂。通常使用路由表根据目标 IP 检查网关,并使用 openvpn 或 192.168.0.1 默认网关。
在 VPN 的另一端设置 Squid http 代理并将浏览器设置为使用代理会更容易。
您不会使用 iptables,因为它会更改 HTTP 连接的目标 IP,并且它将不起作用。
您可以创建一个新的路由表 (/etc/iproute2/rt_tables),并将默认路由设置为 VPN 端点,使用 iptables fwmark ( -j MARK ) 标记所有 HTTP 数据包,然后使用ip 规则为标记的包创建自定义规则以使用新的路由表。