diff --git a/docs/ACCEPTANCE_CHECKLIST.md b/docs/ACCEPTANCE_CHECKLIST.md index 187100b..af5b806 100644 --- a/docs/ACCEPTANCE_CHECKLIST.md +++ b/docs/ACCEPTANCE_CHECKLIST.md @@ -1,6 +1,8 @@ # Чек-лист приёмки перед production-выкладкой -Исторический synthetic validation для версии 0.3.1 зафиксирован в [`VALIDATION_0.3.1.md`](VALIDATION_0.3.1.md). Он подтверждает перечисленные там проверки, но не заменяет этот production acceptance checklist. +Исторический synthetic validation и выполненный clean production acceptance версии 0.3.1 зафиксированы в [`VALIDATION_0.3.1.md`](VALIDATION_0.3.1.md). Этот checklist остаётся воспроизводимой процедурой приёмки для следующих установок. + +> Clean production acceptance release artifact `v0.3.1` выполнен 2026-08-29 на Debian 13 + AmneziaWG 3.1. Итог: PASS; production GO подтверждён. Не наблюдались только фактический scheduler-triggered reboot и повторный multi-peer load-test; anti-torrent threshold выше 500 намеренно не создавался. ## A. Базовая установка diff --git a/docs/README.md b/docs/README.md index 6481871..7efd3d5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,7 +7,7 @@ 3. [`INSTALLATION.md`](INSTALLATION.md) — сжатый порядок установки на production. 4. [`CONFIGURATION.md`](CONFIGURATION.md) — параметры `/etc/awg2-harness/config.toml`. 5. [`ACCEPTANCE_CHECKLIST.md`](ACCEPTANCE_CHECKLIST.md) — чек-лист приёмки перед статусом production-ready. -6. [`VALIDATION_0.3.1.md`](VALIDATION_0.3.1.md) — фактически выполненные Debian 13 build/package/runtime-проверки версии 0.3.1 и их ограничения. +6. [`VALIDATION_0.3.1.md`](VALIDATION_0.3.1.md) — synthetic validation и clean production acceptance release artifact `v0.3.1` на Debian 13 + AmneziaWG 3.1, включая ограничения прогона. 7. [`ANTI_TORRENT.md`](ANTI_TORRENT.md) — ограничение числа соединений через nftables. 8. [`IMPLEMENTATION_SPEC.md`](IMPLEMENTATION_SPEC.md) — архитектура и reconciliation состояния. diff --git a/docs/VALIDATION_0.3.1.md b/docs/VALIDATION_0.3.1.md index 9282fdf..fa3dbb3 100644 --- a/docs/VALIDATION_0.3.1.md +++ b/docs/VALIDATION_0.3.1.md @@ -1,6 +1,9 @@ # AWG2 Harness 0.3.1 — отчёт о валидации -Дата проверки: 2026-08-28 +Даты проверок: + +- 2026-08-28 — synthetic runtime validation; +- 2026-08-29 — clean production acceptance. ## 1. Назначение @@ -12,7 +15,8 @@ - в каком окружении выполнялись проверки; - какие свойства подтверждены реальным Linux runtime; - какие проверки были negative/fail-closed; -- какие сценарии остаются до production acceptance. +- какие сценарии оставались после synthetic-прогона; +- какие из них затем закрыты clean production acceptance. Сырой terminal dump намеренно не включён в репозиторий: в нём присутствуют public keys, container IDs и инфраструктурные детали. Ниже сохранены воспроизводимые команды, существенные наблюдения и границы результата. @@ -340,7 +344,7 @@ Conntrack count читается из Amnezia network namespace, global max — Для отдельного daemon recovery test необходимо использовать clean/owned swap state либо временно отключить `[swap]`. -## 20. Сводный результат +## 20. Сводный результат synthetic run | Контур | Статус | | --- | --- | @@ -374,7 +378,7 @@ Conntrack count читается из Amnezia network namespace, global max — | End-to-end VPN | NOT RUN | | AWG 3.1 production acceptance | NOT RUN | -## 21. Что этим test run не доказано +## 21. Что не доказал synthetic run Не проверены: @@ -390,7 +394,7 @@ Conntrack count читается из Amnezia network namespace, global max — Эти проверки остаются обязательной частью clean production AWG 3.1 acceptance. -## 22. Итог +## 22. Итог synthetic run Для полного synthetic runtime-прогона на `7390d1f` и отдельной финальной build/runtime-проверки swap delta на `3757302` подтверждены: @@ -412,6 +416,355 @@ Conntrack count читается из Amnezia network namespace, global max — **Synthetic runtime validation: PASS for tested components.** -**Production AWG 3.1 acceptance: NOT RUN.** +**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: подтверждён.**