跳到主要内容

用 wg-quick up wg0 手动拉起 WireGuard 隧道,用来第一次测试没有问题,但不是长期相处的好办法。每次重启接口就消失,网络抖动时没人负责重新启动,半夜三点出故障时也没有日志可查。几乎所有现代 Linux 发行版里,答案早已安装好了,那就是 systemd。本文介绍如何把 WireGuard 作为受管理的服务来运行、如何正确安排开机顺序、如何安全地重载,以及如何借助 journal 排查故障。

阅读本文前,假设你已有一个可用的配置文件,并且对终端比较熟悉。如果你还在选择隧道协议,可以先阅读 WireGuard 与 OpenVPN 对比,通用概念见 什么是 VPN 协议。下面出现的所有密钥和地址都是占位示例。

在 systemd 下运行 WireGuard 的两种方式

受支持的路线有两条,值得有意识地选一条。

方式 工作原理 适合场景
wg-quick 服务 模板单元运行 wg-quick 脚本,由它创建接口、添加地址和路由并调用 DNS 工具 笔记本、快速部署、大多数教程
systemd-networkd 用普通的 .netdev 和 .network 文件描述接口,由网络守护进程创建 服务器、固定环境、把所有网络配置集中在一处

第一种是目前最常见的,所以先讲它,之后再回到第二种。无论选哪一种,都不要用两种方式同时管理同一个接口。如果 wg0 已在 networkd 中定义,又运行了 wg-quick@wg0,两者会为地址设置而互相争抢。

配置 wg-quick 服务

把配置放在 /etc/wireguard/wg0.conf。这个文件包含私钥,所以要设置严格的权限:

sudo chown root:root /etc/wireguard/wg0.conf
sudo chmod 600 /etc/wireguard/wg0.conf

当配置文件对所有人可读时 WireGuard 自己也会发出警告,这是有道理的。然后一步完成启用和启动:

sudo systemctl enable --now wg-quick@wg0

@ 后面的名字是不含 .conf 的配置文件名。这种模板设计使得放在 office.conf 里的第二条隧道就是 wg-quick@office。只要地址和路由不冲突,可以同时运行多条。

用三条命令检查结果。

  1. systemctl status wg-quick@wg0 查看单元是否处于 active 状态。它是一个退出后仍保持状态的 one-shot 单元,所以正常情况下会显示 active (exited),这是正确的,并不是错误。
  2. sudo wg show 列出接口、对端,最关键的是 latest handshake 这一行。最近几分钟内有握手,说明流量正常;如果没有这一行,说明对端从未应答。
  3. ip -brief address show wg0 确认地址已经分配。

停止隧道用 systemctl stop wg-quick@wg0,阻止开机启动用 systemctl disable wg-quick@wg0。停止单元时会执行对应的拆除步骤,包括配置里的 PostDown 命令。

等网络就绪之后再启动

最常见的故障是:隧道手动启动能用,开机却失败。原因是服务启动得比网络可用更早,或者 Endpoint 的主机名还解析不了。解决办法是 drop-in 覆盖文件,它不会编辑软件包自带的单元文件,因此不会在升级时丢失。用下面的命令创建:

sudo systemctl edit wg-quick@wg0

然后粘贴:

[Unit]
Wants=network-online.target
After=network-online.target nss-lookup.target

[Service]
Restart=on-failure
RestartSec=15

保存后运行 sudo systemctl daemon-reload 并重启服务。Wants 和 After 两行会等待网络连通。在桌面系统上,要确认你所用网络守护进程对应的 wait 服务已启用,否则 target 会过早到达。较新的 systemd 版本中,one-shot 单元也支持 Restart=on-failure,第一次失败后会再试一次。如果看到提示说该设置被忽略,说明 systemd 版本较旧,可以改用后文的健康检查定时器。

另一个小技巧:在 Endpoint 里使用字面 IP 地址,可以完全排除域名解析这个出错点。代价是服务器地址一旦改变,你必须自己修改文件。

把其他服务绑定到隧道上

隧道往往不是目的,而是别的东西走的路,例如下载工具、备份任务或容器。systemd 可以表达这种依赖,让依赖服务在没有隧道时不会运行。为该服务建立 drop-in,比如 sudo systemctl edit mybackup.service:

[Unit]
After=wg-quick@wg0.service
BindsTo=wg-quick@wg0.service

