Wireguard 服务似乎在网络真正上线之前就启动了

Wireguard 服务似乎在网络真正上线之前就启动了

我有点疯狂地尝试让 Wireguard 在运行于 Raspberry-Pi5 上的 Ubuntu Server 23.10 上运行。

总体而言,Wireguard 配置有效。我可以启动wg0和关闭。但是,如果我重新启动 pi,Wireguard systemd 服务将失败:

-- Boot --
Feb 10 17:25:26 host systemd[1]: Starting [email protected] - WireGuard via wg-quick(8) for wg0...
Feb 10 17:25:26 host wg-quick[600]: [#] ip link add wg0 type wireguard
Feb 10 17:25:26 host wg-quick[600]: [#] wg setconf wg0 /dev/fd/63
Feb 10 17:25:26 host wg-quick[600]: [#] ip -4 address add X.X.X.X/32 dev wg0
Feb 10 17:25:26 host wg-quick[663]: RTNETLINK answers: Network is unreachable
Feb 10 17:25:26 host wg-quick[600]: [#] ip link set mtu 1420 up dev wg0
Feb 10 17:25:26 host wg-quick[600]: [#] ip -4 rule add not fwmark 51820 table 51820
Feb 10 17:25:26 host wg-quick[600]: [#] ip -4 rule add table main suppress_prefixlength 0
Feb 10 17:25:26 host wg-quick[600]: [#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
Feb 10 17:25:26 host wg-quick[600]: [#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
Feb 10 17:25:26 host wg-quick[600]: [#] nft -f /dev/fd/63
Feb 10 17:25:27 host wg-quick[600]: [#] resolvectl dns wg0 9.9.9.9; resolvectl domain wg0 \~.; resolvectl default-route eth0 false
Feb 10 17:25:27 host wg-quick[600]: [#] iptables -I OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 fwmark) -m addrtype ! --dst-type LOCAL -j REJECT && ip6tables -I OUTPUT ! -o wg0 -m mark ! --mark $(wg show wg0 >
Feb 10 17:25:27 host wg-quick[600]: [#] iptables -I OUTPUT -m iprange --dst-range 10.10.10.2-10.10.10.14 -j ACCEPT
Feb 10 17:25:27 host wg-quick[600]: [#] ip route add 10.10.10.0/28 via 172.20.30.1 dev eth0
Feb 10 17:25:27 host wg-quick[727]: Error: Nexthop has invalid gateway.
Feb 10 17:25:27 host wg-quick[600]: [#] nft -f /dev/fd/63
Feb 10 17:25:27 host wg-quick[600]: [#] ip -4 rule delete table 51820
Feb 10 17:25:27 host wg-quick[600]: [#] ip -4 rule delete table main suppress_prefixlength 0
Feb 10 17:25:27 host wg-quick[600]: [#] ip link delete dev wg0
Feb 10 17:25:27 host systemd[1]: [email protected]: Main process exited, code=exited, status=2/INVALIDARGUMENT
Feb 10 17:25:27 host systemd[1]: [email protected]: Failed with result 'exit-code'.
Feb 10 17:25:27 host systemd[1]: Failed to start [email protected] - WireGuard via wg-quick(8) for wg0.

这会导致 iptables 状态不干净。但是,如果我清理 iptablessudo iptables -F并尝试wg0手动启动,这将不会出现任何问题。

现在,我做的并不是什么罕见的事情。基本上,我遵循以下步骤:

  • 使用 Raspberry Pi Imager 安装 Ubuntu Server 23.10
  • 禁用 NetworkInterfaceNames(坚持使用静态名称 - eth0 等)
  • apt updateapt upgrade
  • 安装 Wireguard
  • 配置 Wireguarg 并启动wg0
  • 启用 Wireguard 服务

请注意,相同的配置/方法适用于在 Raspberry-PI3 上运行的 Ubuntu Server 23.04,其中 Wireguard 服务将成功启动和完成,没有任何问题。

此时,一切正常。我可以wg0毫无问题地关闭和启动 PI。但是,如果我重新启动 PI,wireguard 服务将失败。我目前的猜测是,由于某种原因,Wireguard 服务在网络真正上线之前启动。这是基于以下日志的,您可以看到 Wireguard 启动得比 systemd-networkd 报告它从 DHCP 收到配置的时间更早:

-- Boot --
Feb 10 17:25:25 host systemd[1]: Starting systemd-networkd.service - Network Configuration...
Feb 10 17:25:26 host systemd-networkd[451]: lo: Link UP
Feb 10 17:25:26 host systemd-networkd[451]: lo: Gained carrier
Feb 10 17:25:26 host systemd-networkd[451]: Enumeration completed
Feb 10 17:25:26 host systemd[1]: Started systemd-networkd.service - Network Configuration.
Feb 10 17:25:26 host systemd-networkd[451]: eth0: found matching network '/run/systemd/network/10-netplan-eth0.network', based on potentially unpredictable interface name.
Feb 10 17:25:26 host systemd-networkd[451]: eth0: Configuring with /run/systemd/network/10-netplan-eth0.network.
Feb 10 17:25:26 host systemd-networkd[451]: eth0: Link UP
Feb 10 17:25:26 host systemd-networkd[451]: wg0: Link UP
Feb 10 17:25:26 host systemd-networkd[451]: wg0: Gained carrier
Feb 10 17:25:27 host systemd-networkd[451]: wg0: Link DOWN
Feb 10 17:25:27 host systemd-networkd[451]: wg0: Lost carrier
Feb 10 17:25:30 host systemd-networkd[451]: eth0: Gained carrier
Feb 10 17:25:30 host systemd-networkd[451]: eth0: found matching network '/run/systemd/network/10-netplan-eth0.network', based on potentially unpredictable interface name.
Feb 10 17:25:30 host systemd-networkd[451]: eth0: DHCPv4 address 172.20.30.14/28, gateway 172.20.30.1 acquired from 172.20.30.1
Feb 10 17:25:31 host systemd-networkd[451]: eth0: Gained IPv6LL

但是,[email protected]基本上是默认文件,从中可以看出该服务依赖于 network-online.target,这应该仅在网络真正在线时才启动 wireguard:

[Unit]
Description=WireGuard via wg-quick(8) for %I
After=network-online.target nss-lookup.target
Wants=network-online.target nss-lookup.target

PartOf=wg-quick.target
Documentation=man:wg-quick(8)
Documentation=man:wg(8)
Documentation=https://www.wireguard.com/
Documentation=https://www.wireguard.com/quickstart/
Documentation=https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
Documentation=https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/wg-quick up %i
ExecStop=/usr/bin/wg-quick down %i
ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip %i)'
Environment=WG_ENDPOINT_RESOLUTION_RETRIES=infinity

[Install]
WantedBy=multi-user.target

所以,我不明白为什么会发生这种情况以及如何缓解这种情况。任何帮助都非常感谢。谢谢!


添加网络在线状态:

network-online.target - Network is Online
     Loaded: loaded (/lib/systemd/system/network-online.target; static)
     Active: active since Sat 2024-02-10 18:42:29; 1h 24min ago
       Docs: man:systemd.special(7)
             https://systemd.io/NETWORK_ONLINE

Feb 10 18:42:29 host systemd[1]: Reached target network-online.target - Network is Online

答案1

提到的问题似乎与 systemd 的工作方式以及何时认为网络已启动有关。请参阅:https://systemd.io/NETWORK_ONLINE/

“上涨” 究竟意味着什么?

network-online.target 之前订购的服务定义了其含义。通常意味着所有配置的网络设备都已启动并分配了 IP 地址,但细节可能会有所不同。特别是,配置可能会影响要考虑哪些接口。

Systemd 文档总体上提到了如何处理这种情况的不同方法。

但我个人选择在 Wireguard 服务中引入“ExecStartPre”命令,正如@Daniel T 在评论中提到的那样。

...
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=sh -c 'until ping -c 1 example.com; do sleep 1; done'
ExecStart=/usr/bin/wg-quick up %i
ExecStop=/usr/bin/wg-quick down %i
ExecReload=/bin/bash -c 'exec /usr/bin/wg syncconf %i <(exec /usr/bin/wg-quick strip %i)'
Environment=WG_ENDPOINT_RESOLUTION_RETRIES=infinity
...

这个解决方案可能不是最优雅的,但它的主要好处是我不需要处理网络在线或任何其他服务。

但是,如果有人需要一个适用于许多依赖服务的更强大的解决方案,我建议查看 systemd 文档:

还可以插入额外的网络状态检查。例如,为了延迟 network-online.target 直到某个特定主机可访问(可以通过 DNS 解析名称并建立适当的路由),可以使用以下简单服务:

[Unit]
DefaultDependencies=no
After=nss-lookup.target
Before=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=sh -c 'until ping -c 1 example.com; do sleep 1; done'

[Install]
WantedBy=network-online.target

相关内容