# AWG2 Harness 0.3.1 — отчёт о валидации Даты проверок: - 2026-08-28 — synthetic runtime validation; - 2026-08-29 — clean production acceptance. ## 1. Назначение Этот документ фиксирует фактически выполненные build-, package- и runtime-проверки AWG2 Harness 0.3.1 по сохранённым локальным логам оператора. Он не заменяет [`ACCEPTANCE_CHECKLIST.md`](ACCEPTANCE_CHECKLIST.md). Его задача — сохранить доказанный на практике baseline: - какая ревизия проверялась; - в каком окружении выполнялись проверки; - какие свойства подтверждены реальным Linux runtime; - какие проверки были negative/fail-closed; - какие сценарии оставались после synthetic-прогона; - какие из них затем закрыты clean production acceptance. Сырой terminal dump намеренно не включён в репозиторий: в нём присутствуют public keys, container IDs и инфраструктурные детали. Ниже сохранены воспроизводимые команды, существенные наблюдения и границы результата. ## 2. Проверенные ревизии Полный synthetic runtime-прогон выполнен для базовой ревизии: `7390d1fa2c0710cb189897728e1bc1bfed9fbc53` Финальная ревизия с изменениями production-кода, прошедшая повторный Linux build/package gate: `37573022c2ca56480e99bf7515dca1c68254690e` Версия пакета: `awg2-harness 0.3.1` Production delta между этими ревизиями затронул только `traffic_core/src/swap/runtime.rs`: вызов `swapon` переведён на документированную форму `--show=NAME,TYPE,SIZE,PRIO`. Изменение отдельно закрыто regression-тестом и smoke-тестом на реальном util-linux 2.41.5. Таким образом, разделы с полным synthetic runtime относятся к `7390d1f`, а build/package и `swapon` runtime-проверки после этого исправления — к `3757302`. ## 3. Окружение Build/runtime host: - Debian 13 amd64; - Linux `6.12.101+deb13-amd64`; - Rust `1.95.0`; - Cargo `1.95.0`; - ShellCheck `0.10.0`; - util-linux `2.41.5`. Synthetic runtime выполнялся на существующем контейнере AmneziaWG 2.0. Контейнер использовался как локальный runtime fixture. Внешний VPN dataplane на сервере не являлся рабочим из-за известной внешней конфигурационной проблемы, не связанной с AWG2 Harness. Поэтому этот test run не является end-to-end acceptance AWG 3.1. ## 4. Build gate и упаковка Для ревизии `3757302` команда `tools/build.sh --package` успешно выполнила обязательные gates: - `cargo fmt --check`; - `cargo clippy --locked --workspace --all-targets -- -D warnings`; - release tests; - release build; - Cargo locked metadata validation; - ShellCheck; - проверку release-бинарников; - Debian package assembly; - package metadata/content checks; - создание SHA256 manifest. Linux release tests: - `awg2-harness`: 251 passed; - `awg2-reboot-scheduler`: 4 passed; - failures: 0. Собран пакет: `awg2-harness_0.3.1_amd64.deb` Подтверждено: - package metadata: версия `0.3.1`, архитектура `amd64`; - оба binary устанавливаются и выполняют `--help`; - systemd units проходят `systemd-analyze verify`; - production `config.toml` не создаётся автоматически; - после clean package state оба сервиса остаются disabled/inactive до явного включения оператором; - `dist/SHA256SUMS` успешно проверяет пакет на builder. Runtime config создаётся только вручную из `config.example.toml`. ## 5. Целостность перенесённого артефакта Для пакета, собранного из `3757302` до добавления этого отчёта, Windows вычислил SHA-256: `9ffcc8f84e01ddf5b365d37d99c3efdbe0a130aa2017ba63476697bdaa216c4c` Это значение полностью совпало с записью в созданном на builder файле `SHA256SUMS`. Регистр шестнадцатеричных символов на значение digest не влияет. Результат: перенос `.deb` через `scp` не повредил артефакт. Документы `docs/*.md` входят в `.deb`, поэтому package, пересобранный после добавления этого отчёта, закономерно получит другой SHA-256. Его checksum должен проверяться по новому `SHA256SUMS`; изменение package hash само по себе не означает изменение бинарников. ## 6. Реальный smoke-тест `swapon` На Debian 13 с util-linux 2.41.5 выполнен новый документированный вызов: ```bash swapon --show=NAME,TYPE,SIZE,PRIO --bytes --raw --noheadings ``` Он успешно вернул ожидаемые четыре поля. После переустановки пакета команда `status` также успешно прочитала active swap, а foreign-swap fail-closed сохранился. Результат: PASS. Исправление проверено не только unit/regression-тестом, но и реальным Debian runtime. Для расширенной ручной диагностики использовалась форма: ```bash swapon --show=NAME,TYPE,SIZE,USED,PRIO,UUID ``` ## 7. AWG discovery и topology parser На реальном AmneziaWG 2.0 runtime успешно обнаружены: - container; - network namespace; - interface `awg0`; - 28 server-side peers. Все server peer routes были корректно распознаны как IPv4 `/32`. Это подтверждает работоспособность production parser не только на unit fixtures, но и на реальном выводе AWG. Поддерживаемый harness topology остаётся IPv4-only `/32`. Результат: PASS. ## 8. Legacy traffic topology — fail-closed ownership Перед применением 0.3.1 в network namespace существовала topology старой версии: - root HTB на `awg0`; - `ifb0`; - per-peer HTB classes; - `fq_codel`; - legacy per-peer `u32` filters; - peer limit 60 Mbit/s. Legacy `ifb0` не имел ownership marker: `alias awg2-harness:traffic` Команда `apply-limits` отказалась удалять такой IFB с ошибкой `refusing to delete unowned IFB`. Результат: PASS. Это подтверждает safety invariant: существования интерфейса с подходящими именем и типом недостаточно для destructive cleanup; требуется explicit ownership marker. ## 9. Traffic topology 0.3.1 После ручного удаления legacy topology `apply-limits` успешно создал новую topology. Повторный `apply-limits` завершился без ошибки и не изменил healthy state. Подтверждено: - `ifb0` создан с alias `awg2-harness:traffic`; - egress root: HTB; - ingress redirect присутствует; - IFB root: HTB; - root rate: 500 Mbit/s; - peer rate: 50 Mbit/s; - peer ceil: 50 Mbit/s; - `rate == ceil` для всех peers; - leaf qdisc: `fq_codel`; - egress per-peer filters: `flower pref 10`, `dst_ip /32`; - ingress per-peer filters: `flower pref 10`, `src_ip /32`. После reconciliation `status` сообщил `Traffic actual: drift: no` для всех 28 peers. Результат: PASS. ## 10. Ingress redirect На ingress `awg0` реально присутствовал единственный catch-all `u32` filter с действием: `mirred Egress Redirect to device ifb0` Таким образом, design contract сохранён: - `u32` используется только для ingress redirect; - per-peer classification выполняется через `flower`. Результат: PASS. ## 11. Peer traffic counters Для peer `10.8.1.2` использовался HTB class `1:21`. Перед дополнительной генерацией трафика: - 20 packets; - 1680 bytes. После ещё 20 ICMP packets: - 40 packets; - 3360 bytes. `status` также показал для `10.8.1.2` значение `Egress packets = 40`. Результат: PASS. Это подтверждает, что peer counters читаются из фактических HTB class statistics. Отсутствие ICMP reply не является ошибкой harness: внешний VPN dataplane тестового AWG был нерабочим. ## 12. Host firewall IPv4 и IPv6 проверены отдельно. В обоих случаях harness установил единственный owned jump: `awg2-harness:host-firewall -> AWG2H_A` Managed chain содержит: - loopback ACCEPT; - RELATED/ESTABLISHED ACCEPT; - TCP/2323 ACCEPT; - ICMP или IPv6-ICMP ACCEPT; - terminal DROP. Built-in INPUT policy при этом остаётся `ACCEPT`. Это ожидаемая архитектура: политика `input_policy = "drop"` реализуется terminal DROP внутри owned managed chain, а не изменением глобальной policy чужой INPUT chain. После применения `Host firewall: drift: no`. Результат: PASS. ## 13. Docker / AWG UDP port contract При `expected_host_udp_port = 2053` runtime сообщил: - Docker published UDP: 2053; - AWG listen UDP: 2053; - host IPv4 binding: `0.0.0.0:2053`; - host IPv6 binding: `[::]:2053`; - `port_contract: ok`. Наличие host IPv6 Docker publication не означает поддержку IPv6 server-peer topology внутри AWG tunnel. Результат: PASS. ## 14. Anti-torrent guard Anti-torrent guard был применён повторно без ошибки. В Amnezia network namespace подтверждены: - harness-owned nftables table; - IPv4 dynamic set; - peer CIDR `10.8.1.0/24`; - `ct state new`; - threshold `ct count over 500`; - named drop counter. После применения `Anti-torrent: drift: no`. Conntrack count читается из Amnezia network namespace, global max — с host. Результат: PASS. ## 15. Network tuning и BBR-off policy До reconcile присутствовал drift от старого persisted state. После `apply-network-tuning` получено: - persisted sysctl matches desired state; - obsolete harness BBR modules-load file отсутствует; - `rmem_max = 67108864`; - `wmem_max = 67108864`; - `ip_forward = 1`; - `drift: no`. Тестовый host уже имел runtime `net.ipv4.tcp_congestion_control = bbr` при конфигурации `tcp_bbr = "off"`. После reconcile runtime BBR остался активным, одновременно status сообщил: - `bbr_desired: no`; - `bbr_runtime_active: yes`; - `drift: no`. Это ожидаемый policy contract. `off` означает, что harness не требует и не персистит BBR. Он не выполняет принудительное переключение существующего host TCP congestion control на другой алгоритм. Результат: PASS. ## 16. IFB IPv6 observation После создания IFB kernel автоматически назначил link-local IPv6 `fe80::/64` и соответствующий link-local route. На IFB наблюдалось несколько direct packets. На peer IPv4 path признаков обхода HTB не обнаружено: egress peer class counters корректно увеличивались при IPv4 traffic. Эта проверка не заменяет production throughput test. ## 17. Swap — foreign ownership safety На test host уже существовал `/swapfile` и запись в `/etc/fstab`, но ownership record новой версии harness отсутствовал. `ensure-swap` дважды отказался изменять файл: `/swapfile already exists and there is no record of awg2-harness creating it; refusing to touch it` Результат: PASS для fail-closed ownership. Подтверждено, что harness не усыновляет и не изменяет произвольный существующий swapfile только по совпадению path. После исправления argv `swapon` эта защита повторно проверена на ревизии `3757302` и сохранилась. Положительный сценарий создания нового owned swapfile, resize/replacement и rollback в этом test run не выполнялся. Он остаётся частью clean-host production acceptance. ## 18. Reboot scheduler `awg2-reboot-scheduler.service` успешно: - стартовал; - прочитал production-format config; - выбрал случайный reboot timestamp внутри окна `01:00–02:00 UTC`; - оставался active; - штатно остановился по `systemctl stop`. Результат: PASS. Фактическая перезагрузка в рамках этого synthetic test намеренно не ожидалась. ## 19. Daemon startup и periodic recovery Попытка запуска `awg2-harness.service` завершилась fail-closed на startup swap reconcile, поскольку существующий `/swapfile` не принадлежал текущему harness. Это ожидаемая защитная реакция, а не ошибка traffic reconciliation. Из-за завершения daemon последующий intentional deletion root HTB не мог быть автоматически восстановлен. Статус: `daemon periodic drift recovery: NOT RUN` Причина: `BLOCKED BY EXPECTED FOREIGN-SWAP OWNERSHIP FAILURE` Для отдельного daemon recovery test необходимо использовать clean/owned swap state либо временно отключить `[swap]`. ## 20. Сводный результат synthetic run | Контур | Статус | | --- | --- | | Debian 13 build gate | PASS | | `.deb` packaging | PASS | | Artifact transfer integrity | PASS | | Config validation | PASS | | AWG runtime discovery | PASS | | AWG 2.0 peer parser | PASS | | IPv4 `/32` topology | PASS | | Foreign IFB fail-closed | PASS | | HTB creation | PASS | | `rate == ceil` | PASS | | `fq_codel` leaves | PASS | | `flower pref 10` | PASS | | ingress `u32 -> mirred -> IFB` | PASS | | HTB peer counters | PASS | | repeated `apply-limits` | PASS | | IPv4 host firewall | PASS | | IPv6 host firewall | PASS | | Docker/AWG UDP contract | PASS | | Anti-torrent / conntrack | PASS | | Network tuning | PASS | | BBR-off policy semantics | PASS | | Documented `swapon` argv on util-linux 2.41.5 | PASS | | Foreign swap protection | PASS | | Reboot scheduler | PASS | | Daemon periodic self-healing | NOT RUN | | Owned swap create/resize | NOT RUN | | Actual 50 Mbit throughput cap | NOT RUN | | End-to-end VPN | NOT RUN | | AWG 3.1 production acceptance | NOT RUN | ## 21. Что не доказал synthetic run Не проверены: - реальная пропускная способность peer под длительной нагрузкой; - фактический hard cap около 50 Mbit/s на живом VPN client; - simultaneous multi-peer fairness/latency; - bidirectional ingress load; - полноценный AWG handshake; - end-to-end VPN connectivity; - production AWG 3.1 runtime; - positive swap create/resize/replacement path; - periodic daemon self-healing. Эти проверки остаются обязательной частью clean production AWG 3.1 acceptance. ## 22. Итог synthetic run Для полного synthetic runtime-прогона на `7390d1f` и отдельной финальной build/runtime-проверки swap delta на `3757302` подтверждены: - Debian 13 build/package viability; - целостность передачи собранного артефакта; - AWG runtime discovery; - IPv4 peer topology parser; - ownership fail-closed; - HTB/fq_codel/flower traffic topology; - ingress IFB redirect; - peer HTB counters; - IPv4/IPv6 host firewall; - Docker/AWG UDP port contract; - nftables anti-torrent guard; - network tuning reconciliation; - reboot scheduler; - документированный `swapon` argv на реальном util-linux 2.41.5; - foreign swap protection после исправления. **Synthetic runtime validation: PASS for tested components.** **Production AWG 3.1 acceptance в этом synthetic run: NOT RUN.** Окончательный production GO требует выполнения [`ACCEPTANCE_CHECKLIST.md`](ACCEPTANCE_CHECKLIST.md) на clean Debian 13 host с рабочим AWG 3.1 и реальным client traffic. Требуемый clean production acceptance был выполнен 2026-08-29; результаты приведены в следующем разделе. ## 23. Clean production acceptance — Debian 13 / AmneziaWG 3.1 Дата проверки: 2026-08-29 Проверенный release artifact: - tag: `v0.3.1`; - package: `awg2-harness_0.3.1_amd64.deb`; - SHA256: `90dc8bb85f60740ca3358e40c31592b5165e250f878169ad6d05bdee3656f1b8`. Проверка выполнена после публикации релиза. Этот раздел фиксирует post-release evidence и не изменяет tag или опубликованный artifact `v0.3.1`. ### 23.1. Окружение - Debian GNU/Linux 13.6 (trixie); - amd64; - kernel: `6.12.105+deb13-amd64`; - Docker: `26.1.5+dfsg1`; - container: `amnezia-awg2`; - AmneziaWG tools: `v3.1.20260812`; - AWG interface: `awg0`; - AWG peer CIDR: `10.8.1.0/24`; - server peer `AllowedIPs`: IPv4 `/32`; - host UDP port: `2053`; - SSH port: `2323`. Production limits: - per-peer limit: `60mbit`; - root rate: `600mbit`; - anti-torrent connection limit: `500` per peer. ### 23.2. Clean installation До установки AWG2 Harness: - `/etc/awg2-harness` отсутствовал; - harness iptables/ip6tables rules отсутствовали; - harness nftables table отсутствовала; - `ifb0` отсутствовал; - swap отсутствовал; - harness sysctl persistence files отсутствовали. Установка release package завершилась успешно. После установки: - production config автоматически не создавался; - `awg2-harness.service` был `disabled/inactive`; - `awg2-reboot-scheduler.service` был `disabled/inactive`. Результат: PASS. ### 23.3. AmneziaWG 3.1 discovery Runtime discovery определил: - container `amnezia-awg2`; - interface `awg0`; - listen port `2053`; - peer `10.8.1.1/32`. `validate-config` и `validate-runtime` завершились успешно. Docker UDP contract: - `0.0.0.0:2053`; - `[::]:2053`; - inner AWG listen port `2053`; - `port_contract: ok`. Результат: PASS. ### 23.4. Swap — clean positive path На исходном сервере active swap отсутствовал. `ensure-swap` создал managed `/swapfile`: - size: 2048 MiB; - mode: `0600`; - priority: `1`; - `/etc/fstab`: `/swapfile none swap sw,pri=1 0 0`; - `vm.swappiness = 1`; - ownership record создан; - `status`: `drift: no`. Повторный `ensure-swap` сохранил тот же inode, размер и содержимое `/etc/fstab`. Результат: PASS. ### 23.5. Network tuning До reconciliation: - `net.core.rmem_max = 212992`; - `net.core.wmem_max = 212992`; - `net.ipv4.ip_forward = 1`; - congestion control: `cubic`. После `apply-network-tuning`: - `net.core.rmem_max = 67108864`; - `net.core.wmem_max = 67108864`; - `net.ipv4.ip_forward = 1`; - persisted config совпадает с desired state; - `tcp_bbr = "off"` не включает и не персистит BBR; - runtime congestion control остался `cubic`; - `drift: no`. Результат: PASS. ### 23.6. Traffic shaping — clean AWG 3.1 На исходном `awg0` присутствовал только штатный root `fq_codel`. `ifb0`, HTB classes и peer filters отсутствовали. Первый `apply-limits` построил managed topology. Повторный `apply-limits` был идемпотентным. Получено: - egress HTB root: `600Mbit`; - ingress IFB HTB root: `600Mbit`; - peer `10.8.1.1`: - egress: `60Mbit/60Mbit`; - ingress: `60Mbit/60Mbit`; - per-peer egress filter: `flower pref 10`, destination peer IPv4; - per-peer ingress filter: `flower pref 10`, source peer IPv4; - AWG ingress redirect: `u32 -> mirred -> ifb0`; - IFB alias: `awg2-harness:traffic`; - leaf qdisc: `fq_codel`; - `status`: `drift: no`. Результат: PASS. ### 23.7. Live peer and traffic classification После подключения реального AmneziaWG 3.1 клиента: - peer определён как `online`; - endpoint определён; - latest handshake корректно читается; - AWG RX/TX корректно читаются; - egress class counter растёт; - ingress class counter растёт. `direct_packets_stat` не рос пропорционально пользовательской нагрузке; IPv4 peer traffic проходил через managed peer classes. Результат: PASS. ### 23.8. Real bandwidth enforcement Speedtest через реального клиента: - configured peer ceiling: `60 Mbit/s`; - download: `57.81 Mbit/s`; - upload: `55.26 Mbit/s`. Во время нагрузки: - egress и ingress peer counters существенно выросли; - HTB `overlimits` существенно выросли; - topology сохранила `drift: no`. Результат: PASS. ### 23.9. Host firewall Применены managed IPv4 и IPv6 INPUT chains. Разрешены: - loopback; - ESTABLISHED/RELATED; - TCP `2323`; - ICMP / IPv6 ICMP. Завершающее действие owned chain — DROP. Built-in INPUT policy не изменялась. Docker-managed FORWARD rules harness не изменял. После применения подтверждены: - новая SSH-сессия на TCP/2323; - новый AWG handshake; - работающий VPN dataplane; - `Host firewall: drift: no`; - `port_contract: ok`. Результат: PASS. ### 23.10. Anti-torrent guard В AWG network namespace создана `table inet awg2_harness`. Production rule использует: - peer CIDR `10.8.1.0/24`; - `ct state new`; - dynamic IPv4 set; - `ct count over 500`; - named drop counter; - terminal drop. Inspector: - enabled: true; - max_connections_per_peer: 500; - `drift: no`. Threshold load-test выше 500 соединений на production намеренно не выполнялся. Результат: PASS для control-plane и production configuration. ### 23.11. Daemon startup and self-healing После включения `awg2-harness.service`: - service: active; - startup network tuning reconcile: ok; - startup swap reconcile: ok; - startup traffic reconcile: ok; - startup firewall reconcile: ok. Для проверки periodic self-healing вручную удалён root HTB qdisc на `awg0`. Сразу после удаления inspector зарегистрировал: `missing egress root htb qdisc` Через следующий daemon reconciliation root HTB был автоматически восстановлен, peer classes и filters появились снова, `Traffic actual: drift: no`. Результат: PASS. ### 23.12. Reboot scheduler `awg2-reboot-scheduler.service`: - enabled; - active; - планирует reboot внутри configured UTC window `01:00–02:00`. Пример после production reboot: `planned_reboot_utc=2026-08-30T01:00:38Z` Фактического ожидания scheduler-triggered reboot в этом validation run не выполнялось. Результат: PASS для startup/planning. ### 23.13. Reboot recovery Выполнен ручной reboot production host. После загрузки: - Docker active; - `amnezia-awg2` active; - `awg2-harness.service` active; - `awg2-reboot-scheduler.service` active; - swap active с тем же UUID, размером 2 GiB и priority 1; - network tuning: `drift: no`; - traffic topology: `drift: no`; - host firewall: `drift: no`; - anti-torrent: `drift: no`; - Docker/AWG UDP contract: `ok`. AWG client автоматически выполнил новый handshake после reboot, peer определён как `online`, traffic counters росли. Результат: PASS. ### 23.14. Наблюдение за Docker FORWARD state До reboot `status` показывал `host_forward_policy_drop: true`, после reboot — `false`. При этом `docker_forward_rules_present: true`, VPN dataplane после reboot работал, а `port_contract` оставался `ok`. Harness по контракту не управляет built-in FORWARD policy и Docker-managed FORWARD rules. Наблюдаемое изменение host state после reboot не классифицируется как drift или regression AWG2 Harness. ### 23.15. Сводный результат clean production acceptance | Контур | Статус | | --- | --- | | Debian 13 clean host | PASS | | Release `.deb` + SHA256 | PASS | | Clean package installation | PASS | | AWG 3.1 discovery | PASS | | AWG 3.1 real dataplane | PASS | | UDP 2053 contract | PASS | | Owned swap creation | PASS | | Swap persistence / idempotence | PASS | | Network tuning | PASS | | HTB 600 Mbit root | PASS | | 60 Mbit per-peer egress | PASS | | 60 Mbit per-peer ingress | PASS | | Flower classification | PASS | | IFB ingress | PASS | | `fq_codel` | PASS | | No material direct bypass | PASS | | Real download: 57.81 Mbps | PASS | | Real upload: 55.26 Mbps | PASS | | IPv4 host firewall | PASS | | IPv6 host firewall | PASS | | New SSH through firewall | PASS | | New AWG handshake through firewall | PASS | | Docker forwarding preserved | PASS | | Anti-torrent / `ct count over 500` configuration | PASS | | Anti-torrent inspection | PASS | | Daemon startup | PASS | | Startup reconciliation | PASS | | Periodic self-healing | PASS | | Manual drift recovery | PASS | | Service enablement | PASS | | Manual reboot recovery | PASS | | Post-reboot AWG handshake | PASS | | Post-reboot traffic shaping | PASS | | Post-reboot firewall | PASS | | Post-reboot anti-torrent | PASS | | Post-reboot swap | PASS | | Post-reboot network tuning | PASS | | Reboot scheduler startup/planning | PASS | | Actual scheduled-time reboot | NOT OBSERVED | | Multi-peer production load | NOT RE-RUN | Production-critical функции, проверенные на реальном сервере: - package installation; - runtime discovery; - swap lifecycle; - network tuning; - per-peer bidirectional shaping; - real 60 Mbit/s enforcement; - host firewall; - Docker/AWG port contract; - anti-torrent control-plane; - daemon startup reconciliation; - periodic drift self-healing; - reboot persistence and recovery; - reboot scheduler startup/planning. Ограничения текущего validation: - scheduler-triggered reboot не ожидался до фактического времени; - multi-peer production load-test отдельно не повторялся; - anti-torrent threshold выше 500 не создавался искусственно. Эти ограничения зафиксированы как непроверенные сценарии и не признаны blockers для перевода пользователей на сервер: запуск и планирование scheduler проверены, обычный reboot и полное восстановление системы проверены отдельно. **Clean production acceptance: PASS.** **Production GO: подтверждён.**