# UBNT Wireguard IPv6 VPN 踩坑

Unifi 自带 Wireguard 服务器和客户端功能，当我搭建好 Wireguard 服务端准备从 Unifi 连接时发现，2025 年了，竟然还有不支持 IPv6 的设备…

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1758150934616/41edcc0d-6265-453e-b589-de26e4a4cda3.png align="center")

众所周知，新版 Unifi OS 是通过 Debian 魔改得来的，倘若 UBNT 没有无聊到自己实现了一个用户态且不支持 IPv6 的客户端的话，Debian 所支持的内核态 Wireguard 是肯定支持 IPv6 的，上图可见这里还支持填入域名，那么填入一个只有 IPv6 地址的域名能否绕过限制呢？

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1758151124056/fa35f07c-cd53-4297-b40c-50193cdd7873.jpeg align="center")

通过测试发现，当你给 Wireguard 对端填入一个只有 AAAA 记录的域名时，能够暂时提交设置（虽然仍不能使用），此时查看 Unifi OS 中 Wireguard 的配置可见，这个配置的 Peer 压根没有 Endpoint，看来 Unifi 面板会自行解析域名然后判断是否找到了<s>心心念念的</s> IPv4 地址，若否则置空 Endpoint，这也就说明不支持 v6 的限制完全位于 Unifi 面板前端

由此，解决方案就很清晰了，乱填一个 IPv4 地址提交设置，然后通过脚本定时替换掉这个 Endpoint 即可：

```jsx
# 在持久化目录新建
sudo mkdir -p /data/wg
sudo tee /data/wg/wg-endpoint.env >/dev/null <<'EOF'

IFACE=wgclt1

ENDPOINT=[2001:db8:1234::1]:12345

KEEPALIVE=60

PEER_PUBKEY=7uIEwhaI6pRuRHhZnF1Dz+nD/4aE9D+R9FsC1Bgmr3o=
EOF
```

新建一个脚本来自动完成替换

```jsx
sudo tee /data/wg/wg-endpoint.sh >/dev/null <<'EOF'
#!/bin/sh
set -eu

. /data/wg/wg-endpoint.env

log() { logger -t wg-endpoint "[$IFACE] $*"; echo "[wg-endpoint][$IFACE] $*"; }

[ -z "${ENDPOINT:-}" ] && { log "ENDPOINT not set, exit"; exit 0; }

# wait for wg binary (≤60s)
i=0; while ! command -v wg >/dev/null 2>&1;            do [ $((i+=1)) -gt 60 ] && log "wg not found" && exit 1; sleep 1; done
# wait for interface up (≤60s)
i=0; while ! wg show interfaces 2>/dev/null | grep -qw "$IFACE"; do [ $((i+=1)) -gt 60 ] && log "interface not up" && exit 1; sleep 1; done

PEER="${PEER_PUBKEY:-}"
[ -z "$PEER" ] && PEER="$(wg show "$IFACE" peers | head -n1 || true)"
[ -z "$PEER" ] && { log "no peer found"; exit 1; }

CUR_EP="$(wg show "$IFACE" endpoints | awk -v p="$PEER" '$1==p {print $2}')"
if [ "$CUR_EP" != "$ENDPOINT" ]; then
  log "setting endpoint: $CUR_EP -> $ENDPOINT"
  wg set "$IFACE" peer "$PEER" endpoint "$ENDPOINT"
else
  log "endpoint already $ENDPOINT"
fi

[ -n "${KEEPALIVE:-}" ] && wg set "$IFACE" peer "$PEER" persistent-keepalive "$KEEPALIVE" || true
log "current endpoint: $(wg show "$IFACE" endpoints | awk -v p="$PEER" '$1==p {print $2}')"
EOF

sudo chmod +x /data/wg/wg-endpoint.sh
```

由于 Unifi OS 本质 Debian，通过新建两个 service 即可实现自动化替换：

```jsx
sudo tee /etc/systemd/system/wg-endpoint.service >/dev/null <<'EOF'
[Unit]
Description=Enforce WireGuard endpoint on boot (UDM/UniFi OS)
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/data/wg/wg-endpoint.sh

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now wg-endpoint.service
```

上面这个 service 将在 Unifi OS 开机时执行一次替换，如果你担心 Endpoint 在之后被控制器替换（实测如果不改动 VPN 设置是不会触发覆盖的），还可以新建下面这个每 10min 执行一次的 service：

```jsx
sudo tee /etc/systemd/system/wg-endpoint.timer >/dev/null <<'EOF'
[Unit]
Description=Periodically enforce WireGuard endpoint

[Timer]
OnBootSec=30s
OnUnitActiveSec=10min
Unit=wg-endpoint.service

[Install]
WantedBy=timers.target
EOF

sudo systemctl enable --now wg-endpoint.timer
```

到这里，你应该已经成功连接上对端

当你打开网页测试，却发现打开网页异常缓慢，显然玩不明白 IPv6 的 UBNT 也忘了做 TCP MSS Clamping

通过以下命令实现 TCP MSS Clamping

```jsx
iptables -t mangle -A UBIOS_FORWARD_TCPMSS -o wgclt+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A UBIOS_FORWARD_TCPMSS -i wgclt+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A UBIOS_OUTPUT_TCPMSS -o wgclt+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
```

如果你的 Wireguard 隧道内支持 IPv6，你还需要补充 ip6tables 的命令

将下面的脚本加入到之前新建的 /data/wg/[wg-endpoint.sh](http://wg-endpoint.sh) 脚本底部（同时实现幂等添加）

```jsx

# add TCP MSS clamping
add_rule() { iptables -C "$@" 2>/dev/null || { iptables -A "$@"; log "added rule: $*"; }; }
for DIR in "-o" "-i"; do
  add_rule -t mangle UBIOS_FORWARD_TCPMSS "$DIR" wgclt+ -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
done
add_rule -t mangle UBIOS_OUTPUT_TCPMSS -o wgclt+ -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

# IPv6 clamping
#: <<'IP6'
#add6() { ip6tables -C "$@" 2>/dev/null || { ip6tables -A "$@"; log "added v6 rule: $*"; }; }
#for DIR in "-o" "-i"; do
#  add6 -t mangle UBIOS_FORWARD_TCPMSS "$DIR" wgclt+ -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
#done
#add6 -t mangle UBIOS_OUTPUT_TCPMSS -o wgclt+ -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
#IP6

log "MSS clamping done"
```

至此，你应该能够在 Unifi OS 上正常使用 IPv6 Wireguard 客户端了
