为新的 VPN 连接设置路由和 iptables,以仅重定向端口 80 和 443

为新的 VPN 连接设置路由和 iptables,以仅重定向端口 80 和 443

我有一个新的 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 规则为标记的包创建自定义规则以使用新的路由表。

相关内容