Bash 脚本在 Ubuntu 18 上通过单独的 VPN 隧道发送所有 Wifi 热点流量

Bash 脚本在 Ubuntu 18 上通过单独的 VPN 隧道发送所有 Wifi 热点流量

我正在编写一个 bash 脚本,该脚本应该在 ubuntu 18 上创建一个热点。但是,我对该热点应该使用什么连接有特殊需求。

我希望连接到我的热点的所有设备的所有流量都通过单独的 VPN 隧道,并且(不确定这部分是否相关)每次激活热点时,我都会从一组选项中随机选择哪个 VPN。

默认情况下,在 Ubuntu 18 上创建热点时,它只会共享现有连接,无论它当前是什么。

当我打开nm-connection-editorGUI 时包含一个 VPN 选项,但我不知道如何纯粹使用 bash 来创建和修改热点。

我基本上不知道如何通过编程来实现它,或者我是否缺乏其他知识来实现​​这一点。除非我错过了什么,否则手册页对nmcli我没有帮助。

可能使事情复杂化的是,我已经连接到 tun0 上的 VPN,所以我猜我需要创建一个单独的 VPN 连接,比如说通过 tun1,并让热点使用它。

这是我目前所拥有的

#that's the kind of call I use to activate my main VPN connection
#you can assume I have script already that gives me 
#the value for mainconnectionuuid
nmcli con up uuid mainconnectionuuid #activates tun0, all traffic goes through tun0 after this

#now I want to activate a hotspot that uses a different VPN connection 
#the following code activates the hotspot, but there is no option
#to separate the traffic to go over a different VPN
nmcli radio wifi on
nmcli device wifi hotspot ssid somessid password somepassword

我需要的是这样的:

#activate main connection on tun0
nmcli con up uuid mainconnectionuuid

nmcli radio wifi on
#'useconnection' is a phantasy parameter here, but I need something like this
#assuming here that the connection under vpnforhotspotuuid would already define tun1 to be used
nmcli device wifi hotspot ssid somessid password somepassword **useconnection vpnforhotspotuuid**

或者像这样:

#activate main connection on tun0
nmcli con up uuid mainconnectionuuid

#activate connection for hotspot on tun1
nmcli con up uuid vpnforhotspotuuid

nmcli radio wifi on
#'usetunnel' is a phantasy parameter here
nmcli device wifi hotspot ssid somessid password somepassword **usetunnel tun1**

我怎样才能实现这个目标?

我不是这方面的专家,我可以编写 bash 脚本,我也知道 ufw,但我有点害怕 IPtables。我希望有一个不太难理解的解决方案,因为我还想编写一个脚本来撤消或至少停用更改。

编辑1:

我尝试了 Piotr 提出的解决方案,它似乎几乎可以工作,但出现了问题。当我使用 android 9 设备连接到该热点时,它似乎可以工作,直到我执行最后一个命令ip route add default via $TUN1IP table hotspot。发出该命令后,我刚好有足够的时间使用手机上的浏览器请求 whatismyip.com 并验证我确实拥有 tun1 ip。不久之后(大约 15-30 秒),手机 wifi 设置将开始显示“无互联网连接”,手机开始无限循环重新连接,直到我使用ip route del default table hotspot

首先,我想知道这是否是某种防火墙问题,因为我的配置非常严格,并且从

ufw default deny incoming 
ufw default deny outgoing

然后我有一些规则来允许 vpn 连接和本地地址,然后关于到目前为止我确定的热点:

ufw allow out on tun1 to 0.0.0.0/0
ufw allow out on wlan0 to 10.57.213.1/24

编辑2

在发出最终命令之前,ip route add default via $TUN1IP table hotspot我看到以下 UFW 块(通过dmesg),但连接仍然有效:

[UFW BLOCK] IN=wlan0 OUT= MAC=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx SRC=10.57.213.181 DST=10.57.213.1 LEN=28 TOS=0x00 PREC=0x00 TTL=1 ID=xxxxx DF PROTO=UDP SPT=45104 DPT=4886 LEN=8

发出路由命令后,这些块就会消失,所以我猜它们并不重要,但不确定。但是,如果我查看非 ufw 消息,我会在每次重新连接时看到以下消息:

netlink:“wpa_supplicant”:属性类型 213 的长度无效。

