前言

本文是对上一篇文章:WireGuard:局域网跨城通信 的补充。将围绕远程办公的开发者,即不在办公网内的开发者,如何基于 WireGuard® 跨城访问办公网中的服务。

场景

团队提倡远程办公,开发者位于全国各地。公司在某个城市设有办公地点,办公地点的局域网内自建了虚拟化,并部署了开发相关的一系列服务(GitLab,CI,K8s)。

  • 不同城市的开发者需访问办公地点局域网中的多个服务。
  • 不同城市的开发者之间需互相访问。

挑战

  • 开发者如何稳定的跨公网访问局域网内所有设备(如同在办公地点的局域网内)。
  • 局域网内的 WireGuard 节点位于运营商 NAT 设备之后,不支持 NAT 穿透且无公网 IP。
  • 局域网内只运行一个 WireGuard 节点(而不是将所有服务加入 WireGuard 网络)。
  • 如何解决局域网网关不支持静态路由规则的问题。
  • 如何避免路由冲突

架构

wireguard-remote-development-architecture

思路

假设有两个局域网 LAN1,LAN2 分别是公司在深圳(LAN1)和北京(LAN2)的办公网。

有三台服务器,z(IP 前的字母)是公网服务器(有公网 IP),a 和 c 是内网服务器(无公网 IP)。公网服务器(z)和内网服务器(a 和 c)组建了一个 WireGuard 网络,且三台服务器开启封包转发(IP Forward)。

e 和 f 是两个远程办公的开发者,其中 e 在广州,f 在上海,每个开发者是一个 WireGuard Client,通过各自的 WireGuard 客户端配置加入 WireGuard 网络。

开发者访问服务

假设广州的开发者 e(10.70.0.4)要访问北京办公网(LAN2)的中的设备 d(192.168.200.244)。

e 通过 WireGuard 客户端接入 WireGuard 网络。客户端与 WireGuard Server 建立连接,并向系统路由表写入相关路由规则(192.168.200.0/24 由 wg0 负责接收)。

e 的内核通过系统路由表匹配 192.168.200.0/24 由 wg0 负责接收,内核将数据包发给 wg0。WireGuard 收到数据包后,根据目的地址和内部路由表1,匹配 192.168.200.0/24 的目标 Peer 是 z,WireGuard 将数据包转发给 z。

公网服务器(z)收到请求后,z 的内核通过系统路由表匹配 192.168.200.0/24 由 wg0 负责接收,内核将数据包发给 wg0。WireGuard 收到数据包后,根据目的地址和内部路由表,匹配 192.168.200.0/24 的目标 Peer 是 c,WireGuard 将数据包转发给 c。

内网服务器(c)收到请求后,c 的内核通过系统路由表发现 192.168.200.244/32 不是自己(192.168.200.248),而是局域网中设备 d。因为开启了封包转发,c 将数据包转发给设备 d。

设备 d 收到数据包并处理,生成响应 e(10.70.0.4)的数据包。设备 d 通过默认网关(192.168.200.1)确认数据包的下一跳,默认网关中配置了静态路由规则(指定 10.70.0.0/16 的下一跳是 c),因此默认网关将数据包发给 c。

内网服务器(c)收到请求后,c 的内核通过系统路由表匹配 10.70.0.0/16 由 wg0 负责接收,内核将数据包发给 wg0。WireGuard 收到数据包后,根据目的地址和内部路由表实现,匹配 10.70.0.0/16 的目标 Peer 是 z,WireGuard 将数据包发给 z。

公网服务器(z)收到请求后,z 的内核通过系统路由表匹配 10.70.0.0/16 由 wg0 负责接收,内核将数据包发给 wg0。WireGuard 收到数据包后,根据目的地址和内部路由表实现,匹配 10.70.0.4/32 的目标 Peer 是 e,WireGuard 将数据包发给 e。