After 控制先后顺序。BindsTo 比 Requires 更强:隧道单元一旦停止或失败,systemd 也会停掉依赖它的服务。这相当于一个小型的服务级断线保护,因为隧道断开时该任务无法继续通过普通连接发送流量。更完整的概念见 VPN 断线保护(Kill Switch)是什么。请注意,这只能停掉某一个服务,并不能拦住机器上的所有程序。

阅读 journal 日志

出问题时,journal 是第一站。下面这些命令几乎覆盖所有情况。

  • journalctl -u wg-quick@wg0 -b:显示该单元自上次开机以来记录的全部内容。
  • journalctl -u wg-quick@wg0 -f:在另一个终端重启服务时,实时跟踪新增的行。
  • journalctl -u wg-quick@wg0 --since "10 min ago":缩小时间范围。
  • systemctl status wg-quick@wg0 -l:输出最后几行日志以及退出状态。

常见信息及含义:

信息或症状 可能原因 处理办法
Name or service not known Endpoint 主机名暂时无法解析 排在 network-online 之后,或改用 IP
RTNETLINK answers: File exists 接口或路由已存在 先停掉手动运行的 wg-quick 会话
resolvconf: command not found 写了 DNS = 但没有解析器工具 安装提供 resolvconf 的软件包,或删除该行
单元 active 但没有握手 密钥错误、端口错误或 UDP 被拦截 核对公钥,检查防火墙和端口
Configuration file ... is world accessible 权限过于宽松 对文件执行 chmod 600

不拆隧道的重载

重启单元会中断所有使用该隧道的连接。对于常见的修改,例如添加对端或调整允许的网段,WireGuard 可以实时应用差异。常用的写法是:

sudo wg syncconf wg0 <(sudo wg-quick strip wg0)

wg-quick strip 会去掉 Address、DNS、PostUp 这类 wg-quick 专有的行,只剩下 wg syncconf 能理解的纯 WireGuard 设置。已有的会话继续,只改变有差异的部分。凡是 wg-quick 自己处理的内容,也就是地址、路由、DNS 和钩子,仍然需要 systemctl restart。如果希望 systemctl reload 帮你完成这件事,可以添加带有 ExecReload= 的 drop-in,通过 /bin/bash -c 执行上面的命令。

一个简单的健康检查定时器

隧道可能在没有任何服务失败的情况下悄悄失去联系,比如笔记本在另一个网络里唤醒之后。一个简单的定时器就能发现并重启隧道。创建 /etc/systemd/system/wg-check.service:

[Unit]
Description=Check WireGuard tunnel

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'ping -c 2 -W 3 10.8.0.1 || systemctl restart wg-quick@wg0'

再创建 /etc/systemd/system/wg-check.timer:

[Unit]
Description=Run the WireGuard check every minute

[Timer]
OnBootSec=2min
OnUnitActiveSec=1min

[Install]
WantedBy=timers.target

把 10.8.0.1 换成只能通过隧道应答的地址,比如对端的内部地址。用 sudo systemctl enable --now wg-check.timer 启用。重启隧道会打断已打开的连接,所以间隔要留得宽松,检查方式也要可靠。如果服务器屏蔽了 ICMP,ping 可能失败,此时应换用别的探测方式。

原生方案:systemd-networkd

如果服务器已经在使用 systemd-networkd,可以把 WireGuard 与其他配置写在同一类文件里,不再使用 wg-quick。创建 /etc/systemd/network/50-wg0.netdev:

[NetDev]
Name=wg0
Kind=wireguard

[WireGuard]
PrivateKeyFile=/etc/systemd/network/wg0.key
ListenPort=51820

[WireGuardPeer]
PublicKey=PEER_PUBLIC_KEY
Endpoint=203.0.113.10:51820
AllowedIPs=10.8.0.0/24
PersistentKeepalive=25

以及 /etc/systemd/network/50-wg0.network:

[Match]
Name=wg0

[Network]
Address=10.8.0.2/24

密钥文件只能让 root 和 systemd-network 组读取,例如权限 0640,属主 root:systemd-network。用 sudo networkctl reload 应用,并用 networkctl status wg0 和 wg show 检查。networkd 方案不会像 PostUp 那样运行 shell 钩子,所以防火墙规则之类的附加内容要放进单独的单元。如果要做全隧道配置,请先查阅 systemd.netdev 和 systemd.network 手册中有关防火墙标记和路由表的选项,再决定是否采用。

