如何通过wireguard路由来自一个用户的流量?

Max*_*mus 5 iptables internet vpn

使用VPN公司提供的wireguard配置:

如何修改iptables并仅通过wireguard的接口 wg0wg0.conf路由 来自用户的流量vpn,而不影响所有其他流量?

对评论和答案的反应

当将建议的命令(由 Hauke Laging)作为PostUp脚本运行时,会wg0.conf导致用户通过 wg0 接口发送流量,但仍然无法访问互联网,为什么?

#!/bin/sh
# up.sh

iptables -t mangle -nvL OUTPUT | grep -q 0x2a ||
    iptables -t mangle -A OUTPUT -m owner --uid-owner test -j MARK --set-mark 42

grep -q '^42  vpn$' /etc/iproute2/rt_tables ||
    echo '42  vpn' >>/etc/iproute2/rt_tables

ip route show table vpn | grep -q default ||
    ip route add default via 10.66.95.98 dev wg0 table vpn

ip rule | grep -q 0x2a ||
    ip rule add fwmark 42 lookup vpn prio 42
Run Code Online (Sandbox Code Playgroud)

目前的配置wg0.conf如下:

[Interface]
PrivateKey = <Hidden>
Address = 10.66.95.98/32,fc00:bbbb:bbbb:bb01::3:5f61/128
DNS = <DNS>
Table = off
PostUp = up.sh

#Following 2 lines added in attempt to allow local traffic 
PreUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PreDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE

[Peer]
PublicKey = <Hidden>
AllowedIPs = 0.0.0.0/0,::0/0
Endpoint = 185.65.135.224:51820
Run Code Online (Sandbox Code Playgroud)

ip route返回以下输出:

default via 192.168.1.1 dev enp2s0 proto dhcp metric 100 
169.254.0.0/16 dev enp2s0 scope link metric 1000 
192.168.1.0/24 dev enp2s0 proto kernel scope link src 192.168.1.2 metric 100 
Run Code Online (Sandbox Code Playgroud)

ip route show table vpn返回输出

default via 10.66.95.98 dev wg0 
Run Code Online (Sandbox Code Playgroud)

ip rule回报

0:  from all lookup local
42: from all fwmark 0x2a lookup vpn
32766:  from all lookup main
32767:  from all lookup default
Run Code Online (Sandbox Code Playgroud)

iptables -t nvL回报

Chain PREROUTING (policy ACCEPT 5465 packets, 1114K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 2829  671K CONNMARK   udp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* wg-quick(8) rule for wg0 */ CONNMARK restore

Chain INPUT (policy ACCEPT 5450 packets, 1113K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 5786 packets, 1203K bytes)
 pkts bytes target     prot opt in     out     source               destination         
  961 1123K RETURN     all  --  *      *       0.0.0.0/0            192.168.1.0/24       owner UID match 1002
 261M  414G MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1002 MARK set 0x2a
  156 56019 RETURN     all  --  *      *       0.0.0.0/0            192.168.1.0/24       owner UID match 1002
 261M  414G MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1002 MARK set 0x2a
   77 48572 MARK       all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1002 MARK set 0x2a

Chain POSTROUTING (policy ACCEPT 6507 packets, 1310K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1281  209K CONNMARK   udp  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0xca6c /* wg-quick(8) rule for wg0 */ CONNMARK save
Run Code Online (Sandbox Code Playgroud)

运行时tcpdump -i wg0 -n&ping google.se以下返回:

17:48:43.496475 IP 192.168.1.2.33044 > 185.65.135.224.51820: UDP, length 1184
Run Code Online (Sandbox Code Playgroud)

表明数据包确实到达了wg0接口。但是,ping 不会产生任何结果。

110 packets transmitted, 0 received, 100% packet loss, time 111603ms
Run Code Online (Sandbox Code Playgroud)

Hau*_*ing 4

你可以这样做

  1. 使用iptable的模块owner来检测这些数据包
  2. usingiptable的目标MARK将数据包标记设置为任何尚未使用的值
  3. 创建一个额外的路由表,通过 VPN 接口发送所有流量
  4. 使用ip rule策略路由为标记的数据包选择特殊的路由表
iptables -t mangle -nvL OUTPUT | grep -q 0x2a ||
    iptables -t mangle -A OUTPUT -m owner --uid-owner test -j MARK --set-mark 42

grep -q '^42  vpn$' /etc/iproute2/rt_tables ||
    echo '42  vpn' >>/etc/iproute2/rt_tables

ip route show table vpn | grep -q default ||
    ip route add default via 10.66.95.98 dev wg0 table vpn

ip rule | grep -q 0x2a ||
    ip rule add fwmark 42 lookup vpn prio 42
Run Code Online (Sandbox Code Playgroud)