跳转至内容

WireGuard

来自 ArchWiki
(重定向自 Wireguard)

来自 WireGuard 项目主页

WireGuard 是一个极其简单但快速且现代化的 VPN,它利用了最先进的加密技术。它的目标是比 IPsec 更快、更简单、更精简、更有用,同时避免了巨大的麻烦。它旨在比 OpenVPN 性能更优。WireGuard 被设计为一个通用的 VPN,可以运行在嵌入式接口和超级计算机上,适用于许多不同的环境。最初为 Linux 内核发布,现在已跨平台(Windows、macOS、BSD、iOS、Android)并广泛部署。

本文档中使用的主要概念的粗略介绍可以在 WireGuard 项目主页上找到。WireGuard 自 2019 年末以来已被包含在 Linux 内核中。

安装

安装 wireguard-tools 包以获取用户空间工具。

或者,各种网络管理器提供了对 WireGuard 的支持,前提是提供了对等密钥。有关详细信息,请参阅 #持久化配置

图形客户端

  • wireguird — 一个用于 WireGuard 的 Linux GTK GUI 客户端。
https://github.com/UnnoTed/wireguird || wireguirdAUR
  • wireguard-gui — 使用 nextauri 构建的 Linux Wireguard 客户端 GUI。
https://github.com/0xle0ne/wireguard-gui || wireguard-gui-binAUR

命令行工具

  • wg_tool — 用于管理服务器和用户的 WireGuard 配置的工具。
https://github.com/gene-git/wg_tool || wg_toolAUR
  • wg-client — 具有命令行和 GUI 的 Linux 客户端。
https://github.com/gene-git/wg-client || wg-clientAUR
https://git.flu0r1ne.net/wg2nd/about || wg2ndAUR

用法

本文或本节需要在语言、wiki 语法或风格方面进行改进。请参阅 Help:Style 获取参考。

原因:无效的章节名称——此页面上的所有内容都与 WireGuard 的使用有关。将 4 个子章节移到顶层会更有意义。(在 Talk:WireGuard 中讨论)

以下命令演示了如何在两个或多个对等点之间设置具有以下设置的基本隧道

外部(公共)地址 内部 IP 地址 端口
域名 IPv4 地址 IPv6 地址 IPv4 地址 IPv6 地址
对等点 A 198.51.100.101 2001:db8:a85b:70a:ffd4:ec1b:4650:a001 10.0.0.1/24 fdc9:281f:04d7:9ee9::1/64 UDP/51871
对等点 B peer-b.example 203.0.113.102 2001:db8:40f0:147a:80ad:3e88:b002 10.0.0.2/24 fdc9:281f:04d7:9ee9::2/64 UDP/51902
对等点 C dynamic dynamic 10.0.0.3/24 fdc9:281f:04d7:9ee9::3/64 UDP/51993
提示 所有对等点可以使用相同的 UDP 端口。

外部地址应已存在。例如,如果 ICMP 回显请求未被阻止,对等点 A 应该可以通过其公共 IP 地址(或多个地址)ping 对等点 B,反之亦然。

内部地址将是新创建的地址,可以通过使用 ip(8) 工具手动创建,或通过网络管理软件创建,这些地址将在新的 WireGuard 网络内部使用。以下示例将使用 10.0.0.0/24fdc9:281f:04d7:9ee9::/64 作为内部网络。IP 地址中的 /24/64CIDR

密钥生成

为每个对等点生成一个私钥和一个公钥。如果连接数十个对等点,可选地考虑使用自定义密钥对以个性化 Base64 编码的公钥字符串。请参阅 #自定义密钥

要生成私钥,请运行

$ (umask 0077; wg genkey > peer_A.key)
注意 建议仅为所有者允许读写访问。上面的命令会在子 shell 中临时更改 umask,以确保访问(读/写权限)仅限于所有者。

要生成公钥

$ wg pubkey < peer_A.key > peer_A.pub

或者,一次性完成所有操作

$ wg genkey | (umask 0077 && tee peer_A.key) | wg pubkey > peer_A.pub

还可以生成一个预共享密钥,为已有的公钥加密添加一个额外的对称密钥加密层,以实现后量子安全。应为每个对等点对生成一个预共享密钥,并且不应重复使用。例如,三个互连的对等点 A、B 和 C 将需要三个独立的预共享密钥,每个对等点对一个。

