我正在尝试让一些流量通过 VPN,而其他流量则不这样做。
具有给定 fwmark 的数据包应该发送至我的默认接口 ( wlo1
),所有其他流量发送至tun0
主表中的隧道接口( ,使用 OpenVPN)。我在 nftables 中添加了这条规则:
table ip test {
chain test {
type route hook output priority mangle; policy accept;
meta cgroup 1234 meta mark set 1
}
}
在主路由表中,我有以下条目:
default via 10.11.0.1 dev tun0
10.11.0.0/16 dev tun0 proto kernel scope link src 10.11.0.20
[WANIP.0]/24 dev wlo1 proto kernel scope link src [WANIP]
128.0.0.0/1 via 10.11.0.1 dev tun0
[VPNIP] via [WANGATEWAY] dev wlo1
带有 fwmark 的数据包1
会被引导到它们自己的路由表:ip rule add from all fwmark 1 lookup test
。在test
表中我添加了以下路线:
default via [WANGATEWAY] dev wlo1
当我ping 8.8.8.8
从这个 cgroup 运行时,它被卡住了。它似乎能够发送但无法接收任何数据包。
VPN 流量按预期工作。
究竟发生了什么?
答案1
当数据包发出时,会做出路由决策:该决策选择传出接口和要使用的匹配源 IP 地址。
当。。。的时候路线/输出链条设置一个标记,它会触发一个重新路由检查,正如在此看到的示意图(这是为iptables记住但完全可以用于nftables)。重新路由检查会更改路由...但不会更改源 IP 地址。因此还需要做更多的工作。
- 添加 NAT 规则以更改源 IP 地址。
这是必须要做的后重新路由检查,所以它是在NAT/后路由。请注意,同一个表可以有不同的链类型(与iptables其中表 <=> 类型)。
nft add chain ip test testnat '{ type nat hook postrouting priority srcnat; policy accept; }'
nft add rule ip test testnat meta mark 1 masquerade
现在正确的数据包确实离开了。
- 并允许接受回复流,尽管未通过默认路由到达
你可以放松一下反向路径转发通过更改为松散模式
rp_filter
:sysctl -w net.ipv4.conf.wlo1.rp_filter=2
或标记回复流以使用与传出流相同的路由表。它不会真正提高安全性,但无论如何:
nft add chain ip test testpre '{ type filter hook prerouting priority mangle; policy accept; }' nft add rule ip test testpre iif "wlo1" meta mark set 1
唉,如果没有其他调整,这将无法工作,这是自新版本以来所需要的未记录的功能2010年出现:
sysctl -w net.ipv4.conf.wlo1.src_valid_mark=1
笔记:
通过将标记存储在 conntrack 中,可以在安全方面做得更好康马克(
ct mark
) 仅允许正确的回复流,不允许任何其他流绕过严格反向路径转发。在严格模式下,任何内容都不会通过wlo1除非它是来自传出流量的回复。以下是完整对应的 nftables 规则文件(在替换 nftables 规则时与上面的选项 2 一起使用):table ip test { chain test { type route hook output priority mangle; policy accept; meta cgroup 1234 meta mark set 1 ct mark set meta mark } chain testnat { type nat hook postrouting priority srcnat; policy accept; meta mark 1 masquerade } chain testpre { type filter hook prerouting priority mangle; policy accept; ct mark 1 meta mark set ct mark } }
此外,根据我在乌德范围入口:https://kernelnewbies.org/Linux_4.10#Networking
如果您可以将 cgroups 用法转换为一组有限的 uid,则可以仅使用路由堆栈(无需 netfilter 或 nftables)来正确完成此操作,
ip rule add ... uidrange ...
如上所述。请参阅我对此的回答:通过特定接口 (tum1) 路由用户流量。