我谷歌了一下,有些人这是与 WPA2 相关的错误,如果我禁用加密,连接将正常工作,但即使我禁用加密,也不会发生任何变化。设备仍在无限循环中重新连接到热点。

我可能还应该提到我尝试过,ip route flush cache但什么也没改变

编辑3

wpa_cli -i wlan0 log_level DEBUG以及随后的journalctl -u wpa_supplicant -e收益(我使用字母 x 审查了 PID 和 MAC 地址):

Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-70 fc=0x40 seq_ctrl=0xd740 stype=4
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-72 fc=0x40 seq_ctrl=0xd750 stype=4
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:22 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:33 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:33 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=20:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-75 fc=0x40 seq_ctrl=0x8830 stype=4
Mar 05 20:59:33 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:33 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-72 fc=0x40 seq_ctrl=0xe430 stype=4
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-70 fc=0x40 seq_ctrl=0xe450 stype=4
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-71 fc=0x40 seq_ctrl=0xe470 stype=4
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-71 fc=0x40 seq_ctrl=0xe480 stype=4
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-71 fc=0x40 seq_ctrl=0xe490 stype=4
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: BSS Event 59 (NL80211_CMD_FRAME) received for wlan0
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: nl80211: RX frame da=ff:ff:ff:ff:ff:ff sa=10:xx:xx:xx:xx:xx bssid=ff:ff:ff:ff:ff:ff freq=2412 ssi_signal=-71 fc=0x40 seq_ctrl=0xe4a0 stype=4
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: wlan0: Event RX_MGMT (19) received
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: P2P: Not a P2P probe - ignore it
Mar 05 20:59:41 machineone wpa_supplicant[xxxx]: Ignore Probe Request due to DS Params mismatch: chan=1 != ds.chan=2

编辑4

激活 tun1 后,我的路由表如下所示

Destination       Gateway           Genmask         Flags Metric Ref    Use Iface
0.0.0.0           10.10.2.1         0.0.0.0         UG    50     0        0 tun0
0.0.0.0           10.10.3.1         0.0.0.0         UG    50     0        0 tun1
0.0.0.0           192.168.xxx.xxx   0.0.0.0         UG    100    0        0 eth0
10.10.2.0         0.0.0.0           255.255.255.0   U     50     0        0 tun0
10.10.3.0         0.0.0.0           255.255.255.0   U     50     0        0 tun1
10.57.213.1       0.0.0.0           255.255.255.0   U     600    0        0 wlan0 
the.vpn.ip.tun0   192.168.xxx.xxx   255.255.255.255 UGH   100    0        0 eth0
169.254.0.0       0.0.0.0           255.255.0.0     U     1000   0        0 virbr0 
the.vpn.ip.tun1   192.168.xxx.xxx   255.255.255.255 UGH   100    0        0 eth0
192.168.yyy.0     0.0.0.0           255.255.255.0   U     0      0        0 virbr0
192.168.xxx.0     0.0.0.0           255.255.255.0   U     100    0        0 eth0
192.168.xxx.xxx   0.0.0.0           255.255.255.255 UH    100    0        0 eth0

我尝试了诸如ip route add default dev wlan0 via default dev tun1和之类的命令ip route add default dev wlp8s0 via 10.10.3.1 dev tun1,但都不起作用。此外,有时 tun0 的默认网关恰好与 tun1 的默认网关相同。

编辑 5

我发现有一个漏洞在 Linux 内核中(或者更确切地说wpa2_supplicant),内核对传递给它的参数非常严格,并且会导致wpa2_supplicant失败。我做了以下事情

# nmcli connection edit hotspot
set 802-11-wireless-security.pmf disable
save
[CTRL+D]

这将禁用我创建的热点连接的受保护管理框架 (PMF),而内核调用正是在此中断的wpa_supplicant。完成此操作(和route add default dev wlan0 via 10.10.3.1 dev tun1)后,现在我的整个系统(不仅仅是热点)正在运行,tun1而不是tun0。我仍然需要了解为什么我不能实现tun0将用于eth0同时tun1将用于的事情wlan0

在我发出以下命令后

ip route add default dev wlan0 via 10.10.2.1 dev tun1 proto static metric 50
ip route add default dev eth0 via 10.10.3.1 dev tun0 proto static metric 50

我的路由表如下所示:

