AmneziaWG 3.0 readiness: centralize wg CLI contract, drop dead host-side fallback

Peer discovery is now the single owner of how wg is invoked and parsed.

wg.rs:
- resolve the binary through ordered amnezia.wg_binaries (default [awg, wg]);
  awg is the real binary in the official image and wg is a symlink to it, so awg is
  tried first and wg stays for plain WireGuard containers. No probe call: resolution
  is a property of the command being run anyway.
- drop the nsenter fallback. AmneziaWG is userspace and its UAPI socket lives under
  RUNSTATEDIR/amneziawg/ in the container mount namespace, while host wireguard-tools
  looks under /var/run/wireguard/. nsenter -n enters only the network namespace, so
  that path could never return peers.
- classify dump lines structurally instead of by column count. The AWG interface line
  is longer than a peer line (14 columns on AWG 2.0, 28 on AWG 3.0) and its
  handshake/rx/tx positions hold junk-packet sizes that parse as integers, so only the
  allowed-ips column discriminates. Column 1 of an interface line is the device private
  key, which the previous heuristic rejected only incidentally.
- fix allowed-ips parsing: `show all allowed-ips` separates a peer's addresses with
  spaces, not commas, so peers with more than one allowed IP were shaped on their first
  address only and the rest ran unlimited.
- collapse the three duplicated /32-in-CIDR filters into one tokenizer shared by the
  allowed-ips, dump and pretty-print parsers.

config.rs:
- add amnezia.wg_binaries with serde default, validated as bare command names
  (non-empty, no whitespace, no path separators) since they execute inside the
  container. Existing deployed configs keep parsing unchanged.
- remove host wg from the required-tool preflight. It gated daemon startup on
  wireguard-tools for a code path that produced nothing.

status.rs:
- discover peers once instead of twice per status call and degrade gracefully like the
  neighbouring sections instead of aborting the whole output.

Tests: real AWG 3.0 / AWG 2.0 / plain WireGuard interface-line fixtures, AWG 3.0 range
keepalive, space-separated allowed-ips, binary resolution order, and a test that parses
and validates the shipped config.example.toml.
This commit is contained in:
2026-08-06 15:32:26 +05:00
parent 5edefa74b1
commit 16214f3c66
13 changed files with 566 additions and 191 deletions
+14 -4
View File
@@ -1,12 +1,22 @@
[amnezia]
container_names = ["amnezia-awg2", "amnezia-awg"]
# Порядок важен: используется первый запущенный контейнер из списка.
# amnezia-awg3 указан на будущее: в AmneziaVPN 5.0 такого типа контейнера ещё нет.
container_names = ["amnezia-awg2", "amnezia-awg3", "amnezia-awg"]
interface_candidates = ["awg0", "wg0", "amnezia0", "tun0"]
interface_patterns = ["awg*", "wg*", "amnezia*", "tun*"]
# Утилита для чтения peer state внутри контейнера. Пробуются по порядку,
# используется первая успешная. В официальном образе AmneziaWG реальный бинарь —
# /usr/bin/awg, а /usr/bin/wg является symlink на него.
# Значения выполняются внутри контейнера: только имена команд, без путей и пробелов.
# На хосте wireguard-tools не требуется.
wg_binaries = ["awg", "wg"]
# Подсеть VPN peers.
# Проверка:
# C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
# C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
# docker exec "$C" ip -4 addr
# docker exec "$C" wg show
# docker exec "$C" awg show
peer_ipv4_cidr = "10.8.1.0/24"
[traffic]
@@ -53,7 +63,7 @@ enabled = true
# Должен совпадать с реально слушающим портом sshd до apply-firewall.
ssh_port = 2323
# Должен совпадать с опубликованным Docker/Amnezia UDP-портом.
# Проверка: docker port amnezia-awg2 2>/dev/null || docker port amnezia-awg
# Проверка: docker port amnezia-awg2 2>/dev/null || docker port amnezia-awg3 2>/dev/null || docker port amnezia-awg
# Транспортный порт AmneziaWG/AWG, опубликованный Docker, обычно 443/udp.
# Это не AmneziaDNS. Не указывайте здесь 53.
amnezia_port = 443