设备 e 收到请求后,发现目标 IP 就是自己,e 接收并处理来自 d 的数据包。

开发者访问开发者

假设广州的开发者的设备 e(10.70.0.4)要访问上海的开发者的设备 f(10.70.0.5)。

设备 e 的内核通过系统路由表匹配 10.70.0.0/16 由接口 wg0 负责接收,内核将数据包发给 wg0。WireGuard 收到数据包后,根据目的地址和内部路由表实现,匹配 10.70.0.0/16 的目标 Peer 是 z,WireGuard 将数据包发给 z。

公网服务器(z)收到请求后,z 的内核通过系统路由表匹配 10.70.0.0/16 由 wg0 负责接收,内核将数据包发给 wg0。WireGuard 收到数据包后,根据目的地址和内部路由表实现,匹配 10.70.0.5/32 的目标 Peer 是 f,WireGuard 将数据包转给 f。

设备 f 收到请求后,发现目标 IP 是自己,f 接收并处理来自 e 的数据包。

操作

部署 WireGuard 网络

因为 e 和 f 是开发者设备(MacOS/Windows),所以这里 e 和 f 的配置是 wg-quick 的 conf 文件,通过 WireGuard 的 GUI 客户端导入配置即可。

生成密钥对的命令如下(在开发本地执行如下命令即可创建出私钥、公钥、预共享密钥):

prikey="$(wg genkey)"; pubkey="$(wg pubkey <<< ${prikey})"; pskkey="$(wg genpsk)"
echo -e "PrivateKey: ${prikey}\nPublicKey: ${pubkey}\nPresharedKey: ${pskkey}"

e 的配置如下:

[Interface]
PrivateKey = WMWozvjIgpA2h75juoku2btWxbJ54i4Yt0A0RhpW7V8=
ListenPort = 51820
Address = 10.70.0.4/16
MTU = 1280

[Peer]
PublicKey = CmmeC0yqofMMZhEGHuK5dd2Mxyxe7tA8wSniDWiI5V0=
PresharedKey = KKQGN01IkZ1kJD2fAxtDZ6k5VFAI2fMca2q+SV7OrGE=
Endpoint = 39.101.166.124:51820
AllowedIPs = 10.70.0.0/16
AllowedIPs = 192.168.200.0/24
AllowedIPs = 192.168.201.0/24
PersistentKeepalive = 15

f 的配置如下:

[Interface]
PrivateKey = mOUA5x3hfa4D3zwC1HpivQYH2f/z6Ltdpm4YeEQSFXg=
ListenPort = 51820
Address = 10.70.0.5/16
MTU = 1280

[Peer]
PublicKey =CmmeC0yqofMMZhEGHuK5dd2Mxyxe7tA8wSniDWiI5V0=
PresharedKey = pXt2C8EeBPF+y7izRv40GwYpEtaF625PRlp9kcTSzIM=
Endpoint = 39.101.166.124:51820
AllowedIPs = 10.70.0.0/16
AllowedIPs = 192.168.200.0/24
AllowedIPs = 192.168.201.0/24
PersistentKeepalive = 15

公网服务器(z)配置:

文件:/etc/systemd/network/wg0.netdev(WireGuard 内部路由表规则通过这份文件中的 AllowedIPs 来指定)

[NetDev]
Name=wg0
Kind=wireguard
MTUBytes=1280

[WireGuard]
ListenPort=51820
PrivateKey=qJwN1zu5alr89c6k18U4SUwZXnUgVhr/tvSgLM7rmHQ=

# LAN1 WireGuard Client
[WireGuardPeer]
PublicKey=u4vkZywF9hZcy5QUhcbOCjD2EZ7GL2yXgoAH+IoIbHE=
PresharedKey=IBAsO/DwbautQjq/Gksv3lFJZwnUXvkMR3GyxeelS4o=
AllowedIPs=10.70.0.2/32
AllowedIPs=192.168.201.0/24
PersistentKeepalive=15