0.0.0.0          10.10.2.1        0.0.0.0         UG    50     0        0 tun1
0.0.0.0          10.10.3.1        0.0.0.0         UG    50     0        0 tun0
0.0.0.0          192.168.xxx.xxx  0.0.0.0         UG    100    0        0 eth0
10.10.2.0        0.0.0.0          255.255.255.0   U     50     0        0 tun0
10.10.3.0        0.0.0.0          255.255.255.0   U     50     0        0 tun1
10.55.213.1      0.0.0.0          255.255.255.0   U     600    0        0 wlan0
the.vpn.ip.tun1  192.168.xxx.xxx  255.255.255.255 UGH   100    0        0 eth0
169.254.0.0      0.0.0.0          255.255.0.0     U     1000   0        0 virbr0
the.vpn.ip.tun1  192.168.xxx.xxx  255.255.255.255 UGH   100    0        0 eth0
192.168.yyy.0    0.0.0.0          255.255.255.0   U     0      0        0 virbr0
192.168.xxx.0    0.0.0.0          255.255.255.0   U     100    0        0 eth0
192.168.xxx.xxx  0.0.0.0          255.255.255.255 UH    100    0        0 eth0

看起来就像我从未发布过它们一样

编辑6:

当我尝试从终端建立 VPN 连接时

sudo openvpn --config myconfigfile.ovpn --dev tun1 --verb 3

发出以下路线命令,所有内容将通过tun1并被tun0忽略:

Wed Mar 11 19:16:12 2020 /sbin/ip link set dev tun1 up mtu 1500
Wed Mar 11 19:16:12 2020 /sbin/ip addr add dev tun1 10.10.2.6/24 broadcast 10.10.2.255
Wed Mar 11 19:16:12 2020 /sbin/ip route add the.vpn.ip.tun1/32 via 10.10.3.1
Wed Mar 11 19:16:12 2020 /sbin/ip route add 0.0.0.0/1 via 10.10.2.1
Wed Mar 11 19:16:12 2020 /sbin/ip route add 128.0.0.0/1 via 10.10.2.1

我还发现10.10.3.1ip 很奇怪因为它与 有关tun0

当我做

ip route delete 0.0.0.0/1 via 10.10.2.1

我的所有连接都返回tun0并忽略tun1ip route show table如下所示:

default via 10.10.3.1 dev tun0 
default via 10.10.3.1 dev tun0 proto static metric 50 
default via 192.168.xxx.xxx dev eth0 proto dhcp metric 100 
10.10.2.0/24 dev tun1 proto kernel scope link src 10.10.2.3 
10.10.3.0/24 dev tun0 proto kernel scope link src 10.10.3.4 metric 50 
10.55.213.0/24 dev wlan0 proto kernel scope link src 10.55.213.1 metric 600 
128.0.0.0/1 via 10.10.2.1 dev tun1 
the.tun0.vpn.ip via 192.168.xxx.xxx dev eth0 proto static metric 100 
169.254.0.0/16 dev virbr0 scope link metric 1000 linkdown 
the.tun1.vpn.ip via 10.10.3.1 dev tun0 
192.168.aaa.bbb/24 dev virbr0 proto kernel scope link src 192.168.aaa.ccc linkdown 
192.168.xxx.0/24 dev eth0 proto kernel scope link src 192.168.xxx.yyy metric 100 
192.168.xxx.xxx dev eth0 proto static scope link metric 100 
broadcast 10.10.2.0 dev tun1 table local proto kernel scope link src 10.10.2.3 
local 10.10.2.3 dev tun1 table local proto kernel scope host src 10.10.2.3 
broadcast 10.10.2.255 dev tun1 table local proto kernel scope link src 10.10.2.3 
broadcast 10.10.3.0 dev tun0 table local proto kernel scope link src 10.10.3.4 
local 10.10.3.4 dev tun0 table local proto kernel scope host src 10.10.3.4 
broadcast 10.10.3.255 dev tun0 table local proto kernel scope link src 10.10.3.4 
broadcast 10.55.213.0 dev wlan0 table local proto kernel scope link src 10.55.213.1 
local 10.55.213.1 dev wlan0 table local proto kernel scope host src 10.55.213.1 
broadcast 10.55.213.255 dev wlan0 table local proto kernel scope link src 10.55.213.1 
broadcast 127.0.0.0 dev lo table local proto kernel scope link src 127.0.0.1 
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1 
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1 
broadcast 127.255.255.255 dev lo table local proto kernel scope link src 127.0.0.1 
broadcast 192.168.aaa.bbb dev virbr0 table local proto kernel scope link src 192.168.aaa.ccc linkdown 
local 192.168.aaa.ccc dev virbr0 table local proto kernel scope host src 192.168.aaa.ccc 
broadcast 192.168.aaa.255 dev virbr0 table local proto kernel scope link src 192.168.aaa.ccc linkdown 
broadcast 192.168.xxx.0 dev eth0 table local proto kernel scope link src 192.168.xxx.yyy 
local 192.168.xxx.yyy dev eth0 table local proto kernel scope host src 192.168.xxx.yyy 
broadcast 192.168.xxx.255 dev eth0 table local proto kernel scope link src 192.168.xxx.yyy

