我有两个 Debian GNU/Linux 系统 (bullseye/sid),都在端口 23456 上运行 wireguard,均位于 NAT 之后。两者都运行内核版本 > 5.6 (wireguard 主线)。
系统 A 是服务器,它会动态更新其互联网域的权威名称服务器中的专用“A 记录”,其中包含分配给面向互联网的路由器 A(ZyWALL USG 100 防火墙)的正确公共 IP 地址。它每分钟更新一次,但公共 IP 地址实际上仅在路由器/防火墙重新启动时才会更改,而这种情况基本上从未发生过。
系统 B 位于 VDSL 路由器 B 后面,它充当 wireguard 客户端,指向动态更新的“A 记录”和端口 33456。路由器 B 是消费级 VDSL 路由器,它允许出站方向的所有内容,仅回复入站。
路由器/防火墙 A(ZyWALL USG 100)配置为允许端口 23456 上的 UDP 数据包通过,并将其转发到服务器 A。以下是相关的配置屏幕:
这是服务器 A 的 wireguard 配置文件(此代码片段中的键虽然有效,但不是真正的键):
[Interface]
Address = 10.31.33.100/24, fc00:31:33::1/64
ListenPort = 23456
PrivateKey = iJE/5Qy4uO55uUQg8nnDKQ/dFT1MEq+tDfFXrGNj3GY=
# PreUp = iptables -t nat -A POSTROUTING -s 10.31.33.0/24 -o enp1s0 -j MASQUERADE; ip6tables -t nat -A POSTROUTING -s fc00:31:33::/64 -o enp1s0 -j MASQUERADE
# PostDown = iptables -t nat -D POSTROUTING -s 10.31.33.0/24 -o enp1s0 -j MASQUERADE; ip6tables -t nat -D POSTROUTING -s fc00:31:33::/64 -o enp1s0 -j MASQUERADE
# Simon
[Peer]
PublicKey = QnkTJ+Qd9G5EybA2lAx2rPNRkxiQl1W6hHeEFWgJ0zc=
AllowedIPs = 10.31.33.211/32, fc00:31:33::3/128
以下是客户端 B 的 wireguard 配置(再次强调,密钥和域不是真实的):
[Interface]
PrivateKey = YA9cRlF4DgfUojqz6pK89poB71UFoHPM6pdMQabWf1I=
Address = 10.31.33.211/32
[Peer]
PublicKey = p62kU3HoXLJACI4G+9jg0PyTeKAOFIIcY5eeNy31cVs=
AllowedIPs = 10.31.33.0/24, 172.31.33.0/24
Endpoint = wgsrv.example.com:33456
PersistentKeepalive = 25
下面是一个描述这种情况的粗略图表:
Client B -> LAN B -> VDSL Router B (NAT) -> the internet -> ZyWALL (NAT) -> LAN A -> Server A
在两个系统上启动 wireguard 不会建立 VPN 连接。在客户端上激活调试消息并在 iptables 中添加 LOG 规则以记录数据OUTPUT
包,我收到很多这样的消息:
[414414.454367] IN= OUT=wlp4s0 SRC=10.150.44.32 DST=1.2.3.4 LEN=176 TOS=0x08 PREC=0x80 TTL=64 ID=2797 PROTO=UDP SPT=36883 DPT=33456 LEN=156
[414419.821744] wireguard: wg0-simon: Handshake for peer 3 (1.2.3.4:33456) did not complete after 5 seconds, retrying (try 2)
[414419.821786] wireguard: wg0-simon: Sending handshake initiation to peer 3 (1.2.3.4:33456)
我已经在服务器中添加了 LOG iptables 规则,以便诊断路由器配置问题。
root@wgserver ~ # iptables -t nat -I INPUT 1 -p udp --dport 23456 -j LOG
它记录从客户端收到的 wireguard 数据包(但我无法判断它们是否无效或不完整):
[ 1412.380826] IN=enp1s0 OUT= MAC=6c:62:6d:a6:5a:8e:d4:60:e3:e0:23:30:08:00 SRC=37.161.119.20 DST=10.150.44.188 LEN=176 TOS=0x08 PREC=0x00 TTL=48 ID=60479 PROTO=UDP SPT=8567 DPT=23456 LEN=156
[ 1417.509702] IN=enp1s0 OUT= MAC=6c:62:6d:a6:5a:8e:d4:60:e3:e0:23:30:08:00 SRC=37.161.119.20 DST=10.150.44.188 LEN=176 TOS=0x08 PREC=0x00 TTL=48 ID=61002 PROTO=UDP SPT=8567 DPT=23456 LEN=156
所以我倾向于假设路由器 (ZyWALL USG 100) 已正确配置,允许数据包进入服务器本地网络。为了证实这一假设,我甚至尝试用另一个消费级路由器替换 ZyWALL,并将服务器转移到不同的互联网连接上,但问题仍然存在,所以我确信问题不在于防火墙,也不在于其特定的互联网连接。
以下是服务器网络配置,以防万一:
auto lo
iface lo inet loopback
auto enp1s0
iface enp1s0 inet static
address 10.150.44.188/24
gateway 10.150.44.1
最重要的是,其他 wireguard VPN 隧道使用相同的客户端、相同的 VDSL 路由器(客户端)、相同的互联网连接、类似的服务器配置(显然不同的密钥和域)、类似的防火墙配置(服务器端,不同的防火墙模型)确实可以正常工作。
答案1
这可能很愚蠢,但您是否尝试过创建新的服务器密钥、客户端密钥并重试?当配置文件错误时,Wireguard 可以采取这样的行动。
答案2
好的,您提到客户端使用的是 VDSL,所以我怀疑您遇到了 MTU 问题。
有线(以及现在的无线)网络连接的正常 MTU 为 1500 字节,但在 *DSL 上,PPPoE 层占用 8 个字节,因此可用的 MTU 实际上为 1492。(您的网络连接也可能设置为更低的 MTU。)
Wireguard 的数据包开销为 80 字节,这意味着隧道 MTU 默认为 1420。尝试将其降低相同的 8 个字节,即 1412。(或者,如果您的 MTU 已经低于 1492,则可将其降低。)
您还需要让客户端告诉服务器降低隧道数据包的 MTU。这可以通过 iptables 规则来实现。
在客户端 wg0.conf 上,你将需要类似以下内容:
[Interface]
MTU = 1412
PostUp = iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = iptables -D FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
;....the rest