# LAN2 WireGuard Client
[WireGuardPeer]
PublicKey=/d8UR69JrdjxC2Fo9hvfZaoSC35LSGNLJ5mqjEyWjRo=
PresharedKey=YdpxayZdKMeoHzo9fVvBSWoDTn1c++r5awhm28Is9Ic=
AllowedIPs=10.70.0.3/32
AllowedIPs=192.168.200.0/24
PersistentKeepalive=15

# Remote Developer e
[WireGuardPeer]
PublicKey=0VooFEp8ZdpZp3P7BPa2W3piw+eu/6cyUGpSUWZp4HA=
PresharedKey=KKQGN01IkZ1kJD2fAxtDZ6k5VFAI2fMca2q+SV7OrGE=
AllowedIPs=10.70.0.4/32
PersistentKeepalive=15

# Remote Developer f
[WireGuardPeer]
PublicKey=MyeHCD9sVXMXPgyEY79Yif8QskCjqm+SoJqmLXHN1RM=
PresharedKey=pXt2C8EeBPF+y7izRv40GwYpEtaF625PRlp9kcTSzIM=
AllowedIPs=10.70.0.5/32
PersistentKeepalive=15

文件:/etc/systemd/network/wg0.network(系统级的路由表规则通过这份文件指定)

[Match]
Name=wg0

[Network]
Address=10.70.0.1/16

[Route]
Destination=192.168.200.0/24

[Route]
Destination=192.168.201.0/24

添加好配置请执行:systemctl restart systemd-networkd 重启 systemd-networkd。

内网服务器(a)配置:

文件:/etc/systemd/network/wg0.netdev

[NetDev]
Name=wg0
Kind=wireguard
MTUBytes=1280

[WireGuard]
ListenPort=51820
PrivateKey=gNCkDUdQ3yBynzEST9XOd31NsPluF3Q7aeFu82QsV04=

[WireGuardPeer]
PublicKey=CmmeC0yqofMMZhEGHuK5dd2Mxyxe7tA8wSniDWiI5V0=
PresharedKey=IBAsO/DwbautQjq/Gksv3lFJZwnUXvkMR3GyxeelS4o=
Endpoint=39.101.166.124:51820
AllowedIPs=10.70.0.0/16
PersistentKeepalive=15

文件:/etc/systemd/network/wg0.network

[Match]
Name=wg0

[Network]
Address=10.70.0.2/16

添加好配置请执行:systemctl restart systemd-networkd 重启 systemd-networkd。

内网服务器(c)配置:

文件:/etc/systemd/network/wg0.netdev

[NetDev]
Name=wg0
Kind=wireguard
MTUBytes=1280

[WireGuard]
ListenPort=51820
PrivateKey=SF6RqNRo1c9vwFVteFonRwpbU1Ee1zsKp6v9c8pXwnA=

[WireGuardPeer]
PublicKey=CmmeC0yqofMMZhEGHuK5dd2Mxyxe7tA8wSniDWiI5V0=
PresharedKey=YdpxayZdKMeoHzo9fVvBSWoDTn1c++r5awhm28Is9Ic=
Endpoint=39.101.166.124:51820
AllowedIPs=10.70.0.0/16
PersistentKeepalive=15

文件:/etc/systemd/network/wg0.network

[Match]
Name=wg0

[Network]
Address=10.70.0.3/16

添加好配置请执行:systemctl restart systemd-networkd 重启 systemd-networkd。

封包转发

为了实现局域网级别的通信,我们需要开启三台服务器 a/c/z(WireGuard 节点)的封包转发,在服务器上分别执行一遍如下命令:

# sysctl 配置文件名开头的数字会影响优先级
# 为了确保配置项的确有效,请在最后执行:systemd-analyze cat-config sysctl.d 进行验证
echo -e 'net.ipv4.ip_forward = 1' > /etc/sysctl.d/10-ip-forward.conf
sysctl -p /etc/sysctl.d/10-ip-forward.conf

