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:
@@ -5,11 +5,11 @@
|
||||
- [ ] Хост — Debian 13 amd64.
|
||||
- [ ] Сервер выделенный, без соседних сервисов.
|
||||
- [ ] AmneziaWG/AWG 2.0 или AmneziaWG/AWG 1.5 установлена официальным способом.
|
||||
- [ ] Контейнер `amnezia-awg2` или `amnezia-awg` запущен.
|
||||
- [ ] Контейнер `amnezia-awg2` или `amnezia-awg` запущен (`amnezia-awg3` — резерв на будущее, в AmneziaVPN 5.0 такого типа контейнера ещё нет).
|
||||
- [ ] `docker ps` видит контейнер.
|
||||
- [ ] Можно получить PID контейнера.
|
||||
- [ ] `/proc/<pid>/ns/net` существует.
|
||||
- [ ] На хосте доступны `ip`, `tc`, `wg`, `nsenter`, `modprobe`.
|
||||
- [ ] На хосте доступны `ip`, `tc`, `nsenter`, `modprobe`. Хостовый `wg` не требуется.
|
||||
- [ ] `awg2-harness validate-config` проходит без ошибок.
|
||||
|
||||
## B. Peer discovery
|
||||
@@ -17,9 +17,12 @@
|
||||
- [ ] `awg2-harness status` показывает найденный контейнер.
|
||||
- [ ] `awg2-harness status` показывает PID/netns контейнера.
|
||||
- [ ] `awg2-harness status` показывает найденный интерфейс.
|
||||
- [ ] Количество peers совпадает с `wg show all allowed-ips`.
|
||||
- [ ] Количество peers совпадает с `docker exec "$C" awg show all allowed-ips`.
|
||||
- [ ] Peer с несколькими allowed IP даёт отдельный класс на каждый адрес (в этой команде адреса разделены пробелом).
|
||||
- [ ] Offline peers с allowed IP тоже попадают в список shaping.
|
||||
- [ ] IP вне `amnezia.peer_ipv4_cidr` не попадают в traffic shaping.
|
||||
- [ ] В секции `WireGuard clients` вывода `status` нет строки, соответствующей самому интерфейсу (столбец `Public key` не содержит приватный ключ устройства).
|
||||
- [ ] `docker exec "$C" readlink -f /usr/bin/wg` возвращает `/usr/bin/awg`.
|
||||
|
||||
## C. Traffic topology contract
|
||||
|
||||
@@ -161,7 +164,7 @@
|
||||
- [ ] AmneziaDNS установлен из приложения AmneziaVPN.
|
||||
- [ ] Контейнер `amnezia-dns` в состоянии healthy.
|
||||
- [ ] `docker inspect amnezia-dns` показывает `"53/tcp":null` и `"53/udp":null`.
|
||||
- [ ] `amnezia-dns` и активный AWG-контейнер (`amnezia-awg2` или `amnezia-awg`) подключены к одной Amnezia DNS Docker-сети.
|
||||
- [ ] `amnezia-dns` и активный AWG-контейнер (`amnezia-awg2`, `amnezia-awg3` или `amnezia-awg`) подключены к одной Amnezia DNS Docker-сети.
|
||||
- [ ] Публичный DNS-запрос к `<server-public-ip>:53` не резолвит домены; допустимы `connection refused`, `timeout` или `no servers could be reached`.
|
||||
- [ ] DNS-резолвинг у VPN-клиента работает при активном подключении.
|
||||
- [ ] AWG2 host firewall не открывает `53/tcp` и `53/udp`.
|
||||
@@ -181,6 +184,6 @@
|
||||
- [ ] `status` показывает блок `Docker/Amnezia port path` с полями `docker_userland_proxy`, `published_udp_port` и note про Docker-managed `FORWARD`.
|
||||
- [ ] `status` показывает поля `host_forward_policy_drop` и `docker_forward_rules_present` в блоке `Docker/Amnezia port path`.
|
||||
- [ ] Если `docker_userland_proxy=false` и `FORWARD policy DROP`, при отсутствии явных Docker accept-признаков `status` выводит warning, но `awg2-harness` не изменяет `FORWARD` автоматически.
|
||||
- [ ] Сверено соответствие: `config host_firewall.amnezia_port` ↔ опубликованный Docker UDP host port ↔ `docker exec amnezia-awg2 wg show` (`listening port`).
|
||||
- [ ] Сверено соответствие: `config host_firewall.amnezia_port` ↔ опубликованный Docker UDP host port ↔ `docker exec amnezia-awg2 awg show` (`listening port`).
|
||||
- [ ] При нескольких UDP bindings без однозначного соответствия `host_firewall.amnezia_port` диагностика `published_udp_port` показывает `unknown` (ambiguous), а не произвольный первый порт.
|
||||
- [ ] Для диагностики FORWARD используется best-effort проверка: `iptables -S FORWARD` и fallback через `nft list ruleset`; `status` не падает при недоступности одной из команд.
|
||||
|
||||
Reference in New Issue
Block a user