我希望我正确地编辑了所有这些 IP,因为实际上某些 IP 每次都会发生变化,所以我将它们与我之前的编辑进行匹配。

我的直觉告诉我接下来要尝试

ip route replace 10.57.213.1/24 via 10.10.2.6 dev tun1 table AirSpot

但我得到的只是Error: Invalid prefix for given prefix length.,我不明白它的意思。我只是不明白。路由对我来说并不完全直观。有了这一行,我希望任何来自或发往10.57.213.1/24(手动设置的热点范围)的数据包都要经过10.10.2.6,我认为(基于 的详细输出openvpn) 就是 所在的地方tun1

编辑7:

我认为这是一种默认路由问题,但我不够专业,无法解决它。

答案1

您在评论中发布的解决方案几乎是正确的。缺少的是要使用的正确 IP 地址。

步骤 1:检索信息

您需要检索两条信息:

  1. 热点子网的 IP 地址。默认情况下,这些是 形式的随机网络10.42.*.0/24,因此您需要修复地址。最简单的方法是hotspot使用创建一个名为 的新 WiFi 连接nm-connection-editor。您需要:

    • 将模式设置Hotspot“无线上网”标签,
    • 将方法设置Shared with other computers“IPv4 设置”标签,
    • 通过在同一选项卡中添加 IP 地址(例如10.57.213.1带网络掩码)来为网络选择一个子网,24
    • 添加一些身份验证方法(例如 PSK)

    执行这些步骤后,您应该有一个配置良好的/etc/NetworkManager/system-connections/hotspot.nmconnection文件,其内容如下:

    [wifi]
    mode=ap
    
    [ipv4]
    address1=10.57.213.1/24
    method=shared
    

    您可以使用 开始连接nmcli connection up id hotspot

  2. VPN 网关的 IP 地址。它是固定的还是可变的取决于您使用的 VPN 类型。假设它是10.10.10.1

步骤 2:配置策略路由

  1. 这是一个一次性操作。我们需要一个额外的路由表。为了能够按名称引用它,让我们添加:

    200 hotspot
    

    /etc/iproute2/rt_tables

  2. 每次系统启动时执行一次。我们需要告诉内核,来自以下地址的数据包10.57.213.0/24应该使用以下hotspot表:

    ip rule add from 10.57.213.0/24 table hotspot
    
  3. 每次连接到 VPN 时,我们都需要为热点地址添加默认路由:

    ip route replace default via 10.10.3.1 dev tun1 table hotspot
    

    10.10.3.1根据路由表,其中是 VPN 隧道另一端的地址。

    您可以在NetworkManager 调度程序脚本,在这种情况下网关地址将在环境变量中$IP4_GATEWAY

编辑:要自动建立表的默认路由,请添加如下hotspot调度程序脚本:/etc/NetworkManager/dispatcher.d/hotspot.sh

#!/bin/bash
# Be verbose until you test this
set -ex

# First parameter passed by NM: interface
DEVICE="$1"
# Second parameter: action
CMD="$2"
IP=/bin/ip

# Delete the part after '/' from $IP4_ADDRESS_0
LOCAL_IP=${IP4_ADDRESS_0%/*}
if [ "$LOCAL_IP" != "" ]; then
  # Add a 'src' option to the route only if the IP is not empty
  SRC="src $LOCAL_IP"
fi

if [ "$CMD" = "vpn-up" ]; then
  $IP route replace default via $IP4_GATEWAY dev $DEVICE $SRC table hotspot
fi

我没有测试过这个。

相关内容