添加静态路由规则

为了能让 e 访问到 d,我们需要在 d 所在局域网(LAN2)的默认网关上,添加如下静态路由规则(我的测试环境的网关不支持静态路由规则,所以我直接在 d 上添加路由规则):

ip route add 10.70.0.0/16 via 192.168.200.248

同理,在 LAN1 的默认网关上,添加如下静态路由规则:

ip route add 10.70.0.0/16 via 192.168.201.247

e 和 f 就可以跟 LAN1/LAN2 中的所有设备互通了。

测试

d 的 IP 地址: 192.168.200.244,在 e 和 f 上测试能否访问 d:

ping 192.168.200.244

效果如下:

安全加固

由于连上 WireGuard 网络即可以访问 192.168.200.0/24(192.168.201.0/24)中的所有设备,这对于局域网是种风险。这里可以通过在内网服务器(a 和 c)上添加防火墙规则,限制公网服务器主动访问局域网(下面两种安全加固的方式二选一即可)。

添加了这些防火墙规则后,可以防止 WireGuard Server 节点(以及其他不在白名单内的节点)主动访问局域网。

iptables 安全加固

# 只允许 10.70.0.3 和 10.70.0.4 访问局域网,你可以按照实际情况,添加更多的 WireGuard Client's VPN IP 进来
iptables -t filter -I FORWARD 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t filter -I FORWARD 2 -s 10.70.0.3/32 -m conntrack --ctstate NEW -j ACCEPT
iptables -t filter -I FORWARD 2 -s 10.70.0.4/32 -m conntrack --ctstate NEW -j ACCEPT
iptables -t filter -I FORWARD 10 -j DROP

firewalld 安全加固

保存到:/etc/firewalld/direct.xml 内,然后执行:firewall-cmd --reload 即可。

<?xml version="1.0" encoding="utf-8"?>
<direct>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="1">-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="2">-s 10.70.0.3/32 -m conntrack --ctstate NEW -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="2">-s 10.70.0.4/32 -m conntrack --ctstate NEW -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="10">-j DROP</rule>
</direct>

常见问题

网关不支持静态路由规则

当局域网的网关不支持静态路由规则时,可以在局域网 WireGuard 节点(架构图中的 a 和 c)上开启 MASQUERADE,在转发时修改数据包的来源地址,从而实现静态路由规则的效果(下面两种配置 MASQUERADE 的方式二选一即可)。

下面的配置以 LAN2 中的内网服务器(c)作为例子,你需要根据你自己的实际情况进行调整(比如局域网网段,物理网卡名字等)。

iptables 配置 MASQUERADE

iptables -t nat -A POSTROUTING -s 10.70.0.0/16 -d 192.168.200.0/24 -o eth2 -j MASQUERADE

firewalld 配置 MASQUERADE

开启 public Zone 和 wireguard Zone 的 Forward 功能,然后将物理网卡(eth2) 和 wg0 放在一个 Zone 内(假设叫 wireguard):

wireguard (active)
  ...
  interfaces: eth2 wg0
  forward: yes
  masquerade: no
  ...

在 public Zone 添加 rich rule:

public (default, active)
  ...
  sources: 192.168.200.0/24
  services: dhcpv6-client ssh wireguard
  forward: yes
  masquerade: no
  ...
  rich rules:
        rule family="ipv4" source address="10.66.0.0/16" destination address="192.168.200.0/24" masquerade

即可通过 firewalld 实现 MASQUERADE。

测试 MASQUERADE 效果

在远程开发者 e 的设备上测试 WireGuard 网络是否正常。确保 e 可以通过 VPN IP 访问公网服务器 z 和内网服务器 c:

