404 lines
26 KiB
Markdown
404 lines
26 KiB
Markdown
# AWG2 Harness
|
||
|
||
`AWG2 Harness` — host-side orchestrator для выделенного Debian-хоста с self-hosted AmneziaWG. Основной target релиза 0.3.1 — AmneziaWG 3.1; AWG 3.0/2.x сохраняются как regression compatibility. Пакет управляет инфраструктурным состоянием вокруг Amnezia: per-peer traffic shaping, IFB ingress shaping, Docker-совместимый host firewall через `iptables`/`ip6tables`, nftables anti-torrent guard, managed swap, диагностикой drift и плановым reboot.
|
||
|
||
Релиз source-validated по официальной документации и исходникам AWG 3.1; фактическая live-приёмка выполняется после production deployment. Harness не заменяет AmneziaVPN, не генерирует ключи клиентов и не мигрирует AWG 2.0 на 3.1. Amnezia сначала ставится официальным способом, после этого устанавливается AWG2 Harness. Точная upstream-база зафиксирована в [`docs/UPSTREAM_COMPATIBILITY.md`](docs/UPSTREAM_COMPATIBILITY.md).
|
||
|
||
## Что ставит пакет
|
||
|
||
```text
|
||
/usr/sbin/awg2-harness # основной orchestrator
|
||
/usr/sbin/awg2-reboot-scheduler # отдельный reboot scheduler
|
||
/lib/systemd/system/awg2-harness.service
|
||
/lib/systemd/system/awg2-reboot-scheduler.service
|
||
```
|
||
|
||
`awg2-harness.service` запускает только daemon; `ensure-swap` выполняется первым этапом его собственной startup-последовательности, а не отдельным `ExecStartPre`. Дальше daemon в фоне держит drift recovery. Daemon слушает Docker events и дополнительно делает периодический reconcile для `traffic`/`firewall`/`swap`; `sysctl_tuning` применяется только на старте daemon (если включён) или вручную отдельной командой. `awg2-reboot-scheduler.service` отдельно читает общий config, выбирает случайное время в заданном UTC-окне и запрашивает reboot через `systemctl --no-block reboot`.
|
||
|
||
Пакет **не** устанавливает Docker, **не** устанавливает AmneziaVPN, **не** включает сервисы автоматически и **не** создаёт боевой `/etc/awg2-harness/config.toml`. Это сделано намеренно: SSH, Amnezia и боевой config должны быть подготовлены оператором до включения firewall/reconcile.
|
||
|
||
## Репозиторий
|
||
|
||
```text
|
||
awg2_harness/
|
||
├── reboot_module/ # исходники awg2-reboot-scheduler
|
||
├── traffic_core/ # исходники awg2-harness
|
||
├── tools/ # build/package tooling
|
||
├── docs/ # эксплуатационная документация
|
||
├── config.example.toml # пример боевого конфига
|
||
├── awg2-harness.service # основной systemd unit
|
||
└── awg2-reboot-scheduler.service # reboot scheduler unit
|
||
```
|
||
|
||
## Runtime-план production-развёртывания
|
||
|
||
Ниже целевой порядок установки. Его смысл простой: сначала безопасный SSH, потом официальная Amnezia, потом AWG2 Harness.
|
||
|
||
### 1. Подготовить Debian-хост
|
||
|
||
Целевая платформа AWG2 Harness — только Debian 13 amd64 на KVM/полноценной VM или dedicated host.
|
||
|
||
Минимальный baseline перед установкой Amnezia:
|
||
|
||
```bash
|
||
apt update
|
||
apt install -y openssh-server ca-certificates curl
|
||
timedatectl set-timezone Etc/UTC
|
||
```
|
||
|
||
### 2. Настроить SSH до установки Amnezia
|
||
|
||
Production-пример использует порт `2323` и вход только по ключу.
|
||
|
||
Сгенерируйте отдельную пару ключей для Amnezia на Windows (RSA PEM-формат):
|
||
|
||
```cmd
|
||
ssh-keygen -t rsa -b 4096 -m PEM -f %USERPROFILE%\.ssh\amnezia_key
|
||
```
|
||
|
||
Дальше контракт строго такой:
|
||
|
||
- на сервер добавляется **публичный** ключ: содержимое `%USERPROFILE%\.ssh\amnezia_key.pub` в `/root/.ssh/authorized_keys`;
|
||
- в приложении AmneziaVPN в поле **Password or SSH private key** вставляется **приватный** ключ: содержимое `%USERPROFILE%\.ssh\amnezia_key` (без `.pub`).
|
||
|
||
Критично: `.pub` никогда не вставляется в AmneziaVPN как private key.
|
||
|
||
```bash
|
||
install -d -m 0700 /root/.ssh
|
||
nano /root/.ssh/authorized_keys
|
||
chmod 0600 /root/.ssh/authorized_keys
|
||
```
|
||
|
||
Затем включите отдельный drop-in для порта и key-only login:
|
||
|
||
```bash
|
||
install -d -m 0755 /etc/ssh/sshd_config.d
|
||
cat >/etc/ssh/sshd_config.d/99-awg2-production.conf <<'EOF'
|
||
Port 2323
|
||
PermitRootLogin prohibit-password
|
||
PasswordAuthentication no
|
||
KbdInteractiveAuthentication no
|
||
PubkeyAuthentication yes
|
||
EOF
|
||
|
||
sshd -t
|
||
systemctl reload ssh 2>/dev/null || systemctl reload sshd
|
||
ss -ltnp | grep ':2323'
|
||
```
|
||
|
||
Критично: не закрывайте старую SSH-сессию, пока не проверили новый вход с другого терминала:
|
||
|
||
```bash
|
||
ssh -i ~/.ssh/amnezia_key -p 2323 root@<server-ip>
|
||
```
|
||
|
||
Windows-проверки:
|
||
|
||
```cmd
|
||
type %USERPROFILE%\.ssh\amnezia_key.pub
|
||
type %USERPROFILE%\.ssh\amnezia_key
|
||
ssh -i %USERPROFILE%\.ssh\amnezia_key -p 2323 root@<server-ip>
|
||
```
|
||
|
||
Поля в интерфейсе AmneziaVPN:
|
||
|
||
```text
|
||
Server IP address [:port] <server-ip>:2323
|
||
SSH Username root
|
||
Password or SSH private key содержимое %USERPROFILE%\.ssh\amnezia_key
|
||
На сервер содержимое %USERPROFILE%\.ssh\amnezia_key.pub в /root/.ssh/authorized_keys
|
||
```
|
||
|
||
Если сервер уже переведён на 2323 случайно и нужно временно вернуть 22 для тестов, поменяйте `Port 2323` на `Port 22`, выполните `sshd -t`, `systemctl reload ssh` и проверьте `ss -ltnp | grep ':22'`.
|
||
|
||
### 3. Установить AmneziaVPN официальным способом
|
||
|
||
AWG2 Harness не устанавливает Amnezia. Используйте официальный self-hosted flow AmneziaVPN:
|
||
|
||
1. Установите актуальное приложение AmneziaVPN на рабочую машину.
|
||
2. В приложении выберите self-hosted server.
|
||
3. Укажите публичный IPv4 сервера, SSH-порт, SSH-пользователя и приватный ключ.
|
||
4. Установите AmneziaWG 3.1. Для self-hosted deployment требуется AmneziaVPN 5.0.1.5 или новее.
|
||
5. После установки убедитесь, что контейнер поднят и UDP-порт опубликован.
|
||
|
||
Проверка на сервере:
|
||
|
||
```bash
|
||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||
echo "container=$C"
|
||
docker port "$C"
|
||
docker exec "$C" awg show
|
||
```
|
||
|
||
Ожидаемые имена контейнера по умолчанию: основной `amnezia-awg2`, затем legacy fallback `amnezia-awg`. Ожидаемый интерфейс внутри container netns — `awg0`; дополнительные fallback-кандидаты описаны в `config.example.toml`. Любое другое корректное имя можно указать вручную в config.
|
||
|
||
### Совместимость с AmneziaWG 3.1
|
||
|
||
Канонические версии, commit SHA и официальные ссылки приведены в [`docs/UPSTREAM_COMPATIBILITY.md`](docs/UPSTREAM_COMPATIBILITY.md). Релиз 0.3.1 source-validated against AWG 3.1; до отдельной live-приёмки это не означает «протестировано на production AWG 3.1».
|
||
|
||
Обвязка не реализует AWG на уровне пакетов: `tc`, IFB и `nftables` работают с inner-IP уже после декапсуляции, поэтому header protection, content padding, RandomTrailers и DisableCookies её не касаются.
|
||
|
||
Peer state читается через `docker exec` официальным `awg` внутри контейнера; `/usr/bin/wg` в reference image является symlink на него. Это единая container-side точка доступа независимо от того, использован kernel `amneziawg` или fallback `amneziawg-go`, и она не привязывает harness к host-side tools. Порядок задаётся `amnezia.wg_binaries` (по умолчанию `["awg", "wg"]`); host `wireguard-tools` не требуется.
|
||
|
||
Smoke-проверка после обновления контейнера:
|
||
|
||
```bash
|
||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||
|
||
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" ip -d link show awg0
|
||
docker exec "$C" awg show all allowed-ips
|
||
docker port "$C"
|
||
|
||
# Структура dump без раскрытия значений:
|
||
docker exec "$C" awg show all dump | awk -F '\t' '{ print "row=" NR, "fields=" NF, "interface=" $1 }'
|
||
```
|
||
|
||
Для reference tools AWG 3.1 ожидаемо: `/usr/bin/wg` указывает на `/usr/bin/awg`, интерфейс `awg0` существует, peer-адреса отображаются, серверный порт опубликован по UDP, interface-row содержит 30 полей, peer-row — 9.
|
||
|
||
Исторически WireGuard/AWG 2.x/AWG 3.0/AWG 3.1 tools печатают interface-row шириной 5/14/28/30 полей соответственно; текущий peer-row содержит 9. Это только диагностика: ширина зависит от producer tools, а не от версии параметров туннеля. По количеству колонок harness не определяет версию и не классифицирует peer.
|
||
|
||
Полный вывод `awg show all dump` передавать нельзя: во второй колонке interface-строки находится приватный ключ устройства.
|
||
|
||
### 3.1 Установить AmneziaDNS (обязательный production-шаг)
|
||
|
||
Для production-профиля AWG 3.1 установите AmneziaDNS из приложения AmneziaVPN после установки AmneziaWG:
|
||
|
||
```text
|
||
AmneziaVPN:
|
||
Servers → <server> → Services → AmneziaDNS → Install
|
||
```
|
||
|
||
Затем включите использование DNS для подключения:
|
||
|
||
```text
|
||
Settings → Connection → DNS servers → Use AmneziaDNS
|
||
```
|
||
|
||
Security note:
|
||
|
||
В ожидаемой production-схеме AmneziaDNS слушает `53/tcp` и `53/udp` внутри Docker и не публикуется на host interface. Не открывайте публично `53/tcp` или `53/udp` в host firewall; DNS должен быть доступен только через VPN-path.
|
||
|
||
### 4. Собрать пакет на build-machine
|
||
|
||
На production-хосте не нужны Rust, cargo и source tree. Сборка делается отдельно.
|
||
|
||
```bash
|
||
cd awg2_harness
|
||
./tools/build.sh --prepare-build-env --bootstrap-rust --yes
|
||
./tools/build.sh --package
|
||
(cd dist && sha256sum -c SHA256SUMS)
|
||
dpkg-deb -I dist/awg2-harness_0.3.1_amd64.deb
|
||
dpkg-deb -c dist/awg2-harness_0.3.1_amd64.deb | sort
|
||
```
|
||
|
||
Release package берёт версию из `traffic_core/Cargo.toml`. `--version` предназначен только для осознанного Debian packaging override и не меняет версию crate.
|
||
|
||
### 5. Перенести `.deb` и config на production
|
||
|
||
Есть два production-сценария установки.
|
||
|
||
#### Вариант A: config передаётся вместе с `.deb`
|
||
|
||
```bash
|
||
scp -P 2323 dist/awg2-harness_*_amd64.deb root@<server-ip>:/root/
|
||
scp -P 2323 dist/SHA256SUMS root@<server-ip>:/root/
|
||
scp -P 2323 config.example.toml root@<server-ip>:/root/awg2-harness.config.toml
|
||
```
|
||
|
||
Перед установкой отредактируйте `/root/awg2-harness.config.toml`: SSH-порт должен совпадать с реальным sshd, `amnezia.expected_host_udp_port` — с опубликованным Docker UDP-портом, `peer_ipv4_cidr` — с подсетью клиентов Amnezia. Это поле используется для диагностики и не создаёт host INPUT allow-rule: published bridge traffic проходит через Docker `FORWARD`/NAT path.
|
||
|
||
#### Вариант B (основной): config создаётся после установки пакета
|
||
|
||
```bash
|
||
scp -P 2323 dist/awg2-harness_*_amd64.deb root@<server-ip>:/root/
|
||
scp -P 2323 dist/SHA256SUMS root@<server-ip>:/root/
|
||
```
|
||
|
||
### 6. Установить пакет и config
|
||
|
||
Вариант A:
|
||
|
||
```bash
|
||
cd /root
|
||
sha256sum -c SHA256SUMS
|
||
chmod 644 /root/awg2-harness_0.3.1_amd64.deb
|
||
apt install ./awg2-harness_*_amd64.deb
|
||
install -d -m 0755 /etc/awg2-harness
|
||
install -m 0644 /root/awg2-harness.config.toml /etc/awg2-harness/config.toml
|
||
```
|
||
|
||
Пакет ставит пример config в `/usr/share/doc/awg2-harness/repo/config.example.toml`, но не копирует его в `/etc` автоматически.
|
||
|
||
Вариант B (основной):
|
||
|
||
```bash
|
||
cd /root
|
||
sha256sum -c SHA256SUMS
|
||
chmod 644 /root/awg2-harness_0.3.1_amd64.deb
|
||
apt install ./awg2-harness_*_amd64.deb
|
||
install -d -m 0755 /etc/awg2-harness
|
||
cp /usr/share/doc/awg2-harness/repo/config.example.toml /etc/awg2-harness/config.toml
|
||
nano /etc/awg2-harness/config.toml
|
||
```
|
||
|
||
В варианте B после `cp` обязательно проверьте перед первым `apply-firewall`:
|
||
|
||
- `host_firewall.ssh_port` совпадает с реальным sshd-портом;
|
||
- `amnezia.expected_host_udp_port` совпадает с published Docker UDP port;
|
||
- `amnezia.peer_ipv4_cidr` и `anti_torrent.peer_ipv4_cidr` совпадают с реальной peer-подсетью.
|
||
|
||
### 7. Ручная preflight-проверка
|
||
|
||
```bash
|
||
awg2-harness --config /etc/awg2-harness/config.toml validate-config
|
||
awg2-harness --config /etc/awg2-harness/config.toml validate-runtime
|
||
awg2-harness --config /etc/awg2-harness/config.toml ensure-swap
|
||
awg2-harness --config /etc/awg2-harness/config.toml apply-firewall
|
||
awg2-harness --config /etc/awg2-harness/config.toml apply-limits
|
||
awg2-harness --config /etc/awg2-harness/config.toml status
|
||
```
|
||
|
||
Ожидаемый healthy state:
|
||
|
||
```text
|
||
System:
|
||
service: inactive # до enable --now нормально
|
||
Traffic actual:
|
||
drift: no
|
||
Host firewall:
|
||
drift: no
|
||
Docker/Amnezia port path:
|
||
port_contract: ok
|
||
Anti-torrent:
|
||
drift: no
|
||
Swap:
|
||
drift: no
|
||
```
|
||
|
||
Если peers ещё нет, это здоровое desired state. `apply-limits` удалит оставшуюся AWG2-owned traffic topology, если раньше peers были, и завершится успешно. В штатном цикле daemon это не создаёт повторяющийся `info`-шум.
|
||
|
||
### 8. Включить systemd services
|
||
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl enable --now awg2-harness.service
|
||
systemctl enable --now awg2-reboot-scheduler.service
|
||
|
||
systemctl status awg2-harness.service --no-pager -l
|
||
systemctl status awg2-reboot-scheduler.service --no-pager -l
|
||
journalctl -u awg2-harness.service --since '5 minutes ago' --no-pager
|
||
journalctl -u awg2-reboot-scheduler.service --since '5 minutes ago' --no-pager
|
||
```
|
||
|
||
После 30–60 секунд:
|
||
|
||
```bash
|
||
awg2-harness --config /etc/awg2-harness/config.toml status
|
||
```
|
||
|
||
Healthy daemon показывает `service: active`, `traffic=ok`, `firewall=ok`, `swap=ok` в recent events и пустой `last_error`.
|
||
|
||
### 9. Проверить после reboot
|
||
|
||
```bash
|
||
reboot
|
||
```
|
||
|
||
После возврата:
|
||
|
||
```bash
|
||
systemctl status docker --no-pager -l
|
||
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
|
||
```
|
||
|
||
Дополнительно можно проверить фактическую `tc` topology внутри network namespace Amnezia:
|
||
|
||
```bash
|
||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||
PID="$(docker inspect -f '{{.State.Pid}}' "$C")"
|
||
|
||
nsenter -t "$PID" -n -- tc -s class show dev awg0
|
||
nsenter -t "$PID" -n -- tc -s class show dev ifb0
|
||
nsenter -t "$PID" -n -- nft list table inet awg2_harness
|
||
iptables -S INPUT
|
||
iptables -S AWG2H_A 2>/dev/null || iptables -S AWG2H_B
|
||
ip6tables -S INPUT
|
||
ip6tables -S AWG2H_A 2>/dev/null || ip6tables -S AWG2H_B
|
||
```
|
||
|
||
Для default config на одном peer ожидаются классы `1:10` и `2:10` с `rate 50Mbit ceil 50Mbit`, root classes `1:1` и `2:1` с `500Mbit`, помеченный переход из host `INPUT` в одну из цепочек `AWG2H_A`/`AWG2H_B` и anti-torrent table `inet awg2_harness` внутри Amnezia netns.
|
||
|
||
## CLI команды
|
||
|
||
Все команды принимают `--config`. Если параметр не указан, используется `/etc/awg2-harness/config.toml`.
|
||
|
||
```bash
|
||
awg2-harness --config /etc/awg2-harness/config.toml <command>
|
||
```
|
||
|
||
`validate-config` проверяет TOML и смысловые ограничения: пустые списки, формат rate (`50mbit`, `500mbit`), CIDR, reboot window, swap path, SSH/ожидаемый Amnezia UDP port и диапазон textual class id `10..=9999`. Удалённые поля `host_firewall.amnezia_port`/`amnezia_protocols` считаются ошибкой, а не молча игнорируются.
|
||
|
||
`validate-runtime` проверяет host tools, которые реально нужны выбранным модулям: `tc`, `ip`, `docker`, `modprobe`, `nsenter`, а также `iptables`, `ip6tables`, `nft`, `systemctl` и swap tooling при включённых firewall/reboot/swap. Хостовый `wg` в этот список не входит: peer state читается внутри контейнера через `docker exec` (`amnezia.wg_binaries`).
|
||
|
||
`ensure-swap` приводит swap к desired state: создаёт/проверяет swapfile, включает его с заданным priority, применяет `vm.swappiness`, делает swap state exclusive и переписывает swap entries в `/etc/fstab` под управляемый swapfile.
|
||
|
||
`apply-firewall` делает два reconcile: host INPUT firewall в изолированных `iptables`/`ip6tables` A/B-цепочках и nftables anti-torrent guard в выбранном namespace. Команда не меняет policy встроенного `INPUT`, Docker NAT или host `FORWARD`.
|
||
|
||
`apply-limits` находит Amnezia container, заходит в его network namespace, читает peers через container-side `awg`/`wg` и до mutation проверяет строгий server-side контракт: один IPv4 `/32` внутри `amnezia.peer_ipv4_cidr` на peer; `(none)` допустим. IPv6, смешанные или множественные маршруты, другая маска и адрес вне подсети дают явную ошибку unsupported topology. После проверки команда строит per-peer HTB/fq_codel классы на AWG/WG интерфейсе и IFB ingress path. Peer filters создаются classifier-ом `flower` с единым `pref 10`; legacy peer-фильтры `u32` считаются drift и мигрируют через controlled rebuild. Перед удалением проверяются qdisc handles и alias IFB `awg2-harness:traffic`; чужой объект с тем же именем является ошибкой. Healthy state не печатает сообщение на каждом цикле daemon.
|
||
|
||
`status` печатает фактическую диагностику: сервис, контейнер, netns, интерфейс, peers, WireGuard runtime, traffic desired/actual, host firewall drift, Docker/Amnezia port path со всеми UDP `HostIp:HostPort` bindings, anti-torrent counters, swap state, conntrack, recent events и planned reboot.
|
||
|
||
`daemon` — режим для systemd. На старте делает startup reconcile, затем слушает Docker events и периодически сверяет traffic/swap/firewall. Вручную обычно не запускается, кроме отладки.
|
||
|
||
`awg2-reboot-scheduler --config /etc/awg2-harness/config.toml` читает только секцию `[reboot]`, пишет план в `/run/awg2-harness/reboot.plan` и ждёт назначенного UTC-времени.
|
||
|
||
## Что происходит под капотом
|
||
|
||
Traffic shaping реализован через `tc` в network namespace контейнера Amnezia. На egress используется root qdisc `htb 1:` на AWG/WG интерфейсе, root class `1:1`, per-peer classes `1:<id>` и `fq_codel` под каждым peer class. Egress peer filter сопоставляет `dst_ip <peer>/32`, ingress peer filter — `src_ip <peer>/32`; оба используют `flower pref 10`. На ingress ставится `ingress ffff:` на AWG/WG интерфейс, входящие пакеты перенаправляются через `mirred` в configured IFB, а там строится отдельная HTB topology `2:` с такими же per-peer лимитами. Только catch-all redirect в IFB остаётся `u32`. `tc -batch -` является fail-fast, но не транзакционным: при любой ошибке Harness удаляет только доказанно свои частичные объекты, сохраняет первичную и cleanup-ошибку и затем обязательно выполняет verify. Счётчики peers берутся из `tc -s class`, потому что class-only `flower` не гарантирует action statistics.
|
||
|
||
Peer discovery берётся из WireGuard/AmneziaWG allowed IPs, а не из handshake state. Поэтому offline peer с `allowed ips: 10.8.1.1/32` тоже получает лимит заранее.
|
||
|
||
Ограничение относится только к адресации peers внутри server-side AWG topology. Клиентский маршрут `::/0` и внешний IPv6 Docker publish не означают IPv6 peer addressing: Docker может одновременно публиковать тот же UDP port на `0.0.0.0` и `[::]`, и status показывает оба binding.
|
||
|
||
Host firewall владеет только помеченным переходом из встроенного `INPUT` и двумя A/B-цепочками `AWG2H_A`/`AWG2H_B` отдельно для IPv4 и IPv6. Цепочка разрешает loopback, established/related, SSH-порт из конфига и optionally ICMP/ICMPv6, затем применяет configured verdict. Новая цепочка полностью проверяется до переключения; новый jump вставляется первым, а старый удаляется только после успеха обеих IP-family по точной rule specification. Numeric replace/delete не применяется, поэтому чужое правило не затрагивается при конкурентном изменении `INPUT`. Ошибка IPv6 удаляет только новый IPv4 jump и оставляет прежний рабочим. Published Amnezia UDP port здесь намеренно не открывается: Docker bridge publish обслуживается через Docker-managed `FORWARD`/NAT path.
|
||
|
||
Anti-torrent guard — отдельная AWG2-owned таблица `inet awg2_harness` обычно внутри Amnezia netns. Правило ограничивает число новых conntrack flows per source VPN IP. Это не DPI и не распознавание BitTorrent-протокола; это грубый, дешёвый guard против сотен одновременных P2P-соединений.
|
||
|
||
Swap module намеренно строгий: если `swap.enabled=true`, desired state — один управляемый swapfile. Старые swap entries удаляются из `/etc/fstab`, block-device swap выключается, но block device не удаляется.
|
||
|
||
## Production-границы ответственности
|
||
|
||
AWG2 Harness владеет только собственным state:
|
||
|
||
- `tc` topology с handles `1:`/`ffff:` на Amnezia interface и IFB с alias `awg2-harness:traffic`;
|
||
- помеченный host `INPUT` jump и цепочки `AWG2H_A`/`AWG2H_B` в `iptables`/`ip6tables`;
|
||
- nft table `inet awg2_harness` для anti-torrent;
|
||
- `/run/awg2-harness/*` runtime state;
|
||
- managed swapfile и swap entries, если `swap.enabled=true`.
|
||
|
||
AWG2 Harness не владеет:
|
||
|
||
- установкой AmneziaVPN;
|
||
- Docker daemon lifecycle;
|
||
- Docker NAT/FORWARD chains;
|
||
- генерацией client configs/keys;
|
||
- политикой пользователя внутри Amnezia app;
|
||
- сторонними firewall-таблицами.
|
||
|
||
## Документация
|
||
|
||
- [`docs/INSTALLATION.md`](docs/INSTALLATION.md) — установка и preflight.
|
||
- [`docs/UPSTREAM_COMPATIBILITY.md`](docs/UPSTREAM_COMPATIBILITY.md) — upstream-версии и контракт AWG 3.1.
|
||
- [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md) — параметры `config.toml`.
|
||
- [`docs/ACCEPTANCE_CHECKLIST.md`](docs/ACCEPTANCE_CHECKLIST.md) — production checklist.
|
||
- [`docs/ANTI_TORRENT.md`](docs/ANTI_TORRENT.md) — connection-count guard.
|
||
- [`docs/PRODUCTION_EXAMPLE.md`](docs/PRODUCTION_EXAMPLE.md) — эталонный production-пример.
|
||
- [`tools/README.md`](tools/README.md) — сборка и упаковка.
|
||
- [`reboot_module/README.md`](reboot_module/README.md) — внешний reboot scheduler.
|