将 cgroup 中的流量路由到 VPN 隧道之外

将 cgroup 中的流量路由到 VPN 隧道之外

我正在尝试让一些流量通过 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

现在正确的数据包确实离开了。

  • 并允许接受回复流,尽管未通过默认路由到达
  1. 你可以放松一下反向路径转发通过更改为松散模式rp_filter

        sysctl -w net.ipv4.conf.wlo1.rp_filter=2
    
  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) 路由用户流量

相关内容