# 访问公网服务器 z 的 VPN IP:
ping 10.70.0.1 -c 2
# PING 10.70.0.1 (10.70.0.1) 56(84) bytes of data.
# 64 bytes from 10.70.0.1: icmp_seq=1 ttl=64 time=48.9 ms
# 64 bytes from 10.70.0.1: icmp_seq=2 ttl=64 time=48.2 ms

# 访问内网服务器 c 的 VPN IP:
ping 10.70.0.3 -c 2
# PING 10.70.0.3 (10.70.0.3) 56(84) bytes of data.
# 64 bytes from 10.70.0.3: icmp_seq=1 ttl=63 time=96.8 ms
# 64 bytes from 10.70.0.3: icmp_seq=2 ttl=63 time=96.4 ms

确保内网服务器 c 开启了 MASQUERADE(假设通过 iptables 方式配置 MASQUERADE):

iptables-save -t nat
# *nat
# :PREROUTING ACCEPT [1189:501372]
# :INPUT ACCEPT [5:1627]
# :OUTPUT ACCEPT [4:732]
# :POSTROUTING ACCEPT [5:816]
# -A POSTROUTING -s 10.70.0.0/16 -d 192.168.200.0/24 -o eth2 -j MASQUERADE
# COMMIT

在 e 上执行测试命令的同时在 d 上抓包:

# 在 e 上测试:
ping 192.168.200.244 -c 5
# PING 192.168.200.244 (192.168.200.244) 56(84) bytes of data.
# 64 bytes from 192.168.200.244: icmp_seq=1 ttl=62 time=98.3 ms
# 64 bytes from 192.168.200.244: icmp_seq=2 ttl=62 time=97.1 ms
# 在 d 上抓包:
tcpdump -i any -n icmp
# 04:38:02.622391 eth2  In  IP 192.168.200.248 > 192.168.200.244: ICMP echo request, id 16, seq 1, length 64
# 04:38:02.622428 eth2  Out IP 192.168.200.244 > 192.168.200.248: ICMP echo reply, id 16, seq 1, length 64
# 04:38:03.621300 eth2  In  IP 192.168.200.248 > 192.168.200.244: ICMP echo request, id 16, seq 2, length 64
# 04:38:03.621325 eth2  Out IP 192.168.200.244 > 192.168.200.248: ICMP echo reply, id 16, seq 2, length 64

从 d 上抓的包可以看到,来源地址是内网服务器 c 的内网 IP 地址(192.168.200.248)而不是远程开发者 e 的 VPN IP(10.70.0.4)。因此 MASQUERADE 确认生效了。

路由冲突

路由冲突发生在远程办公的开发者来到办公地点时。此时远程办公开发者的设备内,会出现重复的路由规则。导致局域网流量绕行公网。

首先模拟一下远程办公的开发者 e 通过 WireGuard 访问办公网设备 d 的场景,这里通过 iperf3 测试一下线路的速度,结果如下:

# 在 e 上:
iperf3 -c 192.168.200.244 -i 5 -n 1G
# [  5] local 10.70.0.4 port 46172 connected to 192.168.200.244 port 5201
# [ ID] Interval           Transfer     Bitrate         Retr  Cwnd
# [  5]   0.00-5.01   sec  21.0 MBytes  35.2 Mbits/sec  7561    333 KBytes
# [  5]   5.01-10.01  sec  15.4 MBytes  25.8 Mbits/sec   17    277 KBytes
# [  5]  10.01-15.00  sec  13.8 MBytes  23.1 Mbits/sec    0    319 KBytes
# [  5]  15.00-20.00  sec  19.1 MBytes  32.1 Mbits/sec  229    289 KBytes
# [  5]  20.00-25.00  sec  15.2 MBytes  25.6 Mbits/sec    0    323 KBytes
# [  5]  25.00-30.01  sec  15.5 MBytes  26.0 Mbits/sec    9    323 KBytes
# 在 d 上:
iperf3 -s -i 5
# Accepted connection from 192.168.200.248, port 46160
# [  5] local 192.168.200.244 port 5201 connected to 192.168.200.248 port 46172
# [ ID] Interval           Transfer     Bitrate
# [  5]   0.00-5.01   sec  18.4 MBytes  30.8 Mbits/sec
# [  5]   5.01-10.01  sec  14.2 MBytes  23.9 Mbits/sec
# [  5]  10.01-15.01  sec  14.6 MBytes  24.5 Mbits/sec
# [  5]  15.01-20.01  sec  18.5 MBytes  31.0 Mbits/sec
# [  5]  20.01-25.01  sec  16.0 MBytes  26.8 Mbits/sec
# [  5]  25.01-30.01  sec  15.1 MBytes  25.4 Mbits/sec

