WireGuard原本是我在使用OpenVPN后发现的一个挺不错的VPN技术。

由于最开始我是被它极简的配置文件所吸引来学习并使用的,所以本篇文章也从配置文件入手来讲解它。

为了方便讲解,我们先假设一个情景。

现在有一台拥有公网IP的服务器(Server)、一台电脑(PC)和一台手机(Phone),PC和Phone要使用WireGuard创建VPN隧道连接Server访问其内网服务。

配置文件示例

Server配置示例

 # 本机配置
 # Server
 [Interface]
 PrivateKey = <SERVER_PRIVATE_KEY>
 Address = 10.0.0.1/24
 ListenPort = 51820
 MTU = 1420
 ​
 # 对端配置
 # PC
 [Peer]
 PublicKey = <PC_PUBLIC_KEY>
 AllowedIPs = 10.0.0.2/32
 ​
 # Phone
 [Peer]
 PublicKey = <PHONE_PUBLIC_KEY>
 AllowedIPs = 10.0.0.3/32

PC配置示例

 # 本机配置
 # PC
 [Interface]
 PrivateKey = <PC_PRIVATE_KEY>
 Address = 10.10.0.2/32
 DNS = 10.0.0.1
 MTU = 1420
 ​
 # 对端配置
 # Server
 [Peer]
 PublicKey = <SERVER_PUBLIC_KEY>
 AllowedIPs = 0.0.0.0/0
 Endpoint = <SERVER_PUBLIC_IP>:51820
 PersistentKeepalive = 25

Phone配置示例

 # 本机配置
 # Phone
 [Interface]
 PrivateKey = <PHONE_PRIVATE_KEY>
 Address = 10.10.0.3/32
 DNS = 10.0.0.1
 MTU = 1420
 ​
 # 对端配置
 # Server
 [Peer]
 PublicKey = <SERVER_PUBLIC_KEY>
 AllowedIPs = 0.0.0.0/0
 Endpoint = <SERVER_PUBLIC_IP>:51820
 PersistentKeepalive = 25

简单十几行就能创建连接的,相比于OpenVPN的配置来说真的强了不少。

配置字段解析

WireGuard不主动区分谁是客户端谁是服务端,而是区分本机(Interface)与对端(Peer),但是由于在实际环境中公网IP并不容易获取所以通常会把拥有公网IP的终端作为服务端。

服务端

字段

所属区域

作用

是否必要

PrivateKey

[Interface]

标识本机的密码学身份

必要

Address

[Interface]

为本机的隧道网络接口配置 IP 地址和前缀长度

可选

ListenPort

[Interface]

指定本机接收 WireGuard UDP 数据包的端口

可选

MTU

[Interface]

指定隧道接口的最大传输单元

可选

PublicKey

[Peer]

指定你要与哪个公钥身份建立安全通信

每个 Peer 必要

AllowedIPs

[Peer]

决定哪些目标 IP 地址的流量应该选择这个 Peer;决定从这个 Peer 收到的数据包允许使用哪些源 IP 地址

实际配置中必要

客户端

字段

所属区域

作用

是否必要

PrivateKey

[Interface]

标识本机的密码学身份

必要

Address

[Interface]

为本机的隧道网络接口配置 IP 地址和前缀长度

可选

DNS

[Interface]

请求客户端或系统在启用隧道时使用指定 DNS 服务器

可选

MTU

[Interface]

指定隧道接口的最大传输单元

可选

PublicKey

[Peer]

指定你要与哪个公钥身份建立安全通信

每个 Peer 必要

AllowedIPs

[Peer]

决定哪些目标 IP 地址的流量应该选择这个 Peer;决定从这个 Peer 收到的数据包允许使用哪些源 IP 地址

实际配置中必要

Endpoint

[Peer]

指定对端当前已知的网络端点

可选

PersistentKeepalive

[Peer]

按指定间隔发送经过认证的空数据包

可选

从简单密码学理解PrivateKey与PublicKey

首先需要知道一下两点,这也是非对称加密的关键:

  1. 私钥与公钥成对出现

  2. 私钥能轻松计算公钥,但公钥计算私钥困难

或许你会惊奇的发现:欸!为什么配置文件里面存储的PublicKey不是本机的PublicKey?

所以下面展示一下简要的加密流程(实际并非如此简单):

  1. 客户端发起请求使用服务端公钥加密客户端公钥,传递给服务端

  2. 服务端使用私钥解密并确认客户端公钥正确,使用客户端公钥加密服务端公钥,传递给客户端

  3. 客户端使用私钥解密并确认服务端公钥正确

  4. 客户端使用私钥与服务端公钥运算出对话密钥,后续对话使用该密钥加密

  5. 服务端使用私钥与客户端公钥运算出对话密钥,后续对话使用该密钥加密

多层NAT环境下的MTU

MTU 的基本原理

MTU(Maximum Transmission Unit,最大传输单元)是指一条网络链路能够承载的最大网络层数据包大小,通常以字节为单位。

以太网常见 MTU 为 1500 字节,即单个 IP 数据包的总长度通常不能超过 1500 字节。MTU 不代表网速或总传输量,而是限制单个数据包的大小。

