我有一个专用的 Web 服务器,运行 Debian 6 和一些 Apache、Tomcat、Asterisk 和 Mail-stuff。现在我们需要为一个特殊程序添加 VPN 支持。我们安装了 OpenVPN 并在 VPN 提供商处注册。连接运行良好,我们有一个用于隧道的虚拟 tun0 接口。
为了实现仅通过 VPN 隧道传输单个程序的目标,我们启动程序时使用
sudo -u 用户名 -g 组名 命令
并添加了一个 iptables 规则来标记来自 groupname 的所有流量
iptables -t mangle -A OUTPUT -m 所有者 --gid-owner 组名 -j MARK --set-mark 42
之后,我们告诉 iptables 进行一些 SNAT,并告诉 ip route 对标记的流量数据包使用特殊路由表。
问题:如果 VPN 出现故障,特殊的待隧道程序就有可能通过正常的 eth0 接口进行通信。
所需解决方案:所有标记的流量都不应被允许直接通过 eth0,而必须先通过 tun0。
我尝试了以下命令,但没有效果:
iptables -A OUTPUT -m 所有者 --gid-owner 组名 !-o tun0 -j REJECT
iptables -A OUTPUT -m 所有者 --gid-所有者组名 -o eth0 -j REJECT
问题可能是这样的,上述 iptable 规则无法正常工作,因为数据包首先被标记,然后放入 tun0,然后在仍带有标记的情况下通过 eth0 进行传输。我不知道如何在 tun0 中取消对它们的标记,或者告诉 iptables,所有标记的数据包都可以通过 eth0,如果它们之前在 tun0 中,或者它们要去我的 VPN 提供商的网关。
有人有解决方案吗?
一些配置信息:
iptables -nL -v --行号 -t mangle
链输出(策略接受 11M 数据包,9798M 字节) 数据包数量 字节数 目标 协议 选择加入 退出 源 目标 1 591K 50M MARK 全部 -- * * 0.0.0.0/0 0.0.0.0/0 所有者 GID 匹配 1005 MARK 设置 0x2a 2 82812 6938K CONNMARK 全部 -- * * 0.0.0.0/0 0.0.0.0/0 所有者 GID 匹配 1005 CONNMARK 保存
iptables -nL -v --行号 -t nat
链 POSTROUTING(策略接受 393 个数据包,23908 字节) 数据包数量 字节数 目标 协议 选择加入 退出 源 目标 1 15 1052 SNAT 全部 -- * tun0 0.0.0.0/0 0.0.0.0/0 标记匹配 0x2a 到:VPN_IP
ip 规则从所有 fwmark 添加 42 查找 42
ip 路由显示表 42
默认通过 VPN_IP dev tun0
答案1
只需为标记数据包添加默认低优先级路由
ip rule add fwmark 42 table no.out
ip route add blackhole 0.0.0.0 metric 100 table no.out
然后,建立新的 vpn 连接应该为相同的标记设置路由,但使用较低的度量。
答案2
在自己的网络命名空间中运行该程序,阻止所有对 eth0 的访问