可以看到我的测试环境 WireGuard 网络的传输速度大概是 25 Mbits/sec。

下面模拟远程办公开发者来到办公地点时的场景,此时 e 接入办公网并通过 DHCP 直接获得一个 192.168.200.0/24 的 IP:

# 在 e 上:
ip a s wlan0
# wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
#   link/ether 52:54:00:0d:b4:90 brd ff:ff:ff:ff:ff:ff
#   altname enp10s0
#   inet 192.168.200.27/24 metric 1024 brd 192.168.200.255 scope global dynamic wlan0
#      valid_lft 3590sec preferred_lft 3590sec

出现路由冲突。路由表内有两条 192.168.200.0/24 的路由规则:

ip r | grep 200
# 192.168.200.0/24 dev wg0 scope link
# 192.168.200.0/24 dev eth2 proto kernel scope link src 192.168.200.27 metric 1024
# 192.168.200.1 dev eth2 proto dhcp scope link src 192.168.200.27 metric 1024

iperf3 测试同一个局域网内的 d,因为路由冲突,192.168.200.0/24 的局域网流量被转发到公网,实际上也只有 25 Mbits/sec,结果如下:

# 在 e 上:
iperf3 -c 192.168.200.244 -i 5 -n 1G
# Connecting to host 192.168.200.244, port 5201
# [  5] local 10.70.0.4 port 43220 connected to 192.168.200.244 port 5201
# [ ID] Interval           Transfer     Bitrate         Retr  Cwnd
# [  5]   0.00-5.01   sec  22.8 MBytes  38.1 Mbits/sec  6558    329 KBytes
# [  5]   5.01-10.01  sec  13.6 MBytes  22.9 Mbits/sec   10    279 KBytes
# [  5]  10.01-15.00  sec  13.9 MBytes  23.3 Mbits/sec    0    342 KBytes
# [  5]  15.00-20.01  sec  18.1 MBytes  30.4 Mbits/sec  231    302 KBytes
# [  5]  20.01-25.01  sec  16.4 MBytes  27.5 Mbits/sec    0    323 KBytes
# [  5]  25.01-30.01  sec  15.2 MBytes  25.6 Mbits/sec   10    324 KBytes
# 在 d 上:
iperf3 -s -i 5
# Accepted connection from 192.168.200.248, port 46160
# [  5] local 192.168.200.244 port 5201 connected to 192.168.200.248 port 43220
# [ ID] Interval           Transfer     Bitrate
# [  5]   0.00-5.00   sec  18.9 MBytes  31.7 Mbits/sec
# [  5]   5.00-10.01  sec  13.8 MBytes  23.0 Mbits/sec
# [  5]  10.01-15.01  sec  14.9 MBytes  25.0 Mbits/sec
# [  5]  15.01-20.00  sec  18.2 MBytes  30.6 Mbits/sec
# [  5]  20.00-25.01  sec  16.2 MBytes  27.3 Mbits/sec
# [  5]  25.01-30.01  sec  14.9 MBytes  25.0 Mbits/sec

解决办法:

路由表实际上是二叉前缀树的实现,我们可以添加一个优先级更低的路由规则作为目标路由规则的父节点(二叉前缀树的概念)从而降低 WireGuard 添加的路由规则的优先级。

wireguard-remote-development-trie.png

WireGuard GUI 客户端会根据 AllowedIPs 配置项添加对应的系统级路由规则,这里我们将远程开发者 e 客户端配置中的 192.168.200.0/24 改为 192.168.0.0/16 即可。

--- /etc/wireguard/wg0.conf.old 2024-01-22 13:30:54.793166541 +0000
+++ /etc/wireguard/wg0.conf     2024-01-28 05:15:34.232343033 +0000
@@ -9,6 +9,5 @@
 PresharedKey = KKQGN01IkZ1kJD2fAxtDZ6k5VFAI2fMca2q+SV7OrGE=
 Endpoint = 39.101.166.124:51820
 AllowedIPs = 10.70.0.0/16
-AllowedIPs = 192.168.201.0/24
-AllowedIPs = 192.168.200.0/24
+AllowedIPs = 192.168.0.0/16
 PersistentKeepalive = 15

然后我们再通过 iperf3 重新测试一下:

# 在 e 上:
iperf3 -c 192.168.200.244 -i 5 -n 1G
# Connecting to host 192.168.200.244, port 5201
# [  5] local 10.70.0.4 port 43220 connected to 192.168.200.244 port 5201
# [ ID] Interval           Transfer     Bitrate
# [  5]   0.00-5.01   sec  8.39 GBytes  14.4 Gbits/sec    0   2.49 MBytes
# [  5]   5.01-10.01  sec  8.11 GBytes  13.9 Gbits/sec    0   2.62 MBytes
# [  5]  10.01-15.00  sec  8.34 GBytes  14.3 Gbits/sec    0   2.75 MBytes
# [  5]  15.00-20.01  sec  8.24 GBytes  14.1 Gbits/sec    0   2.75 MBytes
# [  5]  20.01-25.01  sec  7.99 GBytes  13.7 Gbits/sec    0   4.28 MBytes
# [  5]  25.01-30.00  sec  7.63 GBytes  13.1 Gbits/sec    0   4.28 MBytes
# 在 d 上:
iperf3 -s -i 5
# Accepted connection from 192.168.200.248, port 46160
# [  5] local 192.168.200.244 port 5201 connected to 192.168.200.248 port 43220
# [ ID] Interval           Transfer     Bitrate
# [  5]   0.00-5.00   sec  8.39 GBytes  14.4 Gbits/sec
# [  5]   5.00-10.00  sec  8.12 GBytes  14.0 Gbits/sec
# [  5]  10.00-15.00  sec  8.36 GBytes  14.4 Gbits/sec
# [  5]  15.00-20.00  sec  8.25 GBytes  14.2 Gbits/sec
# [  5]  20.00-25.00  sec  7.99 GBytes  13.7 Gbits/sec
# [  5]  25.00-30.00  sec  7.73 GBytes  13.3 Gbits/sec

解决冲突后,局域网速度来到了 14Gbits/sec。

这个方法在 Linux/MacOS/iOS 上有效,Android 上未知(没有 Android 设备,无法测试),Windows 上无效(Windows 的路由表不是完全基于二叉前缀树,路由策略还受接口优先级和路由规则优先级的影响)。

总结

局域网互通解决的是两个办公网内的用户如何互相访问的问题。本文是对该场景的补充,旨在解决:不在办公网内的开发者如何访问任意办公网设备的问题。

如果你发现本文中存在任何语法错误,欢迎通过 主页 中 Email 联系我,另外你也可以在 关于 里面找到我的微信二维码。

参考


  1. WireGuard 内部路由表。WireGuard 内部有自己的路由表实现(区别于 Linux 系统路由表),基于二叉前缀树,通过 AllowedIPs 配置项指定前缀树中的节点,树节点跟 Peer 建立映射。 ↩︎