d98ade42ce
The docs folder had drifted into a mixed-language contract: IMPLEMENTATION_SPEC.md was entirely in English while the rest was Russian with English headings. Prose is now Russian throughout; English is kept only where it is technically load-bearing (commands, tool output, config keys, file/module/table names, tc handles) and for terms with no settled Russian equivalent in this context (drift, reconcile, peer, namespace, handshake). docs/README.md now states that contract explicitly. Rewriting the spec surfaced several places where it described intent rather than the code. Corrected against traffic_core/src: - module layout: the spec showed traffic/ and firewall/ as directories with model/inspect/apply submodules. They are single files, and sysctl_tuning.rs was missing from the tree entirely. - data model: Peer was documented as carrying public key, handshake and counters. It carries only ipv4; runtime state lives in a separate PeerRuntime, and there is no desired-state struct at all - it is derived inline from config plus sorted peers. RuntimeTarget.netns_path is a String, not a PathBuf. - interface detection: the spec listed a third step taking the first non-loopback interface with an IPv4 address. No such fallback exists; detection bails with an explicit error, which is safer and is now documented as deliberate. - reconcile: the pseudo-flow folded firewall into reconcile_traffic. They are two independent reconciles with separate locks. - locking: only traffic.lock was documented. There are three locks, and sysctl_tuning.lock has a 30s timeout rather than 10s. Stale-lock recovery via /proc/<pid> was undocumented. - sysctl_tuning: the module also manages /etc/modules-load.d/90-awg2-harness-bbr.conf when BBR is active, and refuses to touch either managed file without its marker. Both docs and the acceptance checklist claimed only the sysctl.d file was written. - status contract: the documented output was outdated. All 15 printed sections are now listed in the order status.rs emits them, including the degraded path when no container is found, and the fact that the Network tuning block is printed between the System service line and the container lines. - swap: size was documented as a constant 2048 MB instead of swap.size_mb, and the /etc/fstab.awg2-harness.bak backup was undocumented. - apply/verify: the tolerated-error lists are now the actual closed sets from the code. Acceptance checklist gained checks for the daemon startup failure policy (sysctl/swap fatal, traffic/firewall not), lock contention and stale-lock recovery, degraded status, the modules-load file, and the marker guard. The stale host wg requirement was dropped from its host-tools item. Every path, table, counter and log string quoted in the docs was verified to exist in the source. cargo test --workspace: 110 + 4 passed.
2.5 KiB
2.5 KiB
Эталонный production-пример
Документ фиксирует эталонное состояние production после успешной установки и preflight. Значения обезличены и предназначены как ориентир для smoke-проверки.
SSH:
host: <server-ip>
port: 2323
user: root
Amnezia:
container: amnezia-awg2
interface: awg0
published UDP: 443
peer CIDR: 10.8.1.0/24
AmneziaDNS:
container: amnezia-dns
status: healthy
internal_ip: 172.29.172.254 # example value; verify with docker inspect
exposed_ports: 53/tcp, 53/udp inside Docker only
published_ports: none
public_53: closed
Expected status:
service: active
network tuning drift: no
traffic drift: no
host firewall drift: no
anti-torrent drift: no
swap drift: no
Проверка ключевых сигналов:
systemctl status awg2-harness.service --no-pager -l
systemctl status awg2-reboot-scheduler.service --no-pager -l
awg2-harness --config /etc/awg2-harness/config.toml status
Проверка Docker/Amnezia runtime:
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
docker port "$C"
docker exec "$C" awg show
docker inspect -f 'ports={{json .NetworkSettings.Ports}}' amnezia-dns
Проверка AWG-контракта внутри контейнера (без раскрытия секретов):
docker exec "$C" readlink -f /usr/bin/wg # ожидается /usr/bin/awg
docker exec "$C" awg --version
docker exec "$C" ip -o link show awg0
docker exec "$C" awg show all allowed-ips
docker exec "$C" awg show all dump | awk -F '\t' '{ print "row=" NR, "fields=" NF, "interface=" $1 }'
Interface-строка awg show all dump даёт 14 полей на AWG 2.0 и 28 на AWG 3.0, peer-строки — 9. Полный вывод awg show all dump передавать нельзя: во второй колонке interface-строки находится приватный ключ устройства.
Проверка, что runtime config создан вручную (ожидаемое поведение):
test -f /etc/awg2-harness/config.toml && echo "runtime config present"
Если файл отсутствует после apt install, это корректно: создайте его вручную из /usr/share/doc/awg2-harness/repo/config.example.toml.