跨平台用户空间实现

虽然 WireGuard 最初是为 Linux 内核开发的,但为了获得最佳性能,它可以使用单独的实现在用户空间中运行。目前wireguard-go功能齐全,并且wireguard-rs正在开发中。在文档中ip link add wg0 type wireguard,您可以随时写成wireguard-go wg0。其他一切都应该相同。

为了防止碎片化,所有用户空间实现都应遵循相同的协议和规范,从而具有与原始 Linux 内核完全相同的行为。此外,它还应遵守以下配置接口。

界面

用户空间实现应该具有以下极其有限的命令行界面:

# userspace-wg [-f/--foreground] INTERFACE-NAME

例如,可以按如下方式调用 Go 实现来创建wg0接口:

# wireguard-go wg0

运行上述命令将创建一个名为 的虚拟 TUN 设备wg0,然后将其守护。成功守护并启动接口后,它会创建/var/run/wireguard/wg0.sock(或/run/wireguard/wg0.sock取决于平台)作为以流模式运行的 UNIX 域套接字。在 Windows 上,在 中使用双向命名管道时使用相同的语义\\.\pipe\WireGuard\wg0

wg(8)工具用于配置接口,以便实现中的配置接口完全一致。该工具将在(或)wg(8)中查找接口。用户空间实现应该在响应 SIGINT/SIGTERM、tun 接口的移除或 UNIX 域套接字文件的删除时正常终止。该工具连接到这些套接字并发送和接收以下基于文本的协议。/var/run/wireguard/*.sock/run/wireguard/*.sockwg(8)

配置协议

WireGuard 实现必须响应两个命令:getset,均为1撰写本文时的版本。wg(8)发送get如下命令:

get=1
{empty line}

wg(8)发送set如下命令:

set=1
key1=value1
key2=value2
key3=value3
key4=value4
key5=value5
...
{empty line}

用户空间实现用以下方式响应get命令:

key1=value1
key2=value2
key3=value3
key4=value4
key5=value5
...
errno=0
{empty line}

用户空间实现用以下方式响应set命令:

errno=0
{empty line}

如果发生错误,errno则是来自的相应整数errno.h

get请注意和命令末尾set以及每个相应响应末尾的空行wg(8)

键和值如下:

All interface-level keys must proceed all per-level keys.

Example Dialog

wg(8) sends:

get=1
{empty line}

Userspace WireGuard implementation responds:

private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a
listen_port=12912
public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33
preshared_key=188515093e952f5f22e865cef3012e72f8b5f0b598ac0309d5dacce3b70fcf52
allowed_ip=192.168.4.4/32
endpoint=[abcd:23::33%2]:51820
public_key=58402e695ba1772b1cc9309755f043251ea77fdcf10fbe63989ceb7e19321376
tx_bytes=38333
rx_bytes=2224
allowed_ip=192.168.4.6/32
persistent_keepalive_interval=111
endpoint=182.122.22.19:3233
public_key=662e14fd594556f522604703340351258903b64f35553763f19426ab2a515c58
endpoint=5.152.198.39:51820
allowed_ip=192.168.4.10/32
allowed_ip=192.168.4.11/32
tx_bytes=1212111
rx_bytes=1929999999
protocol_version=1
errno=0
{empty line}

wg(8) sends:

set=1
private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a
fwmark=0
listen_port=12912
replace_peers=true
public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33
preshared_key=188515093e952f5f22e865cef3012e72f8b5f0b598ac0309d5dacce3b70fcf52
replace_allowed_ips=true
allowed_ip=192.168.4.4/32
endpoint=[abcd:23::33%2]:51820
public_key=58402e695ba1772b1cc9309755f043251ea77fdcf10fbe63989ceb7e19321376
replace_allowed_ips=true
allowed_ip=192.168.4.6/32
persistent_keepalive_interval=111
endpoint=182.122.22.19:3233
public_key=662e14fd594556f522604703340351258903b64f35553763f19426ab2a515c58
endpoint=5.152.198.39:51820
replace_allowed_ips=true
allowed_ip=192.168.4.10/32
allowed_ip=192.168.4.11/32
public_key=e818b58db5274087fcc1be5dc728cf53d3b5726b4cef6b9bab8f8f8c2452c25c
remove=true
{empty line}

Userspace WireGuard implementation responds:

errno=0
{empty line}