教程[25] 在 Unifi 的 Wireguard peer 中使用 IPv6 的方法

开篇废话

最近碰到一个需求,由于客户的网络暂时没有契约 provider ,所以只有NGN大内网 所以我们出于负责任的心态,使用 VPN 隧道来让客户在契约期间可以暂时上网。

具体构造也很简单:

┌───────────────────────────────────────────────────────────────┐
│                           NGN大内网                           │
│                                                               │
│  ┌──────────────┐        WireGuard VPN隧道        ┌──────────────┐ │
│  │   UniFi设备  │◄─────────── IPv6 ────────────►│   VPN服务器    │ │
│  │              │                               │ (我家)   │ │
│  └──────────────┘                               └───────┬────────┘ │
│                                                         │          │
│             客户网络                                    │          │
│          (无provider契约)                               │          │
└─────────────────────────────────────────────────────────┼──────────┘
                                                          │
                                                          ▼
                                              ┌──────────────────────┐
                                              │       Provider       │
                                              │ (v6plus/transix/     │
                                              │  xpass/OCN等)        │
                                              └──────────────────────┘

就是得益于 NGN 大内网内可以互相通信的原理,所以这样可以在没有运营商契约的情况下借道上网。
好像有点太偏题了,反正大概介绍下背景,什么奇妙的裏ワザ(

正文

我家现成的 VPN 是 Wireguard 正好就用上了,稍微折腾了下就发现了不能输入 IPv6 地址的坑:
not a valid IPv4

当然实际测试的话,推测是 Unifi 层面先预先解析 A 记录,然后再把 IP 地址喂给 wg ,所以填域名也是不会解析 AAAA 的(何况 NGN 内网情况下只有 aoi.flets-east.jp 有解析,没有公网)

于是稍微又想了下,然后问了下 GPT ,最后就有了这篇文章(

众所周知现在的 Unifi OS 就是个 Debian ,所以我们去开个 ssh:
enable ssh

然后 wg 自己改下 Endpoint 即可:

# wg
interface: wgclt1
  public key: XXXXXXXX
  private key: (hidden)
  listening port: 42757

peer: YYYYYY
  endpoint: [xxxxx]:37094 # Unifi 如果解析不到域名(仅限 A 记录),会没有 endpoint 这一列,不过无所谓
  allowed ips: 0.0.0.0/0, ::/0
  latest handshake: 1 minute, 6 seconds ago
  transfer: 698.13 MiB received, 296.23 MiB sent

这里我们摘抄下想修改的 interface 以及 peer pubkey 然后设定 endpoint 即可:

wg set wgclt1 peer YYYYYY endpoint "[xxxxx]:12345"

当然手动设置肯定不够的,我们还要进行配置固化,这里我们开个30s的定时任务:
基本上是 GPT 写的,大家自己改改即可:

/usr/local/bin/wg-check.sh

#!/bin/bash
EXPECTED_ENDPOINT="[预期地址]:9981"
PEER_KEY="YYYYYY"
ENDPOINT=$(wg show wgclt1 endpoints | grep "$PEER_KEY" | awk '{print $2}')

if [ "$EXPECTED_ENDPOINT" != "$ENDPOINT" ]; then
    wg set wgclt1 peer "$PEER_KEY" endpoint "$EXPECTED_ENDPOINT"
    # MTU 和静态路由可选,因为前面说了我只是想临时上个网,所以加的静态路由(Unifi 不支持指定 tunnel device 为 wan)
    # ip link set dev wgclt1 mtu 1280
    # ip r add default dev wgclt1
fi

chmod +x /usr/local/bin/wg-check.sh

systemctl edit --full --force wg-check.service

[Unit]
Description=Check WireGuard peer endpoint

[Service]
Type=oneshot
ExecStart=/usr/local/bin/wg-check.sh

systemctl edit --full --force wg-check.timer


[Unit]
Description=Run WireGuard peer check every minute

[Timer]
OnBootSec=30
OnUnitActiveSec=60
Unit=wg-check.service

[Install]
WantedBy=timers.target
systemctl enable --now wg-check.timer
systemctl status wg-check

总结

嘛,平时了解到的没有的知识居然在这个时候派上用场了,还是要多学习,有问题多问 GPT(

然后如果你也想和我一样把 wireguard 当 wan 来用的话,记得加一下默认路由什么的,以及防火墙里面加个 MASQ (以及这样加的话 Unifi 会认为自己还是没有网,所以远程管理什么的是用不了的)

最后 Unifi 的奇奇怪怪的 bug 还是多,而且 UI 感觉天天改,而且 IPv6 相关的功能做的还是有点差的感觉,不过至少开放系统 ssh 可以让我们自己修,还算不错了 = =

以上。