坑边闲话:WireGuard 作为下一代 VPN,基于 UDP 传输。我的理解是最好不要直接使用 WireGuard 做连接,而是把它当作某个大解决方案的内核使用。比如把 containerd 当作 K8S、docker 的核心组件。毕竟,直接使用 WireGuard 门槛非常高,而某些场景需要动态调节 MTU,这在手动配置的情况下几乎是不可实现的。

1. WireGuard 是什么?·

WireGuard (简称 wg) 是一个简单、快速且现代的虚拟专用网络(VPN)技术,提供了高效、安全和轻便的解决方案。相比于其它 VPN 协议,如 OpenVPN 和 IPsec,WireGuard 的代码更少、更易于审计,并且速度更快。

主要特点

  • 简单性:它的代码基础小,使得审计更容易。
  • 高性能:采用最新的加密技术。
  • 现代的加密技术:包括 Curve25519ChaCha20Poly1305 等。
  • 跨平台:支持 Linux、Windows、macOS、BSD、iOS、Android 等。
  • 无状态:没有传统的会话概念,每个数据包都是自包含的。

重要的时间节点

  • 2016:WireGuard 的初版发布。
  • 2018:得到了许多开源社区的关注和支持。
  • 2020:WireGuard 被合并到 Linux 内核 5.6 中。
  • 2021:逐渐被各大 Linux 发行版和其它操作系统所采纳。

2. 在 OpenWrt 中使用多个 wg 接口·

图 1. 多个 WireGuard 接口。

可以在 OpenWrt 中指定多个 Interfaces 的协议为 WireGuard VPN,从而实现更为复杂的网络接入。当然,这些端口都是虚拟的,而且要监听不同的 UDP 端口,比如:

  • lan_wg0 是我用来内网连接的,里面跑的都是我的私人流量,因此直接把防火墙 Zone 设置为 LAN (绿色)即可,还可以省去一次判断。
  • nipc_wg0 是用来管理实验室公共内网的,里面都是实验室同学的私人流量,因此我把它的防火墙 Zone 设置为 WAN(红色),防止其他人直接访问我的内网(那就很尴尬了!)

2.1 WireGuard 与路由表·

WireGuard 在其工作机制中涉及到操作系统的路由表。当我们设置 WireGuard VPN 连接时,一般会对路由表进行以下修改:

  1. 添加 VPN 通道设备:当 WireGuard 启动时,它会创建一个名为 wg0 (或其它名称) 的虚拟网络接口。这个接口就像一个真实的网络适配器,但实际上它是一个 VPN 通道。
  2. 路由表条目:WireGuard 配置中的 AllowedIPs 参数定义了哪些 IP 地址应该通过 WireGuard 通道发送。为了使这一规则生效,WireGuard 会添加相应的路由表条目,指示这些 IP 地址应该通过 wg0 接口(或其它 WireGuard 接口)发送。

例如,如果你有以下的 WireGuard 配置:

1
2
3
[Peer]
PublicKey = ...
AllowedIPs = 10.0.0.2/32, 192.168.2.0/24

那么,路由表中会有如下条目:

1
2
10.0.0.2 via wg0
192.168.2.0/24 via wg0
  1. 默认路由:如果你希望所有的网络流量都通过 WireGuard 通道,那么 AllowedIPs 可以设置为 0.0.0.0/0, ::/0. 这会覆盖默认的路由,从而确保所有的流量都通过 WireGuard.
  2. NAT 和路由:如果 WireGuard 服务器充当网关并为客户端提供互联网接入,那么在 WireGuard 服务器上需要设置适当的网络地址转换(NAT)和路由规则。

总之,WireGuard 和本机路由表的关系是密切的,因为 WireGuard 需要修改路由表,以确保数据包沿正确的路径发送。这也是正确配置 WireGuard 和相关路由设置非常重要的原因。不当的配置可能导致数据泄露或无法建立 VPN 连接。

2.2 OpenWrt 多 WireGuard 接口·

注意:OpenWrt 在配置 WireGuard 虚拟接口时,如果要自动生成路由表,必须要勾选“路由允许的 IP”,否则将不产生对应的路由规则。

图 2. WireGuard 接口 wg1 的对端列表。

如上图,如果不勾选,在配置了相关 AllowedIPs 之后,配置已经成功,连接也已经建立,但无法在系统路由表里找到相关条目。

2.3 其他解决方案·

如果不勾选,则可通过在 wg1 接口上添加静态路由实现同样的功能。

图 3. 添加静态路由。

以下是相关的 /etc/config/network 片段:

1
2
3
4
config route
option interface 'nipc_wg0'
option target '10.10.0.0/16'
option gateway '192.168.123.1'

小结·

通过解决 DNS 问题,一般就能解决 WireGuard 在启动后无法识别端口的问题。毕竟,WireGuard 通过域名查询 endpoint 就十分依赖 DNS,而 OpenWrt 的 WireGuard 貌似只能强制使用系统的 DNS server 配置(/etc/resolv.conf),不能像 Windows 客户端那样指定某个 DNS server 的 IP 地址。