引言
WireGuard 是一款现代、轻量级的虚拟私人网络(VPN)协议,它同时支持 IPv4 和 IPv6 连接。简而言之,VPN 让你可以在不信任的网络环境中,像身处私人网络一样安全地传输数据。当你在公共 WiFi 等不安全网络上使用笔记本电脑或手机时,WireGuard 能够有效提升你的上网安全。
WireGuard 的加密机制依赖于公钥和私钥对,对等端(peers)之间通过这些密钥建立加密隧道。每个 WireGuard 版本都采用一套固定的现代加密方法,这使得协议本身保持简洁、可预测,避免了运行时的协商过程,从而显著降低了配置出错的风险。
与传统的 VPN 解决方案,例如 OpenVPN 和 IPsec 相比,它们通常依赖 TLS 和证书来认证并建立加密隧道。这种方式虽然灵活,能支持多种客户端,但也增加了配置的复杂性,使得网络行为难以推理。WireGuard 的设计理念则更侧重于简洁和高效。
在这篇教程里,我将带领大家在 Ubuntu 服务器上部署 WireGuard,并配置另一台机器作为其对等端,实现 IPv4 和 IPv6 的双栈连接。我们还会探讨如何将对等端的流量通过 WireGuard 服务器进行路由,以实现网关功能,以及如何利用 VPN 进行加密的对等通信。
除了核心设置,本文还会深入探讨一些实际部署中非常重要的主题。这包括理解 WireGuard 的对等架构、密钥的管理与轮换、正确处理 IPv6 和双栈路由、提升 NAT 后对等端的可靠性、性能调优,以及 WireGuard 与 OpenVPN 在传输协议和防火墙行为上的差异。
为了方便演示,本教程将使用另一个 Ubuntu 系统作为 WireGuard 对等端。本系列的后续教程会涵盖在 Windows、macOS、Android 和 iOS 上安装和使用 WireGuard 的内容。
提示:如果你计划在 DigitalOcean Droplet 上设置 WireGuard,请注意 DigitalOcean 和许多其他托管服务提供商一样,会对超出套餐的带宽收取费用。因此,请留意你的服务器处理了多少流量。更多信息,请参阅 DigitalOcean 的带宽计费页面。
核心要点:
- WireGuard 是一种轻量级 VPN,采用现代加密技术,基于公私钥对的简洁设计,有效降低了配置复杂度和错误。
- WireGuard 采用对等(peer-to-peer)架构,所有系统运行相同的软件;“服务器”和“对等端”仅描述网络拓扑,而非不同角色或能力。
- WireGuard 中所有加密、认证和路由行为都在配置文件中明确定义,没有控制平面、证书颁发机构或运行时协商。
AllowedIPs设置具有双重作用:它既控制通过隧道路由的流量,也是对来自对等端的入站流量的严格访问控制列表。- WireGuard 平等支持 IPv4 和 IPv6,双栈配置需要为每种协议仔细设置路由、防火墙规则和转发。
- 当 WireGuard 用作 VPN 网关时,服务器上必须配置 IP 转发和防火墙伪装(masquerading),以允许对等端流量访问外部网络。
wg-quick辅助工具自动化了路由创建、防火墙规则和接口设置,而 WireGuard 内核模块仅负责加密和解密数据包。- 在双栈设置中,如果未明确包含
::/0等 IPv6 路由,可能发生 IPv6 泄露,导致 IPv6 流量绕过 VPN,即使 IPv4 流量已正确隧道化。 - WireGuard 不会自动修改系统路由、DNS 设置或防火墙规则,因此需要
wg-quick或手动配置来管理路由和网络行为。 - 双栈 WireGuard 部署需要分别配置 IPv4 和 IPv6 的转发、防火墙规则和 ICMPv6 支持,因为操作系统独立处理每种协议。
先决条件
要完成本教程,你需要准备以下几项:
- 一台 Ubuntu 服务器,拥有一个具有
sudo权限的非 root 用户,并且已启用防火墙。你可以参考我们的《使用 Ubuntu 进行初始服务器设置》教程来完成这些设置。在本指南中,我们将把这台服务器称为 WireGuard 服务器。 - 一台客户端机器,用于连接到你的 WireGuard 服务器。在本教程中,我们将其称为 WireGuard 对等端。为了方便起见,我建议你使用自己的本地机器作为 WireGuard 对等端,但你也可以选择远程服务器或手机作为客户端。如果你使用的是远程系统,务必按照本教程后续可选章节的说明操作,以免将自己锁定在系统之外。
- 如果你打算将 WireGuard 与 IPv6 一起使用,还需要确保你的服务器已配置为支持此类流量。如果你想在 DigitalOcean Droplet 上启用 WireGuard 的 IPv6 支持,请参考这篇文档页面《如何在 Droplet 上启用 IPv6》。你可以在创建 Droplet 时添加 IPv6 支持,也可以之后按照该页面上的说明进行配置。
WireGuard 架构概览
在配置 WireGuard 之前,理解系统、对等端和网络流量如何交互是非常有帮助的。WireGuard 采用了一种刻意简化的架构,避免了控制平面、证书颁发机构和运行时配置参数的协商。所有加密、认证和路由行为都通过配置文件明确定义。
对等设计与拓扑术语
WireGuard 本质上是一种对等(peer-to-peer)协议。所有参与系统都运行相同的 WireGuard 软件和内核模块,没有明确的服务器或客户端二进制文件。
在本教程中,WireGuard 服务器指的是一种中心辐射型拓扑结构中的核心节点。这个系统是可公开访问的,并作为其他对等端的协调点。而 WireGuard 对等端则指连接到这个核心节点的设备。这些术语只是描述了本指南中使用的网络拓扑,并不代表软件角色或功能上的差异。
理解这种区别很重要,因为 WireGuard 没有专门的“仅服务器”配置选项。任何系统都可以根据密钥、地址和路由规则的定义,充当核心节点、边缘节点,或者两者兼具。
WireGuard 部署中的核心组件
一个 WireGuard 部署由少量清晰定义的组件构成,每个组件都有其特定的职责。
- 中心对等端(Hub):中心对等端是一个可公开访问的系统,在一个单一端口上监听加密的 UDP 流量。它托管一个虚拟隧道接口,通常命名为
wg0,并存储允许与其通信的其他对等端的公钥。中心对等端不会动态发现对等端,也不会隐式接受连接。它只接受那些公钥和允许的 IP 范围已明确配置的对等端发来的流量。 - 连接对等端(Spokes):连接对等端是建立到中心对等端的加密隧道的设备。这些设备可以是笔记本电脑、服务器、虚拟机或移动系统。每个对等端都拥有唯一的加密密钥对和一个或多个分配给其隧道接口的私有 IP 地址。对等端只有在其路由规则指示时,才会将流量发送到隧道中。
- 隧道接口(
wg0):隧道接口是每个参与系统上创建的虚拟网络设备。所有加密流量都通过这个接口进出。从操作系统的角度来看,wg0的行为就像一个标准的网络接口,允许应用正常的路由表、防火墙规则和转发行为。
加密、认证与握手
WireGuard 使用公钥密码学来认证对等端并加密流量。每个对等端都会生成一个长期私钥,该私钥保留在本地系统上,永不传输。对应的公钥则与其他对等端共享,并添加到它们的配置中。
当通信开始时,WireGuard 会基于 Noise 协议框架执行一个无声、自动的加密握手。这个握手会建立临时的会话密钥,并提供完美前向保密性。这些会话密钥会定期轮换,无需用户干预。
WireGuard 不会协商密码套件、认证方法或协议版本。所有加密原语都是设计固定的。这消除了整类配置错误,同时依然提供现代的安全保证。
支持的流量模式
WireGuard 支持多种流量模式,具体取决于路由和转发的配置方式。本教程主要关注两种最常见的用例。
对等通信或内部网络访问
在这种配置中,流量只在作为 VPN 一部分的系统之间加密。中心对等端充当安全端点或中继,但不将流量转发到外部网络。
这种配置通常用于访问私有服务、管理基础设施或连接隔离系统。只有当目标地址与对等端配置中定义的私有 IP 范围匹配时,流量才会被路由到隧道中。
VPN 网关模式
在网关模式下,中心对等端将来自其他对等端的流量转发到外部网络,包括公共互联网。对等端将其部分或全部流量发送到隧道中,中心对等端则使用 IP 转发和网络地址转换(NAT)将这些流量路由出去。
这种配置需要额外的系统设置,包括内核转发和防火墙规则。启用网关模式后,来自对等端的出站流量看起来像是源自中心对等端的公共 IP 地址。
AllowedIPs 的双重作用
AllowedIPs 指令在 WireGuard 中承担着两个截然不同的任务。
首先,它定义了出站路由行为。当一个数据包的目标地址与 AllowedIPs 中的某个条目匹配时,该数据包就会通过 WireGuard 隧道进行路由。
其次,AllowedIPs 还充当一个严格的入站访问控制列表。当从某个对等端收到数据包时,WireGuard 会检查该数据包的源 IP 地址。如果源地址不在该对等端的 AllowedIPs 列表中,数据包将立即被丢弃。
这种双重作用是故意的,但也是最常见的配置错误来源之一。仅仅正确的路由是不够的,对等端被允许使用的源 IP 地址也必须明确允许。
路由自动化和辅助工具
WireGuard 内核模块本身不修改系统路由、DNS 设置或防火墙规则。它只负责加密和解密数据包,并将它们与对等端关联起来。
路由自动化由 wg-quick 等辅助工具处理。这个实用程序读取 WireGuard 配置文件,并在隧道启动或关闭时应用必要的路由表条目、DNS 设置和防火墙规则。
如果 WireGuard 使用其他工具(如原始 wg 命令、systemd-networkd 或自定义脚本)进行配置,这些路由更改就必须手动管理。
这种分离设计保持了核心协议的简洁性,同时允许与不同的系统网络堆栈灵活集成。
步骤 1 — 安装 WireGuard 并生成密钥对
本教程的第一步是在你的服务器上安装 WireGuard。首先,更新你的 WireGuard 服务器的包索引,然后使用以下命令安装 WireGuard。如果你是第一次在本次会话中使用 sudo,系统可能会提示你输入 sudo 用户的密码:
sudo apt update
sudo apt install wireguard
现在 WireGuard 已经安装好了,下一步是为服务器生成一对私钥和公钥。我们将使用内置的 wg genkey 和 wg pubkey 命令来创建密钥,然后将私钥添加到 WireGuard 的配置文件中。
你还需要使用 chmod 命令更改刚刚创建的密钥的权限,因为默认情况下该文件对服务器上的任何用户都是可读的。
使用以下命令创建 WireGuard 的私钥并更改其权限:
wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
这个 sudo chmod go=... 命令会移除文件对于除 root 用户以外的其他用户和组的任何权限,确保仅有 root 用户能够访问这个私钥。这是一种非常重要地安全措施。
你应该会收到一行 base64 编码的输出,这就是私钥。输出的副本也会通过 tee 命令存储在 /etc/wireguard/private.key 文件中,以备将来参考。请仔细记下输出的私钥,因为你稍后需要在 WireGuard 的配置文件中添加它。
下一步是创建对应的公钥,它由私钥派生而来。使用以下命令创建公钥文件:
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
这个命令由三个通过 |(管道)运算符链接起来的独立命令组成:
sudo cat /etc/wireguard/private.key:这个命令读取私钥文件并将其输出到标准输出流。wg pubkey:第二个命令将第一个命令的输出作为其标准输入并进行处理以生成公钥。sudo tee /etc/wireguard/public.key:最后一个命令将公钥生成命令的输出重定向到名为/etc/wireguard/public.key的文件中。
当你运行该命令时,你将再次收到一行 base64 编码的输出,这是你的 WireGuard 服务器的公钥。请将其复制到某个地方以备参考,因为你需要将此公钥分发给连接到服务器的任何对等端。
步骤 2 — 选择 IPv4 和 IPv6 地址
在上一节中,我们安装了 WireGuard 并生成了用于加密服务器进出流量的密钥对。本节中,我们将为服务器创建一个配置文件,并设置 WireGuard 在服务器重启时自动启动。我们还将定义 WireGuard 服务器和对等端使用的私有 IPv4 和 IPv6 地址。
如果你打算同时使用 IPv4 和 IPv6 地址,请遵循这两个小节的说明。否则,请根据你 VPN 的网络需求,遵循相应小节的说明。
步骤 2(a) — 选择 IPv4 范围
如果你的 WireGuard 服务器将与 IPv4 对等端一起使用,那么服务器需要一系列私有 IPv4 地址供客户端和其隧道接口使用。你可以从以下保留的地址块中选择任何 IP 地址范围(如果你想了解更多关于这些地址块的分配方式,请访问 RFC 1918 规范):
10.0.0.0到10.255.255.255(10/8 前缀)172.16.0.0到172.31.255.255(172.16/12 前缀)192.168.0.0到192.168.255.255(192.168/16 前缀)
为了本教程的目的,我们将使用 10.8.0.0/24 作为第一个保留 IP 范围中的一个 IP 地址块。这个范围将允许最多 255 个不同的对等连接,并且通常不会与其他私有 IP 范围发生重叠或冲突。如果这个示例范围与你的网络配置不兼容,请随意选择一个适合你的地址范围。
WireGuard 服务器将从该范围中分配一个 IP 地址作为其私有隧道 IPv4 地址。这里我们使用 10.8.0.1/24,但 10.8.0.1 到 10.8.0.255 范围内的任何地址都可以使用。如果你选择了不同于 10.8.0.1/24 的地址,请记下你选择的 IP 地址。你将在“创建 WireGuard 服务器配置”中定义的配置文件中添加这个 IPv4 地址。
步骤 2(b) — 选择 IPv6 范围
如果你正在将 WireGuard 与 IPv6 一起使用,那么你需要根据 RFC 4193 中的算法生成一个唯一的本地 IPv6 单播地址前缀。你将与 WireGuard 一起使用的地址将与一个虚拟隧道接口相关联。你需要完成几个步骤才能在保留的私有 fd00::/8 IPv6 地址块中生成一个随机、唯一的 IPv6 前缀。
根据 RFC,获取唯一 IPv6 前缀的推荐方法是结合一天中的时间与系统(如序列号或设备 ID)的唯一标识值。然后将这些值进行哈希并截断,从而得到一组比特,可以用作保留私有 fd00::/8 IP 块中的唯一地址。
要开始为你的 WireGuard 服务器生成 IPv6 范围,请使用 date 工具和以下命令收集一个 64 位时间戳:
date +%s%N
你将收到一个类似下面的数字,这是自 1970-01-01 00:00:00 UTC 以来合并在一起的秒数(date 命令中的 %s)和纳秒数(%N):
Output
1628101352127592197
将该值记录下来,以备本节稍后使用。接下来,从 /var/lib/dbus/machine-id 文件中复制你的服务器的 machine-id 值。这个标识符对于你的系统是唯一的,并且只要服务器存在,它就不应该改变。
cat /var/lib/dbus/machine-id
你将收到类似以下的输出:
/var/lib/dbus/machine-id
20086c25853947c7aeee2ca1ea849d7d
现在你需要将时间戳与 machine-id 结合起来,并使用 SHA-1 算法对结果值进行哈希。该命令将使用以下格式:
printf <timestamp><machine-id> | sha1sum
运行命令,替换掉你的时间戳和机器标识值:
printf 162810135212759219720086c25853947c7aeee2ca1ea849d7d | sha1sum
你将收到一个类似以下的哈希值:
Output
4f267c51857d6dc93a0bca107bca2f0d86fac3bc -
请注意,sha1sum 命令的输出是十六进制的,因此输出使用两个字符表示一个字节的数据。例如,示例输出中的 4f 和 26 是哈希数据的前两个字节。
RFC 中的算法只需要哈希输出的最低有效(末尾)40 位,即 5 个字节。使用 cut 命令打印哈希中最后 5 个十六进制编码的字节:
printf 4f267c51857d6dc93a0bca107bca2f0d86fac3bc | cut -c 31-
-c 参数告诉 cut 命令只选择一组指定的字符。31- 参数告诉 cut 打印输入行中从第 31 个位置到末尾的所有字符。
你应该会收到类似以下的输出:
Output
0d86fac3bc
在这个示例输出中,字节集是:0d 86 fa c3 bc。
现在你可以通过将生成的 5 个字节与 fd 前缀拼接起来,构建你的唯一 IPv6 网络前缀,每 2 个字节用 : 冒号分隔,以提高可读性。因为你的唯一前缀中的每个子网总共可以容纳 18,446,744,073,709,551,616 个可能的 IPv6 地址,为了简单起见,你可以将子网限制为标准大小 /64。
使用之前生成的字节和 /64 子网大小,最终的前缀将是:
Unique Local IPv6 Address Prefix
fd0d:86fa:c3bc::/64
这个 fd0d:86fa:c3bc::/64 范围就是你将用于 WireGuard 服务器和对等端上分配独立 IP 地址给 WireGuard 隧道接口的。为了给服务器分配一个 IP,在最后的 :: 字符后添加一个 1。结果地址将是 fd0d:86fa:c3bc::1/64。对等端可以使用该范围内的任何 IP,但通常你在每次添加对等端时会将值递增,例如 fd0d:86fa:c3bc::2/64。请记下这个 IP,然后在教程的下一节中继续配置 WireGuard 服务器。
IPv6 和双栈配置的考量
本教程中现有的步骤解释了如何生成 IPv6 地址并将其分配给 WireGuard 接口。然而,WireGuard 中的 IPv6 行为与 IPv4 在几个重要方面有所不同,尤其是在 WireGuard 用作 VPN 网关时。理解这些差异有助于防止路由失败、部分隧道化和常见的 IPv6 泄露。
WireGuard 中的 IPv6 支持
WireGuard 将 IPv6 作为一流协议来支持。IPv6 流量使用与 IPv4 流量相同的机制进行加密、认证和路由。没有单独的 IPv6 模式或附加配置标志。如果 IPv6 地址分配给隧道接口并且路由规则允许,IPv6 流量将自动流经隧道。
与 IPv4 不同,IPv6 的设计旨在通过使用全局可路由地址来避免 NAT,但在实践中,许多 VPN 和云环境仍出于操作简便性而使用 NAT。然而,这种行为取决于网络环境。在许多 VPN 网关设置中,例如云 VPS 实例或家庭路由器,服务器不会收到可路由到 VPN 对等端的委托 IPv6 前缀。
在这些常见场景中,对等端被分配私有 IPv6 地址,通常来自唯一本地地址(ULA)范围。当使用私有 IPv6 地址且服务器没有可路由前缀时,仍然需要 IPv6 伪装。这通常通过 ip6tables -t nat 规则实现,类似于 IPv4 伪装,以允许 VPN 对等端访问公共互联网。
当有适当的前缀委托可用时,IPv6 可以完全避免 NAT。但是,大多数简单的 VPN 网关部署仍然依赖 IPv6 伪装来保持路由的可管理性。
双栈行为解释
双栈配置同时在同一个 WireGuard 接口上启用 IPv4 和 IPv6。在这种设置中,wg0 接口被分配一个 IPv4 地址和一个 IPv6 地址,并且每种协议独立路由。
操作系统会分别评估 IPv4 和 IPv6 路由。对等端可能会成功地将 IPv4 流量通过隧道路由,而 IPv6 流量则绕过隧道,反之亦然。这种行为是预期的,几乎总是表明配置问题,而不是 WireGuard 本身的问题。
要使双栈路由正常工作,必须满足几个条件。服务器和对等端都必须在其 WireGuard 接口上分配 IPv4 和 IPv6 地址。AllowedIPs 指令必须包含 IPv4 和 IPv6 范围。IP 转发必须为 IPv4 和 IPv6 分别启用。防火墙规则必须允许两种协议的转发和返回流量。
地址分配和前缀长度
对于 IPv4,WireGuard 部署通常使用 10.0.0.0/8 或 192.168.0.0/16 等私有地址范围。每个对等端通常被分配一个单一的 IPv4 地址。
对于 IPv6,通常将 VPN 网络定义为 /64 前缀,例如 fd00::/64。虽然以太网网络需要 /64 用于邻居发现和地址自动配置,但 WireGuard 作为第 3 层点对点接口运行,不使用这些机制。
正因如此,为每个对等端分配一个 /128 IPv6 地址(例如 fd00::2/128)是安全且通常推荐的做法。使用 /128 地址可确保严格的路由行为,并防止对等端在没有正确路由规则的情况下尝试直接与子网中的其他地址通信。
将网络定义为 /64 同时为对等端分配 /128 地址提供了清晰度并避免了模糊路由。
用 IPv6 路由所有流量
当 WireGuard 配置为 VPN 网关时,IPv6 流量必须像 IPv4 流量一样明确路由。
对于 IPv4,路由所有流量使用 0.0.0.0/0 前缀。对于 IPv6,等效前缀是 ::/0。如果目标是将所有流量通过 VPN 路由,则必须同时包含这两个前缀。
如果仅配置 0.0.0.0/0,则 IPv4 流量会通过 VPN 发送,而 IPv6 流量则继续使用本地网络接口。这种情况被称为 IPv6 泄露。它通常导致 DNS 查询、网络流量或应用程序连接绕过 VPN 经由 IPv6,而 IPv4 流量则保持受保护。
IPv6 泄露是常见的混淆来源,在启用双栈网络时应始终进行测试。
防火墙、转发和 ICMPv6
IPv6 转发必须独立于 IPv4 转发启用。启用其中一个不会自动启用另一个。在接口之间路由流量时,两种设置都是必需的。
防火墙规则也必须明确为 IPv6 定义。ufw、iptables 和 nftables 等工具将 IPv4 和 IPv6 视为独立的规则集。缺少 IPv6 规则可能会默默地阻止流量,即使 IPv4 连接看似正常工作。
允许 ICMPv6 流量尤其重要。与 IPv4 不同,IPv6 依赖 ICMPv6 来实现路径 MTU 发现等基本功能。如果 ICMPv6 被阻止,当传输较大的数据包时,连接可能会挂起或失败,即使小数据包看似正常工作。
常见双栈陷阱
在双栈 WireGuard 部署中,经常会出现几个问题。IPv6 路由可能从 AllowedIPs 指令中缺失,导致 IPv6 流量绕过隧道。服务器上可能未启用 IPv6 转发,阻止流量离开隧道接口。防火墙规则可能允许 IPv4 流量,但阻止 IPv6 或 ICMPv6 流量。DNS 解析器可能返回 IPv6 地址,即使 IPv6 路由未正确配置。
这些问题通常表现为间歇性故障,并经常被错误地诊断为应用程序或协议问题。
在 IPv4-Only、IPv6-Only 和双栈之间选择
在某些环境中,使用单一协议可以简化操作。
仅限 IPv4 的部署更容易与传统系统和工具集成。仅限 IPv6 的部署消除了对 IPv4 NAT 的需求并避免了地址耗尽,但它们需要提供商和客户端网络提供一致的 IPv6 支持。
双栈部署提供了最大的灵活性,但也需要最仔细的规划、配置和验证。
步骤 3 — 创建 WireGuard 服务器配置
在创建你的 WireGuard 服务器配置之前,你需要准备以下信息:
- 确保你已从“安装 WireGuard 并生成密钥对”部分获取到私钥。
- 如果你正在使用 IPv4 的 WireGuard,你需要从“选择 IPv4 范围”中为服务器选择的 IP 地址,在本示例中是
10.8.0.1/24。 - 如果你正在使用 IPv6 的 WireGuard,你需要从“选择 IPv6 范围”中为服务器生成的 IP 地址。在本示例中,IP 是
fd0d:86fa:c3bc::1/64。
获取所需的私钥和 IP 地址后,使用 nano 或你偏好的编辑器创建新配置文件,运行以下命令:
sudo nano /etc/wireguard/wg0.conf
将以下行添加到文件中,用你的私钥替换高亮的 base64_encoded_private_key_goes_here 值,并在 Address 行中填入 IP 地址。如果你想让 WireGuard 在不同端口可用,也可以更改 ListenPort 行:
[Interface]
PrivateKey = base64_encoded_private_key_goes_here
Address = 10.8.0.1/24, fd0d:86fa:c3bc::1/64
ListenPort = 51820
SaveConfig = true
SaveConfig 行确保在 WireGuard 接口关闭时,所有更改都会保存到配置文件中。
保存并关闭 /etc/wireguard/wg0.conf 文件。如果你使用的是 nano,可以通过 CTRL+X,然后 Y 和 ENTER 确认来完成。现在你拥有了一个初始的服务器配置,你可以根据你计划如何使用 WireGuard VPN 服务器在此基础上进行构建。
步骤 4 — 调整 WireGuard 服务器的网络配置
如果你只是使用 WireGuard 连接对等端到 WireGuard 服务器,仅为了访问服务器上的服务,那么你可以跳过此节。但如果你希望将 WireGuard 对等端的互联网流量通过 WireGuard 服务器进行路由,那么你就需要按照本教程的这一节来配置 IP 转发。
要配置转发,请使用 nano 或你偏好的编辑器打开 /etc/sysctl.conf 文件:
sudo nano /etc/sysctl.conf
如果你正在将 WireGuard 与 IPv4 一起使用,请在文件底部添加以下行:
/etc/sysctl.conf
net.ipv4.ip_forward=1
如果你正在将 WireGuard 与 IPv6 一起使用,请在文件底部添加以下行:
/etc/sysctl.conf
net.ipv6.conf.all.forwarding=1
如果你同时使用 IPv4 和 IPv6,请确保包含这两行。完成后保存并关闭文件。
要读取文件并为当前的终端会话加载新值,请运行:
sudo sysctl -p
Output
net.ipv6.conf.all.forwarding = 1
net.ipv4.ip_forward = 1
现在,你的 WireGuard 服务器将能够转发来自虚拟 VPN 以太网设备的传入流量到服务器上的其他设备,并从那里转发到公共互联网。使用此配置将允许你通过服务器的 IP 地址路由所有来自 WireGuard 对等端的网络流量,客户端的公共 IP 地址将有效地被隐藏。
然而,在流量能够通过你的服务器正确路由之前,你需要配置一些防火墙规则。这些规则将确保 WireGuard 服务器和对等端之间的流量正常流动。
步骤 5 — 配置 WireGuard 服务器的防火墙
在本节中,你将编辑 WireGuard 服务器的配置,以添加防火墙规则,确保服务器和客户端之间的流量被正确路由。与上一节一样,如果你只使用 WireGuard VPN 进行机器对机器连接以访问受 VPN 限制的资源,请跳过此步骤。
要允许 WireGuard VPN 流量通过服务器的防火墙,你需要启用伪装(masquerading),这是一种 iptables 概念,它提供即时动态的网络地址转换(NAT)以正确路由客户端连接。
首先,使用 ip route 子命令找到你的 WireGuard 服务器的公共网络接口:
ip route list default
公共接口是此命令输出中“dev”单词后面的字符串。例如,此结果显示名为 eth0 的接口,如下面高亮显示:
Output
default via 203.0.113.1 dev eth0 proto static
记下你的设备名称,因为你将在下一步将其添加到 iptables 规则中。
要将防火墙规则添加到你的 WireGuard 服务器,请再次使用 nano 或你偏好的编辑器打开 /etc/wireguard/wg0.conf 文件。
sudo nano /etc/wireguard/wg0.conf
在文件底部 SaveConfig = true 行之后,粘贴以下行:
. . .
PostUp = ufw route allow in on wg0 out on eth0
PostUp = iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PreDown = ufw route delete allow in on wg0 out on eth0
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PreDown = ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
PostUp 规则会在 WireGuard 服务器启动虚拟 VPN 隧道时执行。这些规则确保了流量在正确地被转发和伪装。在本示例中,它将添加三条 ufw 和 iptables 规则:
ufw route allow in on wg0 out on eth0:此规则将允许转发从wg0VPN 接口进入的 IPv4 和 IPv6 流量到服务器上的eth0网络接口。它与你在上一节中配置的net.ipv4.ip_forward和net.ipv6.conf.all.forwardingsysctl 值协同工作。iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE:此规则配置伪装,并重写从wg0VPN 接口进入的 IPv4 流量,使其看起来直接源自 WireGuard 服务器的公共 IPv4 地址。ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE:此规则配置伪装,并重写从wg0VPN 接口进入的 IPv6 流量,使其看起来直接源自 WireGuard 服务器的公共 IPv6 地址。
注意:IPv6 伪装需要内核支持
ip6table_nat。在某些发行版或云镜像中,此模块不可用或默认未启用。在这些情况下,你必须使用具有委托前缀的正确 IPv6 路由,而不是 NAT,并向对等端通告可路由的 IPv6 前缀,而不是使用 ULA 地址。
PreDown 规则在 WireGuard 服务器停止虚拟 VPN 隧道时运行。这些规则与 PostUp 规则相反,旨在在 VPN 停止时撤销 VPN 接口的转发和伪装规则。
在这两种情况下,请编辑配置以包含或排除适合你 VPN 的 IPv4 和 IPv6 规则。例如,如果你只使用 IPv4,那么你可以排除带有 ip6tables 命令的行。
反之,如果你只使用 IPv6,那么只在配置中包含 ip6tables 命令。ufw 行应该适用于 IPv4 和 IPv6 网络的任何组合。完成后保存并关闭文件。
配置 WireGuard 服务器防火墙的最后一部分是允许 WireGuard UDP 端口本身的流量进出。如果你没有更改服务器 /etc/wireguard/wg0.conf 文件中的端口,那么你将要打开的端口是 51820。如果你在编辑配置时选择了不同的端口,请务必在以下 UFW 命令中替换它。
如果你在遵循先决条件教程时忘记打开 SSH 端口,请在此处也添加它:
sudo ufw allow 51820/udp
sudo ufw allow OpenSSH
注意:如果你使用的是不同的防火墙或自定义了你的 UFW 配置,你可能需要添加额外的防火墙规则。例如,如果你决定通过 VPN 连接隧道化所有网络流量,你需要确保端口
53流量被允许用于 DNS 请求,以及端口80和443分别用于 HTTP 和 HTTPS 流量。如果你通过 VPN 使用其他协议,那么你也需要为它们添加规则。
添加这些规则后,禁用并重新启用 UFW 以重新启动它并加载你修改过的所有文件的更改:
sudo ufw disable
sudo ufw enable
你可以通过运行 ufw status 命令来确认规则已生效。运行它,你应该会收到类似以下的输出:
sudo ufw status
Output
Status: active
To Action From
-- ------ ----
51820/udp ALLOW Anywhere
22/tcp ALLOW Anywhere
51820/udp (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)
现在你的 WireGuard 服务器已配置为正确处理 VPN 流量,包括对等端的转发和伪装。有了防火墙规则,你可以启动 WireGuard 服务本身以监听对等端连接。
步骤 6 — 启动 WireGuard 服务器
WireGuard 可以配置为使用其内置的 wg-quick 脚本作为 systemd 服务运行。虽然你可以每次想要使用 VPN 时手动使用 wg 命令创建隧道,但这是一种手动过程,会变得重复且容易出错。相反,你可以借助 wg-quick 脚本,使用 systemctl 来管理隧道。
使用 systemd 服务意味着你可以配置 WireGuard 在启动时自动运行,这样只要服务器正在运行,你就可以随时连接到你的 VPN。为此,通过将其添加到 systemctl 来为定义的 wg0 隧道启用 wg-quick 服务:
sudo systemctl enable wg-quick@wg0.service
提示:请注意,该命令将隧道
wg0设备名称指定为服务名称的一部分。此名称映射到/etc/wireguard/wg0.conf配置文件。这种命名方法意味着你可以使用服务器创建任意数量的独立 VPN 隧道。例如,你可以拥有一个名为
prod的隧道设备,其配置文件将是/etc/wireguard/prod.conf。每个隧道配置可以包含不同的 IPv4、IPv6 和客户端防火墙设置。通过这种方式,你可以支持多个不同的对等连接,每个连接都有自己唯一的 IP 地址和路由规则。
现在启动服务:
sudo systemctl start wg-quick@wg0.service
使用以下命令再次检查 WireGuard 服务是否处于活动状态。你应该会看到服务显示为活动状态。请注意,wg-quick 在配置接口后退出,因此 active (exited) 是正常的。
sudo systemctl status wg-quick@wg0.service
Output
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: enabled)
Active: active (exited) since Wed 2021-08-25 15:24:14 UTC; 5s ago
Docs: man:wg-quick(8)
man:wg(8)
https://www.wireguard.com/
https://www.wireguard.com/quickstart/
https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
Process: 3245 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
Main PID: 3245 (code=exited, status=0/SUCCESS)
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] wg setconf wg0 /dev/fd/63
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip -4 address add 10.8.0.1/24 dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip -6 address add fd0d:86fa:c3bc::1/64 dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip link set mtu 1420 up dev wg0
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ufw route allow in on wg0 out on eth0
Aug 25 15:24:14 wg0 wg-quick[3279]: Rule added
Aug 25 15:24:14 wg0 wg-quick[3279]: Rule added (v6)
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
Aug 25 15:24:14 wg0 wg-quick[3245]: [#] ip6tables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
Aug 25 15:24:14 wg0 systemd[1]: Finished WireGuard via wg-quick(8) for wg0.
输出显示了用于创建虚拟 wg0 设备并为其分配你添加到配置文件中的 IPv4 和 IPv6 地址的 ip 命令。你可以使用这些规则来排除隧道故障,或者如果你想尝试手动配置 VPN 接口,也可以与 wg 命令本身一起使用。
服务器配置并运行后,下一步是将客户端机器配置为 WireGuard 对等端并连接到 WireGuard 服务器。
步骤 7 — 配置 WireGuard 对等端
配置 WireGuard 对等端与设置 WireGuard 服务器类似。一旦安装了客户端软件,你将生成公钥和私钥对,为对等端决定一个或多个 IP 地址,为对等端定义一个配置文件,然后使用 wg-quick 脚本启动隧道。
你可以通过使用以下步骤生成密钥对和配置,向 VPN 添加任意数量的对等端。如果你向 VPN 添加多个对等端,请务必跟踪它们的私有 IP 地址以防止冲突。
要配置 WireGuard 对等端,请确保使用以下 apt 命令安装了 WireGuard 包。在 WireGuard 对等端上运行:
sudo apt update
sudo apt install wireguard
创建 WireGuard 对等端的密钥对
接下来,你需要在对等端上生成密钥对,使用与你在服务器上相同的步骤。从你的本地机器或将作为对等端的远程服务器上,继续并使用以下命令为对等端创建私钥:
wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod go= /etc/wireguard/private.key
你将再次收到一行 base64 编码的输出,这就是私钥。输出的副本也存储在 /etc/wireguard/private.key 中。请仔细记下输出的私钥,因为你稍后需要将其添加到 WireGuard 的配置文件中。
接下来,使用以下命令创建公钥文件:
sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key
你将再次收到一行 base64 编码的输出,这是你的 WireGuard 对等端的公钥。请将其复制到某个地方以备参考,因为你需要将此公钥分发给 WireGuard 服务器以建立加密连接。
创建 WireGuard 对等端的配置文件
现在你已经有了一对密钥,你可以为对等端创建一个配置文件,其中包含建立与 WireGuard 服务器连接所需的所有信息。
你将需要配置文件中的一些信息:
- 你在对等端上生成的
base64编码的私钥。 - 你在 WireGuard 服务器上定义的 IPv4 和 IPv6 地址范围。
- 来自 WireGuard 服务器的
base64编码的公钥。 - WireGuard 服务器的公共 IP 地址和端口号。通常这将是 IPv4 地址,但如果你的服务器有 IPv6 地址并且你的客户端机器有到互联网的 IPv6 连接,你可以使用它而不是 IPv4。
掌握所有这些信息后,在 WireGuard 对等端机器上使用 nano 或你偏好的编辑器打开一个新的 /etc/wireguard/wg0.conf 文件:
sudo nano /etc/wireguard/wg0.conf
将以下行添加到文件中,根据需要替换高亮部分中的各种数据:
[Interface]
PrivateKey = base64_encoded_peer_private_key_goes_here
Address = 10.8.0.2/24
Address = fd0d:86fa:c3bc::2/64
[Peer]
PublicKey = U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
AllowedIPs = 10.8.0.0/24, fd0d:86fa:c3bc::/64
Endpoint = 203.0.113.1:51820
请注意,第一行 Address 使用了你之前选择的 10.8.0.0/24 子网中的一个 IPv4 地址。这个 IP 地址可以是子网中的任何一个,只要它与服务器的 IP 地址不同。每次添加对等端时将地址递增 1 通常是分配 IP 地址最简单的方法。
同样,请注意第二行 Address 使用了你之前生成的子网中的一个 IPv6 地址,并且将服务器的地址递增 1。同样,如果你决定使用不同的地址,该范围内的任何 IP 都是有效的。
文件的另一个值得注意的部分是最后的 AllowedIPs 行。这两个 IPv4 和 IPv6 范围指示对等端,只有当目标系统的 IP 地址在其中任一范围中时,才通过 VPN 发送流量。使用 AllowedIPs 指令,你可以限制对等端上的 VPN 仅连接到 VPN 上的其他对等端和服务,或者你可以配置该设置以通过 VPN 隧道化所有流量并将 WireGuard 服务器用作网关。
如果你只使用 IPv4,那么省略末尾的 fd0d:86fa:c3bc::/64 范围(包括逗号)。反之,如果你只使用 IPv6,那么只包含 fd0d:86fa:c3bc::/64 前缀,并省略 10.8.0.0/24 IPv4 范围。
在这两种情况下,如果你想通过 VPN 发送所有对等端的流量并将 WireGuard 服务器用作所有流量的网关,那么你可以使用 0.0.0.0/0(表示整个 IPv4 地址空间)和 ::/0(表示整个 IPv6 地址空间)。
(可选)配置对等端通过隧道路由所有流量
如果你选择使用 0.0.0.0/0 或 ::/0 路由通过隧道路由所有对等端的流量,并且对等端是一个远程系统,那么你需要完成本节中的步骤。如果你的对等端是本地系统,则最好跳过本节。
对于你通过 SSH 或其他协议使用公共 IP 地址访问的远程对等端,你需要在对等端的 wg0.conf 文件中添加一些额外的规则。这些规则将确保当隧道连接时,你仍然可以从隧道外部连接到系统。否则,当隧道建立后,所有通常在公共网络接口上处理的流量将无法正确路由以绕过 wg0 隧道接口,导致远程系统无法访问。
首先,你需要确定系统用作其默认网关的 IP 地址。运行以下 ip route 命令:
ip route list table main default
你将收到类似以下的输出:
Output
default via 203.0.113.1 dev eth0 proto static
记下高亮的网关 IP 地址 203.0.113.1 以备后用,以及设备 eth0。你的设备名称可能不同。如果是,请在以下命令中替换 eth0。
接下来,通过使用 ip address show 命令检查设备来查找系统的公共 IP:
ip -brief address show eth0
你将收到类似以下的输出:
Output
eth0 UP 203.0.113.5/20 10.20.30.40/16 2604:a880:400:d1::3d3:6001/64 fe80::68d5:beff:feff:974c/64
在这个示例输出中,高亮的 203.0.113.5 IP(不带末尾的 /20)是分配给 eth0 设备的公共地址,你需要将其添加到 WireGuard 配置中。
现在,使用 nano 或你偏好的编辑器打开 WireGuard 对等端的 /etc/wireguard/wg0.conf 文件。
sudo nano /etc/wireguard/wg0.conf
在 [Peer] 行之前,添加以下 4 行:
PostUp = ip rule add table 200 from 203.0.113.5
PostUp = ip route add table 200 default via 203.0.113.1
PreDown = ip rule delete table 200 from 203.0.113.5
PreDown = ip route delete table 200 default via 203.0.113.1
[Peer]
. . .
这些行将创建自定义路由规则,并添加自定义路由以确保到系统的公共流量使用默认网关。
PostUp = ip rule add table 200 from 203.0.113.5:此命令创建一个规则,当 IP 与系统的公共203.0.113.5地址匹配时,检查表号为200的任何路由条目。PostUp = ip route add table 200 default via 203.0.113.1:此命令确保任何由200表处理的流量将使用203.0.113.1网关进行路由,而不是 WireGuard 接口。
PreDown 行在隧道关闭时移除自定义规则和路由。
注意:在构建这些规则时,表号
200是任意的。你可以使用 2 到 252 之间的值,或者通过向/etc/iproute2/rt_tables文件添加标签然后引用名称而不是数字值来使用自定义名称。有关 Linux 中路由表如何工作的更多信息,请访问《Linux IP 层网络管理指南》的路由表部分。
如果你正在通过 VPN 路由所有对等端的流量,请确保你已在“调整 WireGuard 服务器的网络配置”和“配置 WireGuard 服务器的防火墙”中配置了正确的 sysctl 和 iptables 规则。
(可选)配置 WireGuard 对等端的 DNS 解析器
如果你正在使用 WireGuard 服务器作为所有对等端流量的 VPN 网关,你需要在 [Interface] 部分添加一行来指定 DNS 解析器。如果你不添加此设置,那么你的 DNS 请求可能不会受到 VPN 的保护,或者它们可能会暴露给你的互联网服务提供商或其他第三方。
如果你只使用 WireGuard 来访问 VPN 网络上的资源或在对等配置中,那么你可以跳过此节。
要将 DNS 解析器添加到对等端的配置中,首先确定你的 WireGuard 服务器正在使用哪个 DNS 服务器。在 WireGuard 服务器上运行以下命令,如果你的以太网设备名称与此示例不同,请将其替换为 eth0:
resolvectl dns eth0
你应该会收到类似以下的输出:
Output
Link 2 (eth0): 67.207.67.2 67.207.67.3 2001:4860:4860::8844 2001:4860:4860::8888
输出的 IP 地址是服务器正在使用的 DNS 解析器。你可以选择使用其中任何一个或所有,或仅使用 IPv4 或 IPv6,具体取决于你的需求。记下你将要使用的解析器。
接下来,你需要将你选择的解析器添加到 WireGuard 对等端的配置文件中。回到 WireGuard 对等端,使用 nano 或你偏好的编辑器打开 /etc/wireguard/wg0.conf 文件:
sudo nano /etc/wireguard/wg0.conf
在 [Peer] 行之前,添加以下内容:
DNS = 67.207.67.2 2001:4860:4860::8844
[Peer]
. . .
同样,根据你对 IPv4 和 IPv6 的偏好或要求,你可以根据自己的需求编辑列表。
提示:一旦你在下一步连接到 VPN,你可以使用 DNS 泄露测试 等网站检查你是否正在通过 VPN 发送 DNS 查询。
你还可以使用你运行在服务器上的
resolvectl dns命令检查你的对等端是否正在使用配置的解析器。你应该会收到类似以下的输出,显示你为 VPN 隧道配置的 DNS 解析器:Output Global: 67.207.67.2 67.207.67.3 . . .
配置好所有这些 DNS 解析器设置后,你现在就可以将对等端的公钥添加到服务器,然后在对等端上启动 WireGuard 隧道了。
步骤 8 — 添加对等端的公钥到 WireGuard 服务器
在将对等端连接到服务器之前,将对等端的公钥添加到 WireGuard 服务器非常重要。此步骤可确保你能够连接到 VPN 并通过 VPN 路由流量。如果未完成此步骤,WireGuard 服务器将不允许对等端通过隧道发送或接收任何流量。
确保你已有一份 WireGuard 对等端的 base64 编码公钥,通过运行:
sudo cat /etc/wireguard/public.key
Output
PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
现在登录 WireGuard 服务器,并运行以下命令:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2,fd0d:86fa:c3bc::2
请注意,命令的 allowed-ips 部分接受逗号分隔的 IPv4 和 IPv6 地址列表。如果你想限制对等端可以分配给自己的 IP 地址,可以指定单个 IP,或者像示例中那样指定一个范围,如果你的对等端可以使用 VPN 范围内的任何 IP 地址。另请注意,没有两个对等端可以具有相同的 allowed-ips 设置。
如果你想更新现有对等端的 allowed-ips,可以再次运行相同的命令,但更改 IP 地址。支持多个 IP 地址。例如,要更改你刚刚添加的 WireGuard 对等端,以在现有 10.8.0.2 和 fd0d:86fa:c3bc::2 IP 中添加一个 10.8.0.100 这样的 IP,你将运行以下命令:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2,10.8.0.100,fd0d:86fa:c3bc::2
运行添加对等端的命令后,使用 wg 命令检查服务器上隧道的状泰:
sudo wg
Output
interface: wg0
public key: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
private key: (hidden)
listening port: 51820
peer: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
allowed ips: 10.8.0.2/32, fd0d:86fa:c3bc::/128
请注意 peer 行如何显示 WireGuard 对等端的公钥,以及它被允许用于分配 IP 的 IP 地址或地址范围。
现在你已经在服务器上定义了对等端的连接参数,下一步是在对等端上启动隧道。
步骤 9 — 连接 WireGuard 对等端到隧道
现在,你的服务器和对等端都已配置完毕,支持你选择的 IPv4、IPv6、数据包转发和 DNS 解析,是时候将对等端连接到 VPN 隧道了。
因为你可能只想在特定用例下开启 VPN,所以我们将使用 wg-quick 命令手动建立连接。如果你想像在服务器上那样自动化启动隧道,请遵循“启动 WireGuard 服务器”部分的步骤,而不是使用 wq-quick 命令。
如果你正在通过 VPN 路由所有流量并已设置 DNS 转发,你需要在启动隧道之前在 WireGuard 对等端上安装 resolvconf 实用程序。运行以下命令进行设置:
sudo apt install resolvconf
要在 WireGuard 对等端上启动隧道,请运行以下命令:
sudo wg-quick up wg0
你将收到类似以下的输出:
Output
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip -6 address add fd0d:86fa:c3bc::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x
请注意你分配给对等端的高亮的 IPv4 和 IPv6 地址。
如果你将对等端的 AllowedIPs 设置为 0.0.0.0/0 和 ::/0(或使用你为 VPN 选择的范围以外的范围),那么你的输出将类似于以下内容:
Output
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip -6 address add fd0d:86fa:c3bc::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x
[#] wg set wg0 fwmark 51820
[#] ip -6 route add ::/0 dev wg0 table 51820
[#] ip -6 rule add not fwmark 51820 table 51820
[#] ip -6 rule add table main suppress_prefixlength 0
[#] ip6tables-restore -n
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n
在此示例中,请注意命令添加的高亮路由,它们与对等端配置中的 AllowedIPs 对应。
你可以使用 wg 命令检查对等端隧道的状态:
sudo wg
Output
interface: wg0
public key: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
private key: (hidden)
listening port: 49338
fwmark: 0xca6c
peer: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
endpoint: 203.0.113.1:51820
allowed ips: 10.8.0.0/24, fd0d:86fa:c3bc::/64
latest handshake: 1 second ago
transfer: 6.50 KiB received, 15.41 KiB sent
你也可以再次检查服务器上的状态,你将收到类似的输出。
通过使用 ip route 和 ip -6 route 命令验证你的对等端是否正在使用 VPN。如果你将 VPN 用作所有互联网流量的网关,请检查将用于发往 CloudFlare 的 1.1.1.1 和 2606:4700:4700::1111 DNS 解析器的流量的接口。
提示:如果你只使用 WireGuard 访问 VPN 上的资源,请将有效的 IPv4 或 IPv6 地址(如网关本身)替换到这些命令中。例如
10.8.0.1或fd0d:86fa:c3bc::1。
ip route get 1.1.1.1
Output
1.1.1.1 dev wg0 table 51820 src 10.8.0.2 uid 1000
cache
请注意使用了 wg0 设备和分配给对等端的 IPv4 地址 10.8.0.2。同样,如果你使用 IPv6,请运行以下命令:
ip -6 route get 2606:4700:4700::1111
Output
2606:4700:4700::1111 from :: dev wg0 table 51820 src fd0d:86fa:c3bc::2 metric 1024 pref medium
再次注意 wg0 接口和分配给对等端的 IPv6 地址 fd0d:86fa:c3bc::2。
如果你的对等端安装了浏览器,你还可以访问 ipleak.net 和 ipv6-test.com 来确认你的对等端正在通过 VPN 路由其流量。
一旦你准备好断开对等端的 VPN 连接,请使用 wg-quick 命令:
sudo wg-quick down wg0
你将收到类似以下的输出,表明 VPN 隧道已关闭:
Output
[#] ip link delete dev wg0
[#] resolvconf -d tun.wg0 -f
如果你将对等端的 AllowedIPs 设置为 0.0.0.0/0 和 ::/0(或使用你为 VPN 选择的范围以外的范围),那么你的输出将类似于以下内容:
Output
[#] ip rule delete table 200 from 203.0.113.5
[#] ip route delete table 200 default via 203.0.113.1
[#] ip -4 rule delete table 51820
[#] ip -4 rule delete table main suppress_prefixlength 0
[#] ip -6 rule delete table 51820
[#] ip -6 rule delete table main suppress_prefixlength 0
[#] ip link delete dev wg0
[#] resolvconf -d tun.wg0 -f
[#] iptables-restore -n
[#] ip6tables-restore -n
要重新连接到 VPN,请在对等端上再次运行 wg-quick up wg0 命令。如果你想从 WireGuard 服务器中完全删除对等端的配置,你可以运行以下命令,务必替换掉你想要删除的对等端的正确公钥:
sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= remove
通常,你只需要在对等端不再存在,或者其加密密钥受到威胁或更改时才移除对等端配置。否则,最好保留配置,以便对等端可以重新连接到 VPN,而无需你每次都添加其密钥和 allowed-ips。
管理和轮换 WireGuard 密钥
WireGuard 依赖静态公钥和私钥对进行认证和加密。这种设计显著降低了配置的复杂性,但也完全将密钥管理的责任交给了管理员。对于长期运行的 VPN 部署、共享基础设施或拥有多个对等端的环境,仔细的密钥管理对于维护安全和操作稳定性至关重要。
理解 WireGuard 密钥类型
每个 WireGuard 对等端都使用两类加密密钥。
- 长期私钥:私钥唯一标识一个对等端,并且必须始终保密。此密钥在加密握手期间用于认证对等端并派生短寿命的会话密钥。如果私钥被泄露,任何持有该密钥的系统都可以冒充该对等端。
- 长期公钥:公钥由私钥派生而来,并与其他对等端共享。在中心枢纽上,公钥决定哪些对等端被允许通信以及它们被允许使用的 IP 地址。
除了这些长期密钥,WireGuard 还会通过加密握手自动派生临时会话密钥。这些会话密钥会定期轮换,并在没有管理员参与的情况下提供完美前向保密性。
推荐的密钥管理实践
以下实践有助于降低风险并简化持续操作:
- 为每个对等端分配唯一的密钥对:每个设备都应该拥有自己的私钥和公钥对。使用唯一的密钥允许撤销单个设备的访问权限而不会影响其他设备。在多个系统之间重用密钥会增加泄露的影响并使审计复杂化。
- 限制对私钥材料的访问:私钥文件应仅由 root 用户可读。在 Linux 系统上,这通常意味着使用
chmod 600 /etc/wireguard/private.key等命令将权限设置为600。限制文件访问有助于防止通过备份、日志或非特权用户意外泄露。 - 维护明确的对等端清单:记录每个对等端的公钥与其设备名称、分配的 IPv4 和 IPv6 地址以及预期用途之间的映射关系。随着对等端数量的增长,此文档变得越来越重要,并简化了故障排除、审计和日常维护。
- 及时移除未使用或不活动的对等端:当设备退役或不再需要 VPN 访问时,请从中心对等端配置中移除其公钥。保留未使用的密钥会增加攻击面并使未来的审查更加困难。
需要密钥轮换的情况
密钥轮换应在几种常见场景中执行:
- 怀疑或确认密钥泄露:如果私钥可能已被复制、泄露或被未经授权的方访问,则应立即轮换以防止冒充。
- 设备丢失或被盗:当设备丢失或被盗时,轮换其密钥可确保即使原始配置被恢复,它也无法再连接到 VPN。
- 组织安全要求:某些环境要求定期轮换密钥以满足内部策略或合规标准,即使没有怀疑泄露。
- 设备所有权或角色变更:当对等端被重新分配给不同的用户或用途时,轮换其密钥可防止意外的持续访问。
安全轮换对等端的密钥
WireGuard 使用密码密钥路由表将内部 IP 地址映射到特定的公钥。由于这种设计,同一个内部 IP 地址不能同时安全地分配给两个公钥。因此,密钥轮换通常会导致连接短暂中断,同时更新配置。
要轮换对等端的密钥,请遵循以下过程:
- 在对等端上生成新的私钥和公钥对。
- 更新中心对等端的配置,用新的公钥替换旧的公钥,同时保持相同的
AllowedIPs值。暂时不要重启接口。 - 更新对等端的配置文件以使用新的私钥。
- 在中心对等端上应用更新的配置,例如通过重新加载 WireGuard 服务或使用
wg syncconf。此时,对等端将暂时失去连接。 - 在对等端上重启 WireGuard 接口,使其开始使用新的私钥。
- 验证新的握手是否完成以及流量是否正常流动。
- 如果仍然存在旧密钥的任何引用,请将其移除。
这种基于替换的方法反映了 WireGuard 如何强制执行加密路由并避免模糊或冲突的配置。
轮换中心对等端的密钥
轮换中心对等端的私钥会影响所有连接的对等端。每个对等端配置都必须使用新的公钥进行更新,然后才能恢复连接。
由于此更改会同时影响每个对等端,因此应仔细规划中心对等端密钥轮换,并在维护窗口期间执行。实际上,中心密钥的轮换频率低于对等端密钥。
管理预共享密钥(可选)
除了公钥和私钥对,WireGuard 还支持为每个对等端配置可选的预共享密钥(PSK)。PSK 在 WireGuard 现有加密的基础上增加了一层对称加密。
预共享密钥通常在高度安全的坏境中使用,作为防御未来密码学进步的一种手段。如果加密流量在今天被记录下来,并且底层的公钥算法在未来被攻破,PSK 仍然可以阻止对过去会话的解密。
如果使用 PSK,则应将其视为敏感秘密并定期轮换。轮换 PSK 的操作模式与轮换对等端密钥相同,并且必须在连接的两端进行协调。
选择轮换频率
WireGuard 不强制执行固定的密钥轮换计划。合适的轮换间隔取决于环境。
- 个人或短期部署可能不需要定期轮换。
- 共享或生产环境通常每 6 到 12 个月轮换一此密钥。
- 高安全环境可能需要根据策略更频繁地轮换。
定期轮换可以降低与长期凭证相关的风险,并使 WireGuard 部署与常见的安全实践保持一致。
WireGuard 与 OpenVPN:实际差异
WireGuard 和 OpenVPN 都是广泛使用的 VPN 技术,但它们在加密、配置和网络行为方面采用了截然不同的方法。理解这些差异有助于开发人员选择最适合其操作限制的解决方案。
配置和操作模型
WireGuard 使用基于公钥和私钥对的静态配置模型。所有对等端都明确定义,路由行为通过固定配置值控制。没有控制通道、证书颁发机构或参数的动态协商。
OpenVPN 依赖 TLS 和 X.509 证书。它使用控制通道来认证客户端、协商加密设置和管理会话。这种模型提供了灵活性,但也增加了配置和操作的复杂性。
在实践中,WireGuard 配置更短、更易于审计,并且不易出现细微的配置错误。OpenVPN 配置提供了更多控制,但需要仔细管理才能保持安全和一致。
密码学和安全设计
WireGuard 使用一套固定的现代密码学方法。这些选择是不可配置的。这种设计消除了加密降级攻击,并消除了选择密码套件的需要。
OpenVPN 支持广泛的加密算法和认证方法。虽然这种灵活性允许与旧系统兼容,但它也增加了弱或不一致配置的风险。
两种解决方案都支持完美前向保密。WireGuard 通过其握手机制自动执行密钥轮换,而 OpenVPN 则依赖 TLS 会话行为。
性能特点
WireGuard 旨在实现高性能和低延迟。它在 Linux 内核中运行,代码库小,这减少了开销和上下文切换。在大多数环境中,WireGuard 以最少的调优即可提供更高的吞吐量和更一致的延迟。
从历史上看,OpenVPN 在用户空间中运行,并因上下文切换和协议处理而产生额外开销。OpenVPN 的现代版本支持 Kernel Data Channel Offload (DCO),这显著提高了性能,但此功能并非总是默认启用或可用。
即使有 DCO,WireGuard 通常也能以更少的配置变量实现强大的性能。
网络漫游和防火墙穿透
WireGuard 能够优雅地处理网络变化。如果对等端的 IP 地址发生变化,例如在 WiFi 和移动网络之间切换时,隧道可以继续工作而无需重新协商。
然而,WireGuard 仅通过 UDP 运行。虽然 UDP 效率很高,但有时它会在限制性公共 WiFi 网络、公司防火墙或机构网络上被阻止。当 UDP 流量被阻止时,WireGuard 没有原生回退机制。
OpenVPN 支持 UDP 和 TCP。当 UDP 不可用时,OpenVPN 可以配置为通过 TCP 端口 443 运行,使 VPN 流量看起来类似于标准的 HTTPS 流量。此功能使 OpenVPN 在具有严格防火墙规则或审查制度的环境中更加可靠。
对于在限制性网络后操作的用户,TCP 支持通常是选择 OpenVPN 而非 WireGuard 的决定性因素。
功能范围和可扩展性
OpenVPN 包含 WireGuard 刻意不提供的功能。这包括基于用户的认证、动态地址分配以及与外部身份系统的集成。
WireGuard 专注于安全的隧道。认证工作流、访问控制和动态配置必须在协议之外处理。
这使得 OpenVPN 更适合需要复杂认证或集中用户管理的环境,而 WireGuard 更适合基础设施级 VPN 和基于对等端的访问。
总结对比
| 方面 | WireGuard | OpenVPN |
|---|---|---|
| 传输协议 | 仅 UDP | UDP 和 TCP |
| 配置方式 | 静态,基于密钥 | 动态,基于证书 |
| 代码库大小 | 小 | 大 |
| 加密选择 | 固定 | 可配置 |
| 性能 | 高 | 中等到高 |
| 漫游支持 | 内置 | 有限 |
| 防火墙抵抗 | 在限制性网络上有限 | 通过 TCP 443 强 |
| 复杂性 | 低 | 高 |
在 WireGuard 和 OpenVPN 之间选择
WireGuard 非常适合基础设施 VPN、站点到站点隧道、移动客户端以及将简单性、性能和可预测性作为优先考虑的环境。
OpenVPN 对于需要基于 TCP 的隧道、高级认证或在限制性防火墙后可靠运行的企业环境来说仍然是一个强有力的选择。
在许多现代部署中,WireGuard 取代 OpenVPN 并非因为它提供更多功能,而是因为它以更清晰的行为提供了更少的功能。
性能调优和优化
WireGuard 在其默认设置下表现良好,但实际的网络条件可能会影响可靠性和吞吐量。数据包大小、路由范围、NAT 行为和 DNS 解析等因素都会影响隧道在持续或间歇使用时的行为。
让我们来看看最常见的调优领域以及何时进行调整是合适的。
MTU 选择和数据包分片
最大传输单元(MTU)定义了可以传输而不会碎片化的最大数据包大小。WireGuard 会对数据包进行加密和封装,这与物理网络接口相比,降低了实际的 MTU。
默认情况下,WireGuard 使用 1420 的 MTU。这个值考虑了 IPv6 头部、UDP 和 WireGuard 封装的总开销,对于大多数基于以太网的网络来说效果良好。某些环境可能需要更小的 MTU。这在移动网络、PPPoE 连接以及具有额外封装层的云平台上很常见。当 MTU 过大时,数据包可能会被丢弃或碎片化。这通常导致连接对小请求有效,但对大传输则停滞或失败。如果出现这些症状,建议逐渐降低 MTU。像 1360 这样的值,或者在更受限制的环境中,1280(IPv6 最小 MTU)通常可以解决这些问题,而对吞吐量的影响最小。
MTU 应在配置文件的 [Interface] 部分明确设置,以确保在重启时行为一致。
AllowedIPs 的范围和影响
AllowedIPs 指令影响路由行为和性能。宽泛的地址范围会导致更多流量通过隧道,从而增加加密开销和服务器负载。使用狭窄的 AllowedIPs 值会将隧道限制为仅需要保护的流量。这可以减少 CPU 使用并避免不必要的封装。
当配置 0.0.0.0/0 或 ::/0 时,所有流量都通过 VPN 路由。当隐私、集中出口控制或不信任网络是关注点时,此配置是合适的,但它会增加一般互联网流量的延迟和资源使用。
性能调优通常涉及在可能的情况下缩小 AllowedIPs 的范围,并避免全隧道路由,除非有要求。
NAT 穿透和连接稳定性 (PersistentKeepalive)
WireGuard 在没有数据传输时会故意保持静默。它默认不会发送周期性的心跳包。在使用 NAT 的环境中,例如家庭路由器、移动网络或许多云网络,这种静默可能会导致 NAT 设备关闭连接映射。发生这种情况时,来自服务器的入站流量会被阻塞,直到对等端再次发送流量。这种行为通常被认为是延迟、连接延迟或间歇性故障。
为了防止这种情况,WireGuard 提供了 PersistentKeepalive 设置。此选项可以添加到对等端配置的 [Peer] 部分。它使对等端以固定间隔发送一个小型心跳包,以保持 NAT 映射打开。通常使用 25 秒的值,并且与大多数 NAT 设备兼容。如果连接最初工作但闲置后失败,启用 PersistentKeepalive = 25 是主要且推荐的修复方法。
DNS 解析和隧道行为
DNS 配置对感知到的 VPN 性能有显著影响。当 DNS 解析器未正确通过隧道路由时,即使隧道本身正常工作,应用程序也可能显得缓慢或不可靠。
在网关配置中,DNS 查询应通过 VPN 发送,以确保一致的路由并避免泄露。这需要在对等端配置中明确定义 DNS 解析器。当 DNS 配置错误时,常见的症状包括页面加载缓慢、连接不稳定,或尽管隧道处于活动状态,流量却绕过 VPN 进行路由。
选择可以通过隧道访问并快速响应的解析器可以提高可靠性和用户体验。
IPv4 和 IPv6 性能差异
在双栈环境中,IPv4 和 IPv6 的行为可能不同。IPv6 路径可能具有不同的 MTU 限制、路由策略或防火墙行为。
独立测试两种协议有助于识别特定于协议的问题。ping、tracepath 和 ip route get 等工具对于验证每种地址族的路由和 MTU 行为非常有用。
如果 IPv6 性能似乎不稳定,请验证是否允许 ICMPv6 流量。ICMPv6 是路径 MTU 发现所必需的,阻止它可能会导致连接在传输较大数据包时停滞。
CPU 和加密开销
WireGuard 使用现代密码学,在大多数系统上效率很高。然而,加密仍然会消耗 CPU 资源。
在小型虚拟机、嵌入式路由器或没有硬件加速的系统上,全隧道配置在持续负载下可能会使 CPU 饱和。
在高流量期间监控 CPU 使用率有助于确定性能问题是由加密开销而非网络配置引起的。在这种情况下,可能需要减少隧道流量或升级服务器实例。
验证性能变化
性能调优应该循序渐进地进行。每次更改后,都应在应用额外调整之前验证连接性和稳定性。
有用的验证步骤包括使用 wg 检查握手稳定性,测量更改前后的延迟和吞吐量,以及使用 ip route 和 ip -6 route 确认路由行为。这种方法可以最大限度地降低风险并简化故障排除。
常见问题解答
1. WireGuard 是什么?它在 Ubuntu 上如何工作?
WireGuard 是一种现代 VPN 技术,旨在比 OpenVPN 或 IPsec 等老旧选项更快、更容易设置。你可以将其视为一个安全隧道,直接连接你的设备。与笨重复杂的传统 VPN 不同,WireGuard 非常轻量级。在 Ubuntu 上,它直接在 Linux 内核(操作系统的核心“引擎”)内部运行。因为它运行在系统深层而不是作为独立的应用程序运行,所以它使用极少的电池电量,并且处理数据速度极快。
为了建立连接,WireGuard 使用一种与 SSH 非常相似的方法。它为每个设备生成一对“密钥”:一个私钥(秘密保留在设备上)和一个公钥(你与想要连接的其他设备共享)。只有当密钥完美匹配时,连接才会发生,这使得握手快速且安全。
2. WireGuard 比 OpenVPN 更安全吗?
对于大多数用户来说,WireGuard 因其简洁性和现代设计而被认为更安全。主要原因是其代码的规模。WireGuard 的代码量大约只有 4,000 行,而 OpenVPN 超过 100,000 行。这种巨大的差异意味着安全专家更容易阅读 WireGuard 的代码,并在恶意行为者之前发现漏洞(bug)。
WireGuard 还强制你使用当今最新、最强的加密标准。老旧的 VPN 允许加密灵活性,这意味着它们可以降级到较弱的加密方法以支持旧设备。WireGuard 取消了这种选择,防止攻击者诱骗你的 VPN 使用较弱的锁。此外,WireGuard 默认是隐蔽的;如果未经授权的设备向你的服务器发送数据包,WireGuard 根本不会回复。这使得你的服务器对扫描开放端口的黑客来说是隐形的。
3. 我可以在没有 Docker 的情况下在 Ubuntu 上设置 WireGuard 吗?
当然可以,你可以直接在系统上设置,无需使用 Docker 容器。事实上,在 Ubuntu 上直接运行通常是首选方法,因为该软件已包含在标准的 Ubuntu 软件仓库中。你通常只需要运行下面的标准安装命令,它将直接从 Ubuntu 的官方源拉取必要的软件。
sudo apt update
sudo apt install wireguard
4. 我如何添加多个 WireGuard 客户端(对等端)?
WireGuard 使用对等概念,这意味着你连接的每个设备都被视为一个“对等端”。要添加多个设备,例如笔记本电脑、智能手机和平板电脑,你只需编辑服务器的配置文件(通常位于 /etc/wireguard/wg0.conf)。
对于每个新设备,你都要添加一个标有 [Peer] 的新文本块。在此块内,你必须粘贴该特定设备的公钥,并为其分配一个唯一的内部 IP 地址(例如,第一个设备为 10.0.0.2,第二个设备为 10.0.0.3,依此类推)。这些内部 IP 地址不能重叠,这一点至关重要。
这是一个简单的配置块示例:
[Interface]
# Server settings...
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <Server_Private_Key>
[Peer]
# Client 1 (Laptop)
PublicKey = <Laptop_Public_Key>
AllowedIPs = 10.0.0.2/32
[Peer]
# Client 2 (Phone)
PublicKey = <Phone_Public_Key>
AllowedIPs = 10.0.0.3/32
5. WireGuard 使用哪些端口?
WireGuard 默认使用 UDP 端口 51820。它严格依赖 UDP 协议,因为它比 TCP 更快地进行数据隧道传输。TCP 需要对发送的每个数据包进行确认,这会显著降低 VPN 连接的速度。UDP 只是发送数据而无需等待回执,这非常适合 WireGuard 的高速特性。在设置 Ubuntu 防火墙 (UFW) 时,你必须明确允许此 UDP 端口上的流量,否则连接请求将在到达 VPN 软件之前被阻止。
6. 我如何排除 WireGuard 连接问题?
排除 WireGuard 的故障通常非常直接,因为它的活动部件更少。如果你无法连接,你应该遵循以下特定的检查顺序:
首先,通过在服务器上运行 sudo wg show 来检查握手状态。如果连接正常,你将看到一行显示 latest handshake,后面跟着一个时间(例如,“1 minute ago”)。如果缺少此行,则设备根本没有相互通信。这几乎总是由防火墙阻止 UDP 端口或公钥/私钥不匹配引起的。
其次,如果握手正常但你无法浏览互联网,问题可能出在 IP 转发。你需要确保你的 Ubuntu 服务器被允许将流量从 VPN 路由到互联网。你可以通过查看文件 /etc/sysctl.conf 并确保行 net.ipv4.ip_forward=1 处于活动状态(未被注释掉)来验证这一点。
7. WireGuard 支持 Ubuntu 上的 IPv6 吗?
是的,WireGuard 对 IPv6 有出色的支持。它非常灵活,可以封装(包装)不同类型的流量。例如,你可以通过 IPv6 连接访问仅限 IPv4 的网站,反之亦然。要启用此功能,你只需在配置文件中,与标准 IPv4 地址一起包含逗号分隔的 IPv6 地址即可。你需要将这些地址添加到 Address 字段(用于服务器自己的 IP)和 AllowedIPs 字段(用于客户端 IP)。
8. 我如何启用 WireGuard 在启动时自动运行?
为了确保你的 VPN 在你每次重启 Ubuntu 服务器时都能自动开启,你需要使用 systemd,它是 Linux 的系统管理器。你使用 enable 命令告诉系统查找你的特定配置文件(例如 wg0),并在启动序列期间加载它。这可确保如果你的服务器因更新而重启,你的 VPN 连接将在无需你手动启动的情况下重新上线。
sudo systemctl enable wg-quick@wg0
结论
在这篇教程中,我们一起在 Ubuntu 服务器上搭建了一个 WireGuard VPN,并成功连接了一个支持 IPv4 和 IPv6 的对等端。在这个过程中,我们配置了密钥、分配了隧道地址,并启用了服务器安全地路由流量,最终你拥有了一个易于理解和操作的 VPN。
本指南也涵盖了一些实际使用中重要的细节,比如如何长期管理密钥、处理 IPv6 和双栈网络、以及通过 MTU 调优、心跳包和 DNS 设置来提升可靠性和性能。掌握了这些,我相信你已经做好了在真实世界环境中运行 WireGuard 的准备,并能根据需求灵活调整。
如果你想了解更多关于 WireGuard 的信息,包括如何配置更高级的隧道或将 WireGuard 与容器结合使用,请访问 WireGuard 官方文档。有关保护 Ubuntu 系统的更多教程,请查看以下文章:
- 如何在 Ubuntu 上使用 UFW 设置防火墙
- UFW 基础:Linux 安全的常见防火墙规则和命令
- VPC 与 VPN:哪一个适合你的安全网络需求?
- 如何在 Ubuntu 上设置和配置 OpenVPN 服务器
关于
关注我获取更多资讯