我想通过 VPN 将流量路由到某些特定地址。很简单,只需添加一条路由即可:
ip route add <destination ip> dev tun0 scope link
问题来了:我不想路由全部通过 VPN 进行通信,只需一些理想情况下,我希望“映射”一个 IP(例如 10.xxx 地址),该 IP 将“指向”实际目标 IP,但通过 VPN 路由。据我所知,这相当于添加一条路由(如上所示),然后在 POSTROUTING 链中执行相当于 DNAT 的操作。
本质上,我想做一个肮脏的 NAT 伎俩反过来(即在客户端而不是服务器上)。
(我想创建一个简单的 HTTP 代理,仅当 URL 与给定模式匹配时才通过 VPN 路由流量。最终的解决方案是直接从用户空间程序影响给定连接的路由,但我认为这是不可能的。)
假设我想引导一些流量,比如说,8.8.8.8
通过tun0
,但我仍然希望一些流量8.8.8.8
通过eth0
。例如,图片8.8.8.8
托管多个网站,我想将流量隧道仅发送到一些网站。
我想设置一个“假”地址,比如说10.1.2.3
。从我的计算机指向 的任何流量10.1.2.3
都会转到8.8.8.8
,但会通过tun0
而不是主路由表进行路由。
我部分地设法设置:首先我选择一个 IP 范围,例如10.1.0.0/16
。然后我在 OUTPUT 链中标记进入该范围的包,例如0x40
:
sudo iptables -A OUTPUT -t mangle --dst 10.1.0.0/16 -j MARK --set-mark 64
接下来,我添加 DNAT 规则,将该范围内的“假” IP 映射到真实目的地。这可能可以自动完成:
sudo iptables -A OUTPUT -t nat --dst 10.1.2.3 -j DNAT --to 8.8.8.8
根据标记,我使用不同的路由表来路由包裹:
sudo ip rule add fwmark 64 lookup vpn
sudo ip route add default dev tun0 scope global proto static table vpn
不幸的是,我仍然无法 ping 通10.1.2.3
。如果我删除 MARK 规则,我会得到响应,因此 DNAT 部分可以按预期工作。
答案1
我不确定我是否理解您所设想的基于 IP 路由的解决方案,但我对您的实际问题有一个建议:
我想创建一个简单的 HTTP 代理,仅当 URL 与给定模式匹配时才通过 VPN 路由流量。
实现此目的的最简单方法是通过(条件)代理链。在最简单的情况下,例如,使用 squid,您可以设置父级cache_peer
并将 设置cache_peer_domain
为.netflix.com
或任何其他 -http://wiki.squid-cache.org/Features/CacheHierarchy是配置此功能的一个良好起点;使用 apache 的mod_proxy您将使用ProxyRemote
指令(并且可能NoProxy
,取决于您的设置细节)。
回答您基于 IP 的示例:我认为 MARK 规则的唯一问题是它在错误的链中;应该是 PREROUTING,而不是 OUTPUT。引用手册iptables(1)
页:
MARK
This target is used to set the Netfilter mark value associated with
the packet. It can, for example, be used in conjunction with rout‐
ing based on fwmark (needs iproute2). If you plan on doing so, note
that the mark needs to be set in the PREROUTING chain of the mangle
table to affect routing.
答案2
我原来的路由设置有两个问题:
正如 Gabe 的回答所指出的,OUTPUT 中的 MARK 不能影响路由决策,只能影响 NAT 之后的重新路由决策。
这导致传出数据包中的源地址错误,因为源地址是由路由决策分配的,而重新路由则保持不变。我最终决定最好的解决方案是根据标记使用 MASQUERADE 操作来处理此问题:
iptables -A POSTROUTING -t nat -m mark --mark 64 -j MASQUERADE
Linux 有一个反向数据包过滤器。
例如,参见https://superuser.com/a/355408/184915了解过滤器对 VPN 相关路由场景的影响。
A
如果在接口 上收到来自源地址 的数据包I
,则除非发往目标地址 的数据包A
被路由到接口,否则该数据包将被丢弃I
。当然,8.8.8.8
来自 (例如传入 )的应答将被丢弃,因为在没有标记的情况下,tun0
正常路由会将数据包路由到8.8.8.8
。eth0
可以使用以下命令禁用数据包过滤器
echo 2 > /proc/sys/net/ipv4/conf/tun0/rp_filter
但这被认为是有害的,因为现在假装来自 eg 的伪造数据包
127.0.0.1
可以通过 到达机器tun0
。我们可以设置适当的防火墙规则来防止这种安全漏洞。请注意,利用上述漏洞需要破坏 VPN 服务器本身(我们只禁用 rp-filtertun0
),因此,在我看来,无论如何这都不是一个很大的风险。
此设置的一个巧妙的副作用是,tun0
iptables 规则中从未明确提及。我现在可以将任何类型的路由信息添加到 vpn 路由表并创建遵循该路由信息的“假”IP(尽管必须注意 rp-filter)。例如,通过修改单个路由表条目,此设置对于基于 PPTP 的 VPN 同样有用。