来自 wireguard VPN 的白名单 cgroup

来自 wireguard VPN 的白名单 cgroup

我有一个名为 的 wireguard VPN,通过 NetworkManager 设置并启用wg0。我想允许程序直接访问互联网而不通过隧道。为此,我尝试通过以下方式进行匹配:cgroupv2

路由如下所示:

> ip -4 addr show dev wlan0
2: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 10.126.232.253/16 brd 10.126.255.255 scope global dynamic noprefixroute wlan0
       valid_lft 43135sec preferred_lft 43135sec

> ip -4 addr show dev wg0
6: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 10.118.53.99/32 scope global noprefixroute wg0
       valid_lft forever preferred_lft forever

> ip -4 rule
0:      from all lookup local
31760:  from all lookup main suppress_prefixlength 0
31761:  not from all fwmark 0xcc4d lookup 52301
32766:  from all lookup main
32767:  from all lookup default

> ip -4 route list table local
local 10.118.53.99 dev wg0 proto kernel scope host src 10.118.53.99
local 10.126.232.253 dev wlan0 proto kernel scope host src 10.126.232.253
broadcast 10.126.255.255 dev wlan0 proto kernel scope link src 10.126.232.253
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1

> ip -4 route list table main
default via 10.126.255.254 dev wlan0 proto dhcp src 10.126.232.253 metric 600
10.126.0.0/16 dev wlan0 proto kernel scope link src 10.126.232.253 metric 600

> ip -4 route list table 52301
default dev wg0 proto static scope link metric 20050

现在从阅读开始关于 wg-quick 路由并试图理解Netfilter 数据包流例如,我创建了一个名为“bypass”的表,它与我的终端的 cgroup 匹配,并添加了 fwmark 0xcc4d

> sudo nft list tables
table inet bypass

> sudo nft list table inet bypass
table inet bypass {
        chain out {
                type filter hook output priority mangle; policy accept;
                socket cgroupv2 level 5 "user.slice/user-1000.slice/[email protected]/app.slice/app-org.kde.konsole-698af79930294eb09aa9231b0a8bd258.scope" log prefix "cgroup_matched out "
                socket cgroupv2 level 5 "user.slice/user-1000.slice/[email protected]/app.slice/app-org.kde.konsole-698af79930294eb09aa9231b0a8bd258.scope" meta mark 0x00000000 meta oiftype != loopback meta mark set 0x0000cc4d
        }

        chain check {
                type filter hook postrouting priority mangle; policy accept;
                ip daddr 34.160.111.145 log prefix "postroute check "
        }
}

> cat /proc/$$/cgroup
0::/user.slice/user-1000.slice/[email protected]/app.slice/app-org.kde.konsole-698af79930294eb09aa9231b0a8bd258.scope

测试一下,看起来数据包匹配正确,但是从 netfilter 图来看

> host ifconfig.me
34.160.111.145

> sudo conntrack -L -d 34.160.111.145
conntrack v1.4.7 (conntrack-tools): 0 flow entries have been shown.

> d=`date +'%Y-%m-%d %H:%M:%S'`

> curl https://ifconfig.me; echo
<tunnel public IP>  # Expect to see my own public IP

> sudo journalctl --dmesg --since "$d" -n 2
Apr 14 12:40:56 <hostname> kernel: cgroup_matched out IN= OUT=wg0 SRC=10.118.53.99 DST=34.160.111.145 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=26291 DF PROTO=TCP SPT=48504 DPT=443 WINDOW=64860 RES=0x00 SYN URGP=0
Apr 14 12:40:56 <hostname> kernel: postroute check IN= OUT=wg0 SRC=10.118.53.99 DST=34.160.111.145 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=26291 DF PROTO=TCP SPT=48504 DPT=443 WINDOW=64860 RES=0x00 SYN URGP=0 MARK=0xcc4d

据我了解,fwmark0xcc4d正确地针对传出的数据包曼格尔,我们看到后路由。然而后路由,即在重新路由检查在 netfilter 流程​​图上,我们仍然有OUT=wg0 SRC=10.118.53.99,但据我了解:

  • 更改fwmarkmangle 中的 should 应该会触发重新路由,请参阅此主题, Linuxipt mangle 源代码
  • 任何标记fwmark 0xcc4d都不应查找表52301,因此使用路线default via 10.126.255.254 dev wlan0 proto dhcp src 10.126.232.253

那么我遗漏了什么?我该如何解决这个问题?


我正在运行 OpenSUSE Tumbleweed (20230411):

  • Linux 内核 6.2.9
  • libnftables1 1.0.7
  • iproute2 6.2
  • wireguard-tools 1.0.20210914
  • conntrack-tools 1.4.7
  • 网络管理器 1.42.4

答案1

我找到了一个似乎可行的解决方案:

  • 要更改输出设备,nftables 规则需要为type route。但是这不会改变源 IP,它仍为隧道的私有地址
  • 为了更改此地址,我添加了一条nat规则,该规则应用masquerade更改源 IP
table inet bypass {
        chain in {
                type filter hook prerouting priority raw; policy accept;
                socket cgroupv2 level 5 "user.slice/user-1000.slice/[email protected]/app.slice/app-org.kde.konsole-aed769efd3b74de792530f9a71b0c14b.scope" meta mark 0x00000000 meta oiftype != loopback meta mark set 0x0000cc4d
        }

        chain out {
                type route hook output priority mangle; policy accept;
                socket cgroupv2 level 5 "user.slice/user-1000.slice/[email protected]/app.slice/app-org.kde.konsole-aed769efd3b74de792530f9a71b0c14b.scope" meta mark 0x00000000 meta oiftype != loopback meta mark set 0x0000cc4d
        }

        chain nat {
                type nat hook postrouting priority srcnat; policy accept;
                meta oif wlan0 meta mark 0x0000cc4d masquerade
        }
}

我不确定这是否是一个正确的解决方案,还是一个黑客问题。

我认为该设置也可能受益于对隧道和非隧道流量使用单独的 conntrack 区域,因为它们可以瞄准相同的 IP。

相关内容