当数据包超过链路 MTU 时,可能发生 IP 分片、数据包丢弃或发送端调整数据包大小等情况,具体取决于协议和网络设备的处理方式。

VPN 为什么需要考虑 MTU?

VPN 会对原始 IP 数据包进行加密和封装,在外层增加 IP、UDP 及 VPN 协议头部,从而增加数据包的总长度。

以常见的 WireGuard over IPv4 为例,封装开销通常约为 60 字节:

  • 外层 IPv4 头:20 字节

  • UDP 头:8 字节

  • WireGuard 数据头及认证标签:约 32 字节

假设外层路径 MTU 为 1500 字节,则内层 IP 数据包的理论上限约为:

1500 − 20 − 8 − 32 = 1440 字节

因此,WireGuard 常用 MTU 设定值为 1420,但实际合适的数值取决于底层网络、外层 IP 版本及其他封装开销。

多层 NAT 环境下 MTU 的必要性

多层 NAT 本身并不必然要求降低 MTU。 NAT 主要修改 IP 地址和端口,通常不会像 VPN 隧道一样额外增加一整套封装头部。

真正影响 MTU 的因素包括:

  1. 路径最小 MTU:数据包必须能够通过整条传输路径中 MTU 最小的链路。

  2. VPN 封装开销:封装后的外层数据包必须符合底层网络的 MTU 限制。

  3. 路径 MTU 发现(PMTUD):依赖网络设备通过 ICMP 等机制反馈数据包过大的问题。如果相关报文被防火墙过滤,可能导致发送端无法及时调整数据包大小。

  4. 额外隧道封装:如果 VPN 流量还经过其他 VPN、隧道或特殊网络链路,可用 MTU 可能进一步减小。

因此,多层 NAT 环境下是否需要调整 MTU,应根据实际传输路径判断,而不是简单地按照 NAT 层数计算。

MTU 不合适的典型表现

  • VPN 显示已连接,但网页加载不完整或停顿。

  • 小型 Ping 请求正常,大数据包传输失败。

  • 文件传输速度异常,或者部分网络服务无法正常使用。

这些现象可能与 MTU 不匹配或路径 MTU 发现失效有关,但也可能由防火墙、路由或其他网络问题导致。

WireGuard 的 MTU 设置建议

  • 网络正常时,优先使用客户端或软件的默认 MTU。

  • 常规 IPv4 WireGuard 场景可以从 1420 开始测试。

  • 如果存在移动网络、PPPoE、额外隧道封装或大数据包传输异常,可以尝试 1400、1380 等数值。

  • 调整后应测试不同大小的数据包和实际业务,而不只是确认 VPN 是否能够连接。

设计巧妙的AllowedIPs

AllowedIPs 的作用

AllowedIPs 是 WireGuard 配置中用于指定某个 Peer 所对应的 IP 地址范围的参数,它兼具两种功能:

  1. 路由选择:决定哪些目标 IP 地址的流量应该通过哪个 Peer 发送。

  2. 来源地址校验:接收数据时,验证解密后的数据包源 IP 是否属于该 Peer 被允许使用的地址范围。

例如:

 [Peer]
 PublicKey = CLIENT_PUBLIC_KEY
 AllowedIPs = 10.0.0.2/32

这表示该 Peer 对应 10.0.0.2 这个地址。发送到该地址的流量会选择这个 Peer;接收到来自该 Peer 的数据时,WireGuard 也会检查其源 IP 是否符合配置。

AllowedIPs 设计的巧妙之处

  1. 将路由选择与身份授权结合

传统网络中,路由表负责决定数据包发往哪里,访问控制机制则负责判断数据包是否有权使用某个地址。WireGuard 将 Peer 与 IP 地址范围关联起来,使路由选择和来源地址校验共享同一份配置,减少了配置复杂度。

  1. 以公钥识别 Peer,以 IP 范围约束其行为

WireGuard 使用公钥识别通信对端,而 AllowedIPs 规定这个 Peer 可以代表哪些源 IP 地址。即使数据包能够通过加密认证,如果其解密后的源 IP 不属于该 Peer 被允许的范围,也不会被接受。

  1. 支持灵活的网络拓扑

AllowedIPs 可以使用单个主机地址,也可以使用 CIDR 网段:

 AllowedIPs = 10.0.0.2/32

只允许对应单个 IPv4 地址。

 AllowedIPs = 10.0.0.0/24

覆盖整个 10.0.0.0/24 网段。

 AllowedIPs = 0.0.0.0/0

匹配所有 IPv4 目标地址,常用于 IPv4 全隧道配置。

  1. 让配置本身表达网络边界

通过为不同 Peer 指定不同的 IP 范围,可以明确哪些地址归哪个 Peer 负责。例如,服务器为每个客户端分配独立的 /32 地址,既便于路由,也能避免客户端冒用其他客户端的 VPN 地址。

额外的可选配置字段

WireGuard还有一些其他的配置字段,我没怎么用到过。

字段

所属区域

FwMark

[Interface]

Table

[Interface]

PreUp

[Interface]

PostUp

[Interface]

PreDown

[Interface]

PostDown

[Interface]

SaveConfig

[Interface]

PresharedKey

[Peer]