常见错误

  • 同时手动运行 wg-quick up 和 systemd 单元。
  • 让配置文件对所有人可读。
  • 把 active (exited) 当成故障。对这个单元来说,这是正常的健康状态。
  • 直接编辑软件包自带的单元文件,而不是使用 systemctl edit。
  • 修改单元后忘记 daemon-reload。
  • 使用主机名形式的 endpoint,却没有等待网络的顺序设置。
  • 使用与家庭网络重叠的私有网段,请按 RFC 1918 另选一个地址块。

总结

把 WireGuard 作为 systemd 服务运行,你就得到了开机启动、排在网络之后的顺序、journal 里的日志,以及对依赖它的服务清晰的依赖关系。用 wg-quick@名称 求简单,用 drop-in 管顺序和重启,用 wg syncconf 做实时修改,用 journalctl 弄懂故障。对于已经运行在 systemd-networkd 里的服务器,原生文件可以把一切集中在一起。

如果你更想在 Linux 上使用现成的应用,Linux 设置指南 介绍了免费 VPNclient 的安装,价格页面 列出了可用的选项。

常见问题

systemctl 命令里的 wg-quick@wg0 是什么意思?

wg-quick@.service 是模板单元,@ 后面的文字是配置文件名。wg-quick@wg0 会读取 /etc/wireguard/wg0.conf 并创建接口 wg0;名为 office.conf 的文件则用 wg-quick@office 控制。

怎样让 WireGuard 开机自动启动?

运行 sudo systemctl enable --now wg-quick@wg0。enable 负责建立开机启动链接,now 表示立刻启动。可以用 systemctl is-enabled wg-quick@wg0 和 wg show 检查。

修改配置时能不能不中断隧道?

大多数对端和密钥的修改可以。对 wg-quick strip wg0 的输出使用 wg syncconf wg0,只应用差异而不拆除接口。但地址、路由和 DNS 的修改仍需完整重启。

为什么开机时服务失败,稍后手动启动却正常?

通常是服务启动时网络还没就绪,或者无法解析 Endpoint 里的主机名。可以用 drop-in 覆盖让它排在 network-online.target 之后,或者直接把 endpoint 写成 IP 地址。

应该用 wg-quick 还是 systemd-networkd?

wg-quick 更简单,多数教程都以它为准。systemd-networkd 把所有内容放在与其他网络配置相同的文件里,适合服务器和固定环境。两者都可以,但不要对同一个接口同时使用。

关于作者

Bob Kanokphon Thongdee,XPASS VPN 创始人

Bob Kanokphon Thongdee

  • XPASS VPN 创始人
  • eSIMonline.asia 联合创始人
  • 7 年以上网络营销经验
  • Cojourney Visa 与 Cojourney Travel 创始人

短途出行或忙碌的一个月,需要 VPN?

XPASS 提供按天数计算的预付通行证。一次付款,不会自动续费。

查看通行证

继续阅读

VPN 安全

WireGuard 与 OpenVPN 有什么区别

WireGuard 和 OpenVPN 都能建立加密隧道,但设计、复杂度和灵活性不同。本文用通俗的方式比较,并说明该怎样选择。

阅读约 9 分钟

VPN 基础

什么是 VPN 协议?

VPN 协议规定了你的设备与 VPN 服务器如何连接并保护流量。本文用通俗的语言讲清楚它的含义和主要取舍。

阅读约 9 分钟

故障排除

WireGuard 速度测试:应该测哪些指标

吞吐量只是测试 WireGuard 隧道时六项指标之一。本文提供可重复的方法、计算示例,以及会让结果失真的陷阱。

阅读约 10 分钟

VPN 安全

什么是 VPN 断网保护(Kill Switch)?

Kill Switch 能防止 VPN 断开时设备悄悄改用不受保护的连接。本文介绍它的原理,以及如何检查它是否有效。

阅读约 12 分钟

故障排除

VPN 连接不上?逐步排查方法

VPN 连接不上时的清晰排查顺序:通行证状态、登录信息、Wi-Fi 与移动数据、权限、防火墙、应用冲突和错误提示。

阅读约 8 分钟