WireGuard 无法创建自己的接口,于是没有设备可配置、没有密钥可交换、也没有握手可调试。失败完全停留在本机,错误文本会说明本地协议栈的哪一层拒绝了请求。正确读懂它,比重新安装对端配置更快。各层是可以分开的,而消息点名了拒绝的那一层。

错误在任何对端开口之前就已发生

创建接口,是向内核发出的一条 netlink 请求,要求一个 wireguard 类型的设备。内核要么有理解该类型的驱动,要么没有,答复会立刻返回。这一步没有任何数据包离开本机,所以端点地址和服务器密钥都不可能是原因。

这个顺序对诊断很重要。如果命令从未创建设备,问题就不可能是公钥写错,也不可能是 UDP 端口被封。先修好本地创建路径,然后再向外看。

究竟该由哪个实现拥有设备

两种实现都可以回应这条请求。内核内的模块注册 wireguard 设备类型,而 wireguard-go 之类的用户态实现以另一种机制提供同样的接口。如果模块缺失,内核会以不支持该设备的错误拒绝请求,解决办法要么是加载模块,要么让工具指向用户态实现。

在两者之间选择之前,先确认实际存在的是什么。第一条命令显示模块是否已加载,第二条则直接向内核发问:

lsmod | grep wireguard
ip link add wgtest0 type wireguard

第二条命令是最小的复现:只要一个设备,别的都不要。如果它以“不支持的类型”失败,缺失的那一环是实现,而不是你的配置文件。

Error textWhat refusedNext step
Unknown device type or operation not supportedThe kernel has no wireguard driverLoad the module or use the userspace implementation
Operation not permittedMissing privilegeUse the service context or grant the capability
File existsThe name is already in useInspect the owner before touching it
No such device in a containerNo tunnel device or capabilityAdd the device and NET_ADMIN to the container

权限与容器边界

创建并配置网络设备需要权限,要么以 root 身份,要么具备网络管理的权能。普通用户会话做不到,这个限制本身就是设计,而不是可以靠运行一个没审过的安装脚本来绕过的障碍。

在容器里边界翻倍。容器需要访问隧道设备,也需要配置它的权能,而授予这些的标志与 Linux 上的 VPN 容器所用的相同。一个平时能正常上网的受限客户机仍然创建不了接口,因为浏览网页并不需要这种权能。把权能给需要它的服务,而不是给主机上的每个会话。

先解决名称冲突,然后重试

已存在的接口并不自动是残留物。另一个管理器可能占着这个名字,而且正在使用它,所以动手删除之前先查看:

ip link show wg0
sudo wg show wg0

如果所有者是正在运行的服务,就配置该服务,而不是再建一个设备。如果它确实已经废弃,就用创建它的工具删除,然后用文档中给出的客户端或 unit 把接口拉起来,让配置与设备保持一致。

一旦创建成功,下一次失败属于更靠后的阶段,设备已经存在之后报告失败的 unit,与从未创建过的设备是两回事。再次改动权限之前,先把两者分开。

相关文章