使用以下命令为每个对等点对生成预共享密钥(确保也使用 umask 0077

$ wg genpsk > peer_A-peer_B.psk
$ wg genpsk > peer_A-peer_C.psk
$ wg genpsk > peer_B-peer_C.psk

自定义密钥

目前,wg show 不支持为密钥附加人类可读的名称。这使得将密钥与更易于识别的实体关联变得困难,尤其是在使用多个密钥时。除了安装一个完全支持这种关联的 工具外,一种可能的解决方案是生成一个包含一些熟悉字符的公钥(可能是所有者姓名或主机名的前几个字母等)。wireguard-vanity-address,或者 wicuvanityAUR 可以做到这一点。

例如:

$ wireguard-vanity-address --in 8 leslie
searching for 'leslie' in pubkey[0..10], one of every 214748364 keys should match
one core runs at 2.69e6 keys/s, CPU cores available: 16
est yield: 5.0 seconds per key, 200.10e-3 keys/s
hit Ctrl-C to stop
private wEoVMj92P+E3fQXVf9IixWJqpCqcnP/4OfvrB1g3zmY=  public LEsliEny+aMcWcRbh8Qf414XsQHSBOAFk3TaEk/aSD0=
private EAOwlGGqpHVbZ9ehaCspdBJt+lkMcCfkwiA5T5a4JFs=  public VlesLiEB5BFd//OD2ILKXviolfz+hodG6uZ+XjoalC8=
private UDWG4VWI+RzAGzNSnlC+0X4d3nk9goWPs/NRC5tX524=  public 9lESlieIFOlJFV6dG7Omao2WS+amWgshDdBYn8ahRjo=

手动配置

对等点设置

手动设置通过使用 ip(8)wg(8) 来完成。

注意 这些示例使用了在 #密钥生成 中作为 *可选* 功能引入的预共享密钥。如果不使用它们,只需忽略命令中的相应部分。

对等点 A 设置

在此示例中,对等点 A 将监听 UDP 端口 51871 并接受来自对等点 B 和 C 的连接。

# ip link add dev wg0 type wireguard
# ip addr add 10.0.0.1/24 dev wg0
# ip addr add fdc9:281f:04d7:9ee9::1/64 dev wg0
# wg set wg0 listen-port 51871 private-key /path/to/peer_A.key
# wg set wg0 peer PEER_B_PUBLIC_KEY preshared-key /path/to/peer_A-peer_B.psk endpoint peer-b.example:51902 allowed-ips 10.0.0.2/32,fdc9:281f:04d7:9ee9::2/128
# wg set wg0 peer PEER_C_PUBLIC_KEY preshared-key /path/to/peer_A-peer_C.psk allowed-ips 10.0.0.3/32,fdc9:281f:04d7:9ee9::3/128
# ip link set wg0 up

PEER_X_PUBLIC_KEY 应为 peer_X.pub 的内容。

allowed-ips 关键字是将被路由到对等点的地址列表。确保至少指定一个包含 WireGuard 连接内部 IP 地址(或多个地址)的地址范围。

对等点 B 设置

# ip link add dev wg0 type wireguard
# ip addr add 10.0.0.2/24 dev wg0
# ip addr add fdc9:281f:04d7:9ee9::2/64 dev wg0
# wg set wg0 listen-port 51902 private-key /path/to/peer_B.key
# wg set wg0 peer PEER_A_PUBLIC_KEY preshared-key /path/to/peer_A-peer_B.psk endpoint 198.51.100.101:51871 allowed-ips 10.0.0.1/32,fdc9:281f:04d7:9ee9::1/128
# wg set wg0 peer PEER_C_PUBLIC_KEY preshared-key /path/to/peer_B-peer_C.psk allowed-ips 10.0.0.3/32,fdc9:281f:04d7:9ee9::3/128
# ip link set wg0 up

对等点 C 设置

# ip link add dev wg0 type wireguard
# ip addr add 10.0.0.3/24 dev wg0
# ip addr add fdc9:281f:04d7:9ee9::3/64 dev wg0
# wg set wg0 listen-port 51993 private-key /path/to/peer_C.key
# wg set wg0 peer PEER_A_PUBLIC_KEY preshared-key /path/to/peer_A-peer_C.psk endpoint 198.51.100.101:51871 allowed-ips 10.0.0.1/32,fdc9:281f:04d7:9ee9::1/128
# wg set wg0 peer PEER_B_PUBLIC_KEY preshared-key /path/to/peer_B-peer_C.psk endpoint peer-b.example:51902 allowed-ips 10.0.0.2/32,fdc9:281f:04d7:9ee9::2/128
# ip link set wg0 up

附加路由

要建立比点对点更复杂的连接,需要进行额外的设置。

本文章或章节需要扩充。

原因:添加一个场景:只有对等点 A 拥有公共 IP 地址(即 *endpoint*),对等点 B 和 C(通常在 NAT 后面)通过 `PersistentKeepalive` 连接到对等点 A,对等点 B 到对等点 C 以及反之亦然的连接通过对等点 A 路由。(在 Talk:WireGuard 中讨论)
点对点连接

要访问对等点的网络,请在应能连接到它的对等点的配置中的 allowed-ips 中指定网络子网。例如 allowed-ips 10.0.0.2/32,fdc9:281f:04d7:9ee9::2/128,192.168.35.0/24,fd7b:d0bd:7a6e::/64

请务必使用 ip-route(8) 设置 路由表。例如:

# ip route add 192.168.35.0/24 dev wg0
# ip route add fd7b:d0bd:7a6e::/64 dev wg0
站点对点连接

本文章或章节需要扩充。

原因:添加 `ip route` 示例;添加使用 NAT 的替代方案;提及“站点”对等点是网络网关的情况。(在 Talk:WireGuard 中讨论)

如果目的是将设备连接到具有 WireGuard 对等点的网络,请在每个设备上设置路由,以便它们知道对等点可以通过该设备访问。

提示 通过在路由器中配置路由,可以跨网络部署路由。例如,使用 DHCP 选项 121。

之后,在其他设备将连接到 WireGuard 对等点的对等点上 启用 IP 转发

站点对站点连接

要连接两个(或更多)网络,请在所有 *站点* 上同时应用 #点对点连接#站点对点连接

通过 WireGuard 路由所有流量

要将所有流量通过 WireGuard 隧道路由,请使用

# ip route add default dev wg0 table 2468
# wg set wg0 fwmark 1234
# ip rule add not fwmark 1234 table 2468 pref 10

在第一行,默认路由被添加到备用路由表(表 2468)。此备用路由表的唯一目的是将数据包传递给 wg0 接口。

在第二行,由 wg0 接口处理的所有传出数据包都用防火墙标记标记。

第三行,缺乏此防火墙标记的数据包被定向到备用路由表 2468,该表将其路由到 wg0 接口。pref 10 表示此规则的优先级为 10。要列出所有规则及其相应的优先级,请使用 ip rule show。这些规则决定了将为特定数据包使用哪个路由表。

此实现的优点在于避免使用任何端点。这很方便,因为 WireGuard 端点可以漫游。可以定义没有端点的 WireGuard 对等点。

在此实现中,本地访问网络将无法访问。要白名单 LAN 使用

# ip rule add suppress_prefixlength 0 table main pref 5

使用 ip-rule(8) 添加白名单条目非常简单。例如,要允许特定用户发送隧道外的查询,请使用

# ip rule add uidrange 955-955 table main pref 5

955 是用户的用户 ID。所有用户的用户 ID 可以在 /etc/passwd 中找到。

DNS

要将对等点用作 DNS 服务器,请将其 WireGuard 隧道 IP 地址(或多个地址)添加到 /etc/resolv.conf。例如,使用对等点 B 作为 DNS 服务器

/etc/resolv.conf
nameserver fdc9:281f:04d7:9ee9::2
nameserver 10.0.0.2
注意 如果对等点将充当 DNS 服务器,请确保使用其 WireGuard 隧道地址(或多个地址)作为 DNS 服务器地址,而不是其在 Allowed IPs 中的其他地址。否则 DNS 查询可能会失败。

基本检查

调用不带参数的 wg(8) 命令将快速概览当前配置。

例如,在配置了对等点 A 后,我们可以看到它的身份及其关联的对等点

# wg
interface: wg0
  public key: UguPyBThx/+xMXeTbRYkKlP0Wh/QZT3vTLPOVaaXTD8=
  private key: (hidden)
  listening port: 51871

peer: 9jalV3EEBnVXahro0pRMQ+cHlmjE33Slo9tddzCVtCw=
  endpoint: 203.0.113.102:51902
  allowed ips: 10.0.0.2/32, fdc9:281f:04d7:9ee9::2

peer: 2RzKFbGMx5g7fG0BrWCI7JIpGvcwGkqUaCoENYueJw4=
  endpoint: 192.0.2.103:51993
  allowed ips: 10.0.0.3/32, fdc9:281f:04d7:9ee9::3

此时,您应该可以到达隧道的终点。如果对等点不阻止 ICMP 回显请求,请尝试 ping 对等点以测试它们之间的连接。

使用 ICMPv4

$ ping 10.0.0.2

使用 ICMPv6

$ ping fdc9:281f:04d7:9ee9::2

在对等点之间传输一些数据后,wg 工具将显示额外信息

# wg
interface: wg0
  public key: UguPyBThx/+xMXeTbRYkKlP0Wh/QZT3vTLPOVaaXTD8=
  private key: (hidden)
  listening port: 51871

peer: 9jalV3EEBnVXahro0pRMQ+cHlmjE33Slo9tddzCVtCw=
  endpoint: 203.0.113.102:51902
  allowed ips: 10.0.0.2/32, fdc9:281f:04d7:9ee9::2
  latest handshake: 5 seconds ago
  transfer: 1.24 KiB received, 1.38 KiB sent

peer: 2RzKFbGMx5g7fG0BrWCI7JIpGvcwGkqUaCoENYueJw4=
  allowed ips: 10.0.0.3/32, fdc9:281f:04d7:9ee9::3

持久化配置

可以通过使用 wg-quick@.service 实现持久化配置,该服务随 wireguard-tools 一起提供,或者使用网络管理器。支持 WireGuard 的网络管理器包括 systemd-networkdnetctl[1]NetworkManagerConnMan[2]

  • netctl 依赖于 wireguard-tools 中的 wg(8)/etc/wireguard/interfacename.conf 配置文件来建立 WireGuard 连接。
  • ConnMan 对 WireGuard 的支持非常有限。它只能连接到一个对等点。[3]

wg-quick

wg-quick(8) 使用 /etc/wireguard/interfacename.conf 中的配置文件来配置 WireGuard 隧道。

当前 WireGuard 配置可以通过使用 wg(8) 工具的 showconf 命令来保存。例如:

# wg showconf wg0 > /etc/wireguard/wg0.conf

要使用配置文件启动隧道,请使用:

# wg-quick up interfacename

或者使用 systemd 服务 — wg-quick@interfacename.service。要使隧道在启动时启动,请 启用 该单元。

  • 使用 *wg-quick* 配置 WireGuard 接口的用户,应确保没有其他 网络管理软件尝试管理它。要使用 NetworkManager 且不通过它配置 WireGuard 接口,请参阅 #路由被周期性重置
  • wg-quick 在配置文件格式中添加了额外的配置选项,因此它与 wg(8) § 配置文件格式 不兼容。请参阅 wg-quick(8) § 配置 手册页以了解相关配置值。可以通过使用 wg-quick strip 来生成一个 *wg* 兼容的配置文件。
  • wg-quick 不提供指示 resolvconf 将 WireGuard 接口设置为 *私有* 的方法。即使指定了搜索域,所有来自系统的 DNS 查询,而不仅仅是匹配搜索域的查询,都将被发送到 WireGuard 配置中设置的 DNS 服务器。

对等点 A 设置

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24, fdc9:281f:04d7:9ee9::1/64
ListenPort = 51871
PrivateKey = PEER_A_PRIVATE_KEY

[Peer]
PublicKey = PEER_B_PUBLIC_KEY
PresharedKey = PEER_A-PEER_B-PRESHARED_KEY
AllowedIPs = 10.0.0.2/32, fdc9:281f:04d7:9ee9::2/128
Endpoint = peer-b.example:51902

[Peer]
PublicKey = PEER_C_PUBLIC_KEY
PresharedKey = PEER_A-PEER_C-PRESHARED_KEY
AllowedIPs = 10.0.0.3/32, fdc9:281f:04d7:9ee9::3/128
  • 要将 *所有流量* 通过隧道路由到特定对等点,请将 默认路由(IPv4 为 0.0.0.0/0,IPv6 为 ::/0)添加到 AllowedIPs。例如 AllowedIPs = 0.0.0.0/0, ::/0。wg-quick 将自动处理正确的路由和 fwmark[4] 的设置,以确保网络仍然正常工作。
  • 要使用对等点作为 DNS 服务器,请在 [Interface] 部分设置 DNS = wireguard_internal_ip_address_of_peer搜索域也使用 DNS = 选项设置。用逗号分隔列表中的所有值。

对等点 B 设置

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.2/24, fdc9:281f:04d7:9ee9::2/64
ListenPort = 51902
PrivateKey = PEER_B_PRIVATE_KEY

[Peer]
PublicKey = PEER_A_PUBLIC_KEY
PresharedKey = PEER_A-PEER_B-PRESHARED_KEY
AllowedIPs = 10.0.0.1/32, fdc9:281f:04d7:9ee9::1/128
Endpoint = 198.51.100.101:51871

[Peer]
PublicKey = PEER_C_PUBLIC_KEY
PresharedKey = PEER_B-PEER_C-PRESHARED_KEY
AllowedIPs = 10.0.0.3/32, fdc9:281f:04d7:9ee9::3/128

对等点 C 设置

/etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.3/24, fdc9:281f:04d7:9ee9::3/64
ListenPort = 51993
PrivateKey = PEER_C_PRIVATE_KEY

[Peer]
PublicKey = PEER_A_PUBLIC_KEY
PresharedKey = PEER_A-PEER_C-PRESHARED_KEY
AllowedIPs = 10.0.0.1/32, fdc9:281f:04d7:9ee9::1/128
Endpoint = 198.51.100.101:51871

[Peer]
PublicKey = PEER_B_PUBLIC_KEY
PresharedKey = PEER_B-PEER_C-PRESHARED_KEY
AllowedIPs = 10.0.0.2/32, fdc9:281f:04d7:9ee9::2/128
Endpoint = peer-b.example:51902

systemd-networkd

systemd-networkd 原生地支持设置 WireGuard 接口。在 systemd.netdev(5) § 示例 手册页中提供了示例。

注意 通过 WireGuard 路由所有 DNS(即 Domains=~.)将阻止端点的 DNS 解析。除非对等点域被配置为在特定网络链接上解析。

对等点 A 设置

/etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel wg0

[WireGuard]
ListenPort=51871
PrivateKey=PEER_A_PRIVATE_KEY
RouteTable=main

[WireGuardPeer]
PublicKey=PEER_B_PUBLIC_KEY
PresharedKey=PEER_A-PEER_B-PRESHARED_KEY
AllowedIPs=10.0.0.2/32,fdc9:281f:04d7:9ee9::2/128
Endpoint=peer-b.example:51902

[WireGuardPeer]
PublicKey=PEER_C_PUBLIC_KEY
PresharedKey=PEER_A-PEER_C-PRESHARED_KEY
AllowedIPs=10.0.0.3/32,fdc9:281f:04d7:9ee9::3/128
/etc/systemd/network/99-wg0.network
[Match]
Name=wg0

[Network]
Address=10.0.0.1/24
Address=fdc9:281f:04d7:9ee9::1/64
  • 要使用对等点作为 DNS 服务器,请在 *.network* 文件中使用 DNS= 选项指定其 WireGuard 隧道的 IP 地址(或多个地址)。对于 搜索域,请使用 Domains= 选项。有关详细信息,请参阅 systemd.network(5) § [NETWORK] 段选项
  • 要将对等点用作 *唯一* DNS 服务器,请在 *.network* 文件的 [Network] 部分设置 DNSDefaultRoute=trueDomains=~.
  • 要自动为 AllowedIPs 中的所有内容创建路由,请将 RouteTable=main 添加到 *.netdev* 文件中的 [WireGuard][WireGuardPeer] 部分。或者,可以使用 *.network* 文件中的 [Route] 部分手动指定其他路由。
警告 为了防止私钥和预共享密钥泄露,建议设置 *.netdev* 文件的权限
# chown root:systemd-network /etc/systemd/network/99-wg*.netdev
# chmod 0640 /etc/systemd/network/99-wg*.netdev

或者,可以将密钥存储在单独的文件中,并使用 PrivateKeyFile=PresharedKeyFile=PublicKeyFile= 进行引用,或者使用 systemd-creds 将它们加密存储。请参阅 #使用 systemd 凭据存储私钥 (systemd-networkd)

提示 要在 nftables 规则中通过 systemd-networkd 的 NFTSet 选项 使用 WireGuard 接口名称或 IP 地址,请在 [Address] 部分而不是 [Network] 部分指定地址。例如:
/etc/systemd/network/99-wg0.network
...
[Address]
Address=10.0.0.1/24
NFTSet=address:inet:my_table:wg_ipv4_address
NFTSet=prefix:inet:my_table:wg_ipv4_prefix
NFTSet=ifindex:inet:my_table:wg_ifindex

[Address]
Address=fdc9:281f:04d7:9ee9::1/64
NFTSet=address:inet:my_table:wg_ipv6_address
NFTSet=prefix:inet:my_table:wg_ipv6_prefix
NFTSet=ifindex:inet:my_table:wg_ifindex

对等点 B 设置

/etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel wg0

[WireGuard]
ListenPort=51902
PrivateKey=PEER_B_PRIVATE_KEY
RouteTable=main

[WireGuardPeer]
PublicKey=PEER_A_PUBLIC_KEY
PresharedKey=PEER_A-PEER_B-PRESHARED_KEY
AllowedIPs=10.0.0.1/32,fdc9:281f:04d7:9ee9::1/128
Endpoint=198.51.100.101:51871

[WireGuardPeer]
PublicKey=PEER_C_PUBLIC_KEY
PresharedKey=PEER_B-PEER_C-PRESHARED_KEY
AllowedIPs=10.0.0.3/32,fdc9:281f:04d7:9ee9::3/128
/etc/systemd/network/99-wg0.network
[Match]
Name=wg0

[Network]
Address=10.0.0.2/24
Address=fdc9:281f:04d7:9ee9::2/64

对等点 C 设置

/etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel wg0

[WireGuard]
ListenPort=51993
PrivateKey=PEER_C_PRIVATE_KEY
RouteTable=main

[WireGuardPeer]
PublicKey=PEER_A_PUBLIC_KEY
PresharedKey=PEER_A-PEER_C-PRESHARED_KEY
AllowedIPs=10.0.0.1/32,fdc9:281f:04d7:9ee9::1/128
Endpoint=198.51.100.101:51871

[WireGuardPeer]
PublicKey=PEER_B_PUBLIC_KEY
PresharedKey=PEER_B-PEER_C-PRESHARED_KEY
AllowedIPs=10.0.0.2/32,fdc9:281f:04d7:9ee9::2/128
Endpoint=peer-b.example:51902
/etc/systemd/network/99-wg0.network
[Match]
Name=wg0

[Network]
Address=10.0.0.3/24
Address=fdc9:281f:04d7:9ee9::3/64

systemd-networkd: 通过 WireGuard 路由所有流量

在此示例中,对等点 B 通过公共 IP 地址连接到对等点 A。对等点 B 通过 WireGuard 隧道路由其所有流量,并使用对等点 A 处理 DNS 请求。

对等点 A 设置

/etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel wg0

[WireGuard]
ListenPort=51871
PrivateKey=PEER_A_PRIVATE_KEY
RouteTable=main

[WireGuardPeer]
PublicKey=PEER_B_PUBLIC_KEY
PresharedKey=PEER_A-PEER_B-PRESHARED_KEY
AllowedIPs=10.0.0.2/32
AllowedIPs=fd31::2/128
/etc/systemd/network/99-wg0.network
[Match]
Name=wg0

[Network]
Address=10.0.0.1/32
Address=fd31::1/128
IPMasquerade=both
注意 IPMasquerade=both 选项会为 IPv4 和 v6 启用 WireGuard 接口上的 IP 转发,为其设置 IP 伪装的防火墙规则,以便对等点 A 可以为对等点 B 提供有效的互联网连接。此外:
  • 为用于连接到互联网的接口 启用 IP 转发(即,在其 *.network* 文件中添加 IPv4Forwarding=yes)。
  • 确保 防火墙不会阻止转发
  • 配置本地 DNS 服务器以接受对 WireGuard 接口 IP 地址的连接。对于 systemd-resolved,请参阅 systemd-resolved#附加监听接口
  • 要自动为 AllowedIPs 中的所有内容创建路由,请将 RouteTable=main 添加到 *.netdev* 文件中的 [WireGuard][WireGuardPeer] 部分。

对等点 B 设置

/etc/systemd/network/99-wg0.netdev
[NetDev]
Name=wg0
Kind=wireguard
Description=WireGuard tunnel wg0

[WireGuard]
ListenPort=51902
PrivateKey=PEER_B_PRIVATE_KEY
FirewallMark=0x8888

[WireGuardPeer]
PublicKey=PEER_A_PUBLIC_KEY
PresharedKey=PEER_A-PEER_B-PRESHARED_KEY
AllowedIPs=0.0.0.0/0
AllowedIPs=::/0
# Endpoint=[2a01::1]:51871
Endpoint=198.51.100.101:51871
RouteTable=1000


在 netdev 配置中,最值得关注的行是 RouteTable=1000FirewallMark=0x8888。RouteTable 行指定为 wireguard 接口创建一个 id 为 1000 的新路由表,并且主路由表上没有设置任何规则。

FirewallMark 只是用数字 0x8888 标记此 wireguard 接口发送和接收的所有数据包,该数字可用于在这些数据包上定义策略规则。

/etc/systemd/network/50-wg0.network
[Match]
Name=wg0

[Network]
Address=10.0.0.2/32
Address=fd31::2/128
DNS=10.0.0.1
DNS=fd31::1
DNSDefaultRoute=true
Domains=~.

[RoutingPolicyRule]
Family=both
FirewallMark=0x8888
InvertRule=true
Table=1000
Priority=10

# Exempt the endpoint IP address so that wireguard can still connect to it.
[RoutingPolicyRule]
#To = "2a01::1/128";
To=198.51.100.101/32
Priority=5

我们在这里定义两个路由策略。对于所有未标记为 0x8888 的数据包(即所有非 wireguard/普通流量),我们指定必须使用路由表 1000(即 wireguard 路由表)。此规则将所有流量路由通过 wireguard。

我们通过使用主表(默认为 Table=main)路由我们的端点来豁免它,该表具有更高的优先级。

豁免特定地址

为了豁免特定地址(例如私有 LAN 地址)不通过 WireGuard 隧道路由,请将它们添加到另一个具有更高优先级的 RoutingPolicyRule 中。

/etc/systemd/network/50-wg0.network
...
[RoutingPolicyRule]
To=192.168.0.0/24
Priority=9
...

特定用户的路由

可能希望仅为特定用户(例如,用于 torrent 流量的 transmission 用户)通过隧道路由 WAN 流量。

/etc/systemd/network/99-wg0.network
...
[RoutingPolicyRule]
Table=1000
User=transmission
Priority=30001
Family=both

[RoutingPolicyRule]
Table=main
User=transmission
SuppressPrefixLength=0
Priority=30000
Family=both
...

优先级更高的规则(30000)匹配 transmission 用户生成的所有流量,并将其路由通过主表(无 wireguard),但仅使用前缀长度大于 0 的规则。这排除了默认的 catch-all 规则。因此,只有匹配主表特定规则(如定义本地家庭网络子网的规则)的流量才通过主表路由。

优先级较低的规则(30001)匹配 transmission 用户生成的所有流量,并将其路由通过表 1000,即 wireguard 表。

注意:这些规则应该 *代替* 本节开头定义的两个规则来路由所有流量通过 wireguard。

测试

使用以下命令测试代理:

# ipv4
$ curl -4 zx2c4.com/ip

# ipv6
$ curl -6 zx2c4.com/ip

检查 systemd-networkd 日志以获取任何错误和警告消息。

$ journalctl -u systemd-networkd.service

调用 wireguard-tools 中的 wg 命令。

Netctl

Netctl 原生地支持设置 WireGuard 接口。一组典型的 WireGuard netctl 配置文件如下所示:

对等点 A 设置

/etc/netctl/wg0
Description="WireGuard tunnel on peer A"
Interface=wg0
Connection=wireguard
WGConfigFile=/etc/wireguard/wg0.conf

IP=static
Address=('10.0.0.1/24')
/etc/wireguard/wg0.conf
[Interface]
ListenPort = 51871
PrivateKey = PEER_A_PRIVATE_KEY

[Peer]
PublicKey = PEER_B_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
Endpoint = peer-b.example:51902

[Peer]
PublicKey = PEER_C_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32

对等点 B 设置

/etc/netctl/wg0
Description="WireGuard tunnel on peer B"
Interface=wg0
Connection=wireguard
WGConfigFile=/etc/wireguard/wg0.conf

IP=static
Address=('10.0.0.2/24')
/etc/wireguard/wg0.conf
[Interface]
ListenPort = 51902
PrivateKey = PEER_B_PRIVATE_KEY

[Peer]
PublicKey = PEER_A_PUBLIC_KEY
AllowedIPs = 10.0.0.1/32
Endpoint = peer-a.example:51871

[Peer]
PublicKey = PEER_C_PUBLIC_KEY
AllowedIPs = 10.0.0.3/32

对等点 C 设置

/etc/netctl/wg0
Description="WireGuard tunnel on peer C"
Interface=wg0
Connection=wireguard
WGConfigFile=/etc/wireguard/wg0.conf

IP=static
Address=('10.0.0.3/24')
/etc/wireguard/wg0.conf
[Interface]
ListenPort = 51993
PrivateKey = PEER_C_PRIVATE_KEY

[Peer]
PublicKey = PEER_A_PUBLIC_KEY
AllowedIPs = 10.0.0.1/32
Endpoint = peer-a.example:51871

[Peer]
PublicKey = PEER_B_PUBLIC_KEY
AllowedIPs = 10.0.0.2/32
Endpoint = peer-b.example:51902

然后根据需要启动和/或启用每个参与对等点上的 wg0 接口,即:

# netctl start wg0

要使用 WireGuard 和 Netctl 实现持久化的站点对点、点对站点或站点对站点连接,只需在 netctl 配置文件中添加适当的 Routes= 行,并将此网络添加到 WireGuard 配置文件的 AllowedIPs 中,例如在 /etc/netctl/wg0 中添加 Routes=('192.168.10.0/24 dev wg0'),并在 /etc/wireguard/wg0.conf 中添加 AllowedIPs=10.0.0.1/32, 192.168.10.0/24,然后别忘了 启用 IP 转发

NetworkManager

NetworkManager 原生地支持设置 WireGuard 接口。有关 WireGuard 在 NetworkManager 中使用的所有详细信息,请阅读 Thomas Haller 的博客文章 — WireGuard in NetworkManager

提示 NetworkManager 可以导入 wg-quick 配置文件。例如:
# nmcli connection import type wireguard file /etc/wireguard/wg0.conf
注意 nmcli 可以创建一个 WireGuard 连接配置文件,但它不支持配置对等点。请参阅 NetworkManager issue 358

以下示例通过 keyfile 格式 *.nmconnection* 文件配置 WireGuard。有关语法和可用选项的说明,请参阅 nm-settings-keyfile(5)nm-settings(5)

对等点 A 设置

/etc/NetworkManager/system-connections/wg0.nmconnection
[connection]
id=wg0
type=wireguard
interface-name=wg0

[wireguard]
listen-port=51871
private-key=PEER_A_PRIVATE_KEY
private-key-flags=0

[wireguard-peer.PEER_B_PUBLIC_KEY]
endpoint=peer-b.example:51902
preshared-key=PEER_A-PEER_B-PRESHARED_KEY
preshared-key-flags=0
allowed-ips=10.0.0.2/32;fdc9:281f:04d7:9ee9::2/128;

[wireguard-peer.PEER_C_PUBLIC_KEY]
preshared-key=PEER_A-PEER_C-PRESHARED_KEY
preshared-key-flags=0
allowed-ips=10.0.0.3/32;fdc9:281f:04d7:9ee9::3/128;

[ipv4]
address1=10.0.0.1/24
method=manual

[ipv6]
address1=fdc9:281f:04d7:9ee9::1/64
method=manual
  • 要将 *所有流量* 通过隧道路由到特定对等点,请将 默认路由(IPv4 为 0.0.0.0/0,IPv6 为 ::/0)添加到 wireguard-peer.PEER_X_PUBLIC_KEY.allowed-ips。例如 wireguard-peer.PEER_B_PUBLIC_KEY.allowed-ips=0.0.0.0/0;::/0;。自 NetworkManager 1.20.0 起,支持对 WireGuard 连接中的默认路由进行特殊处理。
  • 要使用对等点作为 DNS 服务器,请使用 ipv4.dnsipv6.dns 设置指定其 WireGuard 隧道的 IP 地址(或多个地址)。搜索域可以使用 ipv4.dns-search=ipv6.dns-search= 选项指定。有关详细信息,请参阅 nm-settings(5)。例如,使用 keyfile 格式:
...
[ipv4]
...
dns=10.0.0.2;
dns-search=corp;
...
[ipv6]
...
dns=fdc9:281f:04d7:9ee9::2;
dns-search=corp;
...

要将对等点用作 *唯一* DNS 服务器,请设置负 DNS 优先级(例如 dns-priority=-1)并将 ~. 添加到 dns-search= 设置中。

对等点 B 设置

/etc/NetworkManager/system-connections/wg0.nmconnection
[connection]
id=wg0
type=wireguard
interface-name=wg0

[wireguard]
listen-port=51902
private-key=PEER_B_PRIVATE_KEY
private-key-flags=0

[wireguard-peer.PEER_A_PUBLIC_KEY]
endpoint=198.51.100.101:51871
preshared-key=PEER_A-PEER_B-PRESHARED_KEY
preshared-key-flags=0
allowed-ips=10.0.0.1/32;fdc9:281f:04d7:9ee9::1/128;

[wireguard-peer.PEER_C_PUBLIC_KEY]
preshared-key=PEER_B-PEER_C-PRESHARED_KEY
preshared-key-flags=0
allowed-ips=10.0.0.3/32;fdc9:281f:04d7:9ee9::3/128;

[ipv4]
address1=10.0.0.2/24
method=manual

[ipv6]
address1=fdc9:281f:04d7:9ee9::2/64
method=manual

对等点 C 设置

/etc/NetworkManager/system-connections/wg0.nmconnection
[connection]
id=wg0
type=wireguard
interface-name=wg0

[wireguard]
listen-port=51993
private-key=PEER_C_PRIVATE_KEY
private-key-flags=0

[wireguard-peer.PEER_A_PUBLIC_KEY]
endpoint=198.51.100.101:51871
preshared-key=PEER_A-PEER_C-PRESHARED_KEY
preshared-key-flags=0
allowed-ips=10.0.0.1/32;fdc9:281f:04d7:9ee9::1/128;

[wireguard-peer.PEER_B_PUBLIC_KEY]
endpoint=peer-b.example:51902
preshared-key=PEER_B-PEER_C-PRESHARED_KEY
preshared-key-flags=0
allowed-ips=10.0.0.2/32;fdc9:281f:04d7:9ee9::2/128;

[ipv4]
address1=10.0.0.3/24
method=manual

[ipv6]
address1=fdc9:281f:04d7:9ee9::3/64
method=manual

特定用例:VPN 服务器

本文档或此章节可以合并到 #wg-quick

注意:相同的用例。(在 Talk:WireGuard 中讨论)
注意 本节中“服务器”和“客户端”这两个词的选择是为了帮助新用户/现有 OpenVPN 用户熟悉 WireGuard 配置文件的构建。WireGuard 文档仅将这两个概念都称为“对等点”。

本节的目的是设置一个 WireGuard“服务器”和通用的“客户端”,以便通过加密和安全的隧道(如 OpenVPN 等)访问服务器/网络资源。“服务器”运行在 Linux 上,“客户端”可以在任何数量的平台上运行(WireGuard 项目除了 Linux、Windows 和 MacOS 外,还提供 iOS 和 Android 平台的应用程序)。有关更多信息,请参阅官方项目 安装链接

提示 除了使用 wireguard-tools 进行服务器/客户端配置外,还可以使用 systemd-networkd 的原生 WireGuard 支持。

服务器

本文档或此章节可以合并到 #站点对点连接

注意:相同的用例。(在 Talk:WireGuard 中讨论)

在充当“服务器”的对等点上,首先 启用 IPv4 转发

如果服务器配置了公共 IP,请务必

  • 允许 WireGuard 运行所在的指定端口(例如,允许 51820/UDP 上的流量)的 UDP 流量。
  • 如果防火墙未包含在接口本身的 WireGuard 配置中,请设置防火墙的转发策略 /etc/wireguard/wg0.conf。下面的示例应包含 iptables 规则并且可以正常工作。

如果服务器位于 NAT 后面,请务必将 WireGuard 运行所在的指定端口(例如 51820/UDP)从路由器转发到 WireGuard 服务器。

密钥生成

按照 #密钥生成 中的说明为服务器和每个客户端生成密钥对。

服务器配置

创建“服务器”配置文件

/etc/wireguard/wg0.conf
[Interface]
Address = 10.200.200.1/24
ListenPort = 51820
PrivateKey = SERVER_PRIVATE_KEY

# substitute eth0 in the following lines to match the Internet-facing interface
# the FORWARD rules will always be needed since traffic needs to be forwarded between the WireGuard
# interface and the other interfaces on the server.
# if the server is behind a router and receives traffic via NAT, specify static routing back to the
# 10.200.200.0/24 subnet, the NAT iptables rules are not needed but the FORWARD rules are needed.
# if the server is behind a router and receives traffic via NAT but one cannot specify static routing back to
# 10.200.200.0/24 subnet, both the NAT and FORWARD iptables rules are needed. 
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# foo
PublicKey = PEER_FOO_PUBLIC_KEY
PresharedKey = PRE-SHARED_KEY
AllowedIPs = 10.200.200.2/32

[Peer]
# bar
PublicKey = PEER_BAR_PUBLIC_KEY
PresharedKey = PRE-SHARED_KEY
AllowedIPs = 10.200.200.3/32

可以根据需要以相同的格式列出其他对等点(“客户端”)。每个对等点都需要设置 PublicKey。但是,指定 PresharedKey 是可选的。

请注意,Address 的 netmask 为 /24,而客户端的 AllowedIPs/32。客户端仅使用其 IP,而服务器仅将其各自的地址发送回。

可以使用 wg-quick(8) 手动管理接口,或者使用通过 systemctl(1) 管理的 systemd 服务。

可以使用 wg-quick up wg0 分别通过 启动 并可能通过 wg-quick@interface.service 启用 接口来启动接口,例如 wg-quick@wg0.service。要关闭接口,请使用 wg-quick down wg0 分别 停止 wg-quick@interface.service

客户端配置

创建相应的“客户端”配置文件(或多个配置文件)

foo.conf
[Interface]
Address = 10.200.200.2/32
PrivateKey = PEER_FOO_PRIVATE_KEY
DNS = 10.200.200.1

[Peer]
PublicKey = SERVER_PUBLICKEY
PresharedKey = PRE-SHARED_KEY
Endpoint = my.ddns.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
bar.conf
[Interface]
Address = 10.200.200.3/32
PrivateKey = PEER_BAR_PRIVATE_KEY
DNS = 10.200.200.1

[Peer]
PublicKey = SERVER_PUBLICKEY
PresharedKey = PRE-SHARED KEY
Endpoint = my.ddns.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0

使用通配符 AllowedIPs = 0.0.0.0/0, ::/0 将转发所有 IPv4 (0.0.0.0/0) 和 IPv6 (::/0) 流量通过 VPN。

注意 NetworkManager 的用户可能需要 启用 NetworkManager-wait-online.service 服务,而 systemd-networkd 的用户可能需要 启用 systemd-networkd-wait-online.service 服务,以在尝试 WireGuard 连接之前等待设备准备好网络。

测试隧道

本文档或此章节可以合并到 #基本检查

注意:相同主题。(在 Talk:WireGuard 中讨论)

建立隧道后,可以使用 netcat 通过隧道发送流量以测试吞吐量、CPU 使用率等。在隧道的任一侧运行 nc 以监听模式,在另一侧将一些数据从 /dev/zero 管道传输到 nc 的发送模式。

在下面的示例中,端口 2222 用于流量(如果使用防火墙,请确保允许端口 2222 上的流量)。

在隧道的一侧监听流量

$ nc -vvlnp 2222

在隧道的另一侧发送流量

$ dd if=/dev/zero bs=1024K count=1024 | nc -v 10.0.0.203 2222

可以使用 wg 直接监控状态。

# wg
interface: wg0
  public key: UguPyBThx/+xMXeTbRYkKlP0Wh/QZT3vTLPOVaaXTD8=
  private key: (hidden)
  listening port: 51820

peer: 9jalV3EEBnVXahro0pRMQ+cHlmjE33Slo9tddzCVtCw=
  preshared key: (hidden)
  endpoint: 192.168.1.216:53207
  allowed ips: 10.0.0.0/0
  latest handshake: 1 minutes, 17 seconds ago
  transfer: 56.43 GiB received, 1.06 TiB sent

技巧与提示

将私钥存储为加密形式 (wg-quick)

可能希望将私钥以加密形式存储,例如通过使用 pass。只需将 WireGuard 配置文件中 [Interface] 下的 PrivateKey 行替换为:

PostUp = wg set %i private-key <(su user -c "export PASSWORD_STORE_DIR=/path/to/your/store/; pass WireGuard/private-keys/%i")

其中 user 是相关用户的 Linux 用户名。有关更多详细信息,请参阅 wg-quick(8) 手册页。

另外,也可以使用 systemd-creds。这有助于创建绑定到系统 TPM 的加密私钥。有关更多详细信息,请参阅 systemd-creds(1)

首先,创建一个加密凭据

# echo -n your_wg_private_key | systemd-creds --tpm2-device=auto encrypt - /etc/credstore.encrypted/wg-private-key.cred

最后,将 WireGuard 配置文件中 [Interface] 下的 PrivateKey 行替换为

PostUp = wg set %i private-key <(systemd-creds decrypt /etc/credstore.encrypted/wg-private-key.cred)

为私钥使用 systemd 凭据 (systemd-networkd)

您可以使用 systemd-creds 来加密存储您的私钥。

# echo -n your_wg_private_key | systemd-creds encrypt - /etc/credstore.encrypted/network.wireguard.private.wg0
# echo -n your_pre_shared_key | systemd-creds encrypt - /etc/credstore.encrypted/network.wireguard.psk.wg0
注意 存储的名称必须匹配 network.wireguard.*。请参阅 systemd.netdev(5) § [WIREGUARD]_SECTION_OPTIONS

修改您的 .netdev 文件以使用

PrivateKey = @network.wireguard.private.wg0
PresharedKey = @network.wireguard.psk.wg0

IP 地址变化的端点

解析服务器的域名后,WireGuard 将不再检查 DNS 更改

如果 WireGuard 服务器因 DHCP、Dyndns、IPv6 等原因频繁更改其 IP 地址,任何 WireGuard 客户端都会丢失连接,直到其端点通过 wg set "$INTERFACE" peer "$PUBLIC_KEY" endpoint "$ENDPOINT" 等方式更新。

另外请注意,如果端点更改其地址(例如,迁移到新的提供商/数据中心),仅更新 DNS 是不够的,因此定期运行 reresolve-dns 脚本可能对任何基于 DNS 的设置都有意义。

幸运的是,wireguard-tools 提供了一个示例脚本 /usr/share/wireguard-tools/examples/reresolve-dns/reresolve-dns.sh,该脚本可以解析 WG 配置文件并自动重置端点地址。

需要定期运行 /usr/share/wireguard-tools/examples/reresolve-dns/reresolve-dns.sh /etc/wireguard/wg.conf 以从端点 IP 更改中恢复。

一种方法是通过 systemd 定时器每三十秒更新所有 WireGuard 端点一次[5]

/etc/systemd/system/wireguard_reresolve-dns.timer
[Unit]
Description=Periodically reresolve DNS of all WireGuard endpoints

[Timer]
OnCalendar=*:*:0/30

[Install]
WantedBy=timers.target
/etc/systemd/system/wireguard_reresolve-dns.service
[Unit]
Description=Reresolve DNS of all WireGuard endpoints
Wants=network-online.target
After=network-online.target nss-lookup.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'for i in /etc/wireguard/*.conf; do /usr/share/wireguard-tools/examples/reresolve-dns/reresolve-dns.sh "$i"; done'

之后 启用启动 wireguard_reresolve-dns.timer

生成二维码

如果客户端是手机等移动设备,可以使用 qrencode 来生成客户端配置的二维码并在终端显示。

$ qrencode -t ansiutf8 -r client.conf

启用调试日志

当使用支持 动态调试 的内核的 Linux 内核模块时,可以通过运行以下命令将调试信息写入内核环形缓冲区(可通过 dmesgjournalctl 查看):

# modprobe wireguard
# echo module wireguard +p > /sys/kernel/debug/dynamic_debug/control

重新加载对等方(服务器)配置

如果 WireGuard 对等方(主要是服务器)正在从其配置中添加或删除其他对等方,并且希望在不停止任何活动会话的情况下重新加载配置,可以执行以下命令:

# wg syncconf ${WGNET} <(wg-quick strip ${WGNET})

其中 $WGNET 是 WireGuard 接口名称或配置基本名称,例如 wg0(对于服务器)或 client(不带 .conf 扩展名,对于客户端)。

wg-quick@.service 的用户可以简单地 重新加载 服务。

本文章或章节需要扩充。

原因:展示如何使用 #持久化配置 中的其他网络管理器来实现此目的。(在 Talk:WireGuard 中讨论)

解决部分公共 Wi-Fi 网络似乎阻止 WireGuard 连接的变通方法

注意 仅当设备可用蜂窝网络连接时,此变通方法才是一个选项。

某些 Wi-Fi 网络可能配置为主动识别和阻止 WireGuard 的握手,从而阻止初始连接并阻止建立安全隧道。

此策略可以阻止 *新* 的 WireGuard 连接,但对 *现有* 连接无效。因此,要在此类网络上使用 WireGuard,只需在加入 Wi-Fi 网络之前通过蜂窝网络连接到 WireGuard 对等方,从而允许在主动阻止发生之前完成握手。当设备从蜂窝网络切换到 Wi-Fi 时,WireGuard 会保持此隧道开启。

故障排除

路由被定期重置

NetworkManager 的用户应确保它 不管理 WireGuard 接口。例如,创建以下配置文件:

/etc/NetworkManager/conf.d/unmanaged.conf
[keyfile]
unmanaged-devices=type:wireguard

DNS 解析中断

当通过 WireGuard 接口隧道传输所有流量时,连接可能会在一段时间后或在新连接时看似丢失。这可能是由于 网络管理器DHCP 客户端覆盖了 /etc/resolv.conf

默认情况下,wg-quick 使用 resolvconf 注册新的 DNS 条目(来自配置文件中的 DNS 关键字)。这会导致不使用 resolvconf网络管理器DHCP 客户端出现问题,因为它们会覆盖 /etc/resolv.conf,从而删除 wg-quick 添加的 DNS 服务器。

解决方案是使用支持 resolvconf 的网络软件。

注意 systemd-resolved 的用户应确保 systemd-resolvconf安装

NetworkManager 的用户应该知道它默认不使用 resolvconf。建议使用 systemd-resolved。如果不想这样做,请 安装 openresolv 并配置 NetworkManager 使用它:NetworkManager#Use openresolv

调整 MTU 值

Wireguard 的默认最大传输单元 (MTU) 值为 1420

由于 MTU 过低(低于 1280),wg-quick 可能无法创建 WireGuard 接口。这可以通过在客户端的 WireGuard 配置的 Interface 部分设置 MTU 值来解决。

foo.config
[Interface]
Address = 10.200.200.2/24
MTU = 1420
PrivateKey = PEER_FOO_PRIVATE_KEY
DNS = 10.200.200.1

根据您的网络情况,较低的 MTU 值也能使您的 WireGuard 连接工作。

在某些情况下,由于路径上的 路径 MTU 发现 (PMTU) 不可靠,较大的 MTU 值可能导致连接不稳定或间歇性连接。这可能导致 ICMP ping 由于其数据包大小小而工作,但大多数 TCP 连接因 MTU 大小被充分利用而失败。例如,IPv6 连接比 IPv4 具有更高的数据包开销,因此在相同的 MTU 值下,分片可能会更早发生。

值得检查双方对等方以及其他涉及的路由器的链路 MTU 大小,以确定最小值。

# ip link show
5: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1400 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/none

另一种选择是回退到 1280 的 MTU,并通过试错法找到给定路径的适当值。

MTU 为 1420 及以上可能导致链路部分损坏,这可能被解释为防火墙或路由问题,而不是实际的 MTU 大小。

密钥长度或格式不正确

为避免出现以下错误,请将密钥值放在配置文件中,而不是密钥文件的路径。

# wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
Key is not the correct length or format: `/path/example.key'
Configuration parsing error
[#] ip link delete dev wg0

在 NAT / 防火墙后无法建立持久连接

默认情况下,WireGuard 对等方在不需要通信时保持静默,因此位于 NAT 和/或 防火墙后面的对等方可能无法从其他对等方到达,直到它们自己联系其他对等方(或连接超时)。在位于 NAT 和/或防火墙后面的对等方的 [Peer] 设置中添加 PersistentKeepalive = 25 可以确保连接保持打开状态。

要通过命令行临时设置持久保持连接设置,请运行以下命令:

# wg set wg0 peer public_key persistent-keepalive 25

循环路由

将端点 IP 添加到允许的 IP 列表,内核将尝试将握手发送到该设备绑定,而不是使用原始路由。这会导致握手尝试失败。

作为一种变通方法,需要使用以下命令手动添加到端点的正确路由:

# ip route add endpoint_ip via gateway dev network_interface

例如,对于上面对等方 B 在标准 LAN 设置中:

# ip route add 203.0.113.102 via 192.168.0.1 dev eth0

要使此路由持久化,可以将命令作为 PostUp = ip route ... 添加到 wg0.conf[Interface] 部分。但是,在某些设置中(例如,在与 NetworkManager 结合使用 wg-quick@.service 时),这可能在恢复时失败。此外,这仅适用于静态网络设置,并且在网关或设备更改时(例如,在笔记本电脑上使用以太网或 Wi-Fi)会失败。

使用 NetworkManager,一个更灵活的解决方案是通过调度器脚本启动 WireGuard。以 root 身份创建:

/etc/NetworkManager/dispatcher.d/50-wg0.sh
#!/bin/sh
case $2 in
  up)
    wg-quick up wg0
    ip route add <endpoint ip> via $IP4_GATEWAY dev $DEVICE_IP_IFACE
    ;;
  pre-down)
    wg-quick down wg0
    ;;
esac

如果尚未运行,请启动并启用 NetworkManager-dispatcher.service。另外,请确保 NetworkManager 没有管理 wg0 的路由,请参阅 #路由被定期重置

使用 systemd-networkd 睡眠后连接丢失

systemd 版本 253 在从挂起状态恢复时重新配置网络接口的方式上引入了一项更改[6]。在此过程中,由 systemd-networkd 管理的网络连接将与 wireguard 接口断开。除非配置了终止开关(kill switch),否则恢复挂起状态后可能会暴露公共 IP 地址。要解决此问题,请在 /etc/systemd/networkd.conf 中注释掉 ManageForeignRoutingPolicyRules 并将其值更改为 no[7]

请完整查看 systemd-networkd 页面,以了解此更改可能带来的任何其他潜在副作用。

参见