feat: support AmneziaWG 3.1
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
|
||||
- [ ] Хост — Debian 13 amd64.
|
||||
- [ ] Сервер выделенный, без соседних сервисов.
|
||||
- [ ] AmneziaWG/AWG 2.0 или AmneziaWG/AWG 1.5 установлена официальным способом.
|
||||
- [ ] Контейнер `amnezia-awg2` или `amnezia-awg` запущен (`amnezia-awg3` — резерв на будущее, в AmneziaVPN 5.0 такого типа контейнера ещё нет).
|
||||
- [ ] AmneziaWG 3.1 установлена официальным self-hosted способом через AmneziaVPN 5.0.1.5 или новее.
|
||||
- [ ] Контейнер `amnezia-awg2` запущен; `amnezia-awg` допустим только как осознанный legacy fallback.
|
||||
- [ ] `docker ps` видит контейнер.
|
||||
- [ ] Можно получить PID контейнера.
|
||||
- [ ] `/proc/<pid>/ns/net` существует.
|
||||
@@ -15,6 +15,12 @@
|
||||
|
||||
## B. Обнаружение peers
|
||||
|
||||
- [ ] `C=amnezia-awg2` соответствует фактически запущенному контейнеру.
|
||||
- [ ] `docker exec "$C" awg --version` зафиксирован в acceptance evidence.
|
||||
- [ ] `docker exec "$C" ip -o link show awg0` находит основной интерфейс.
|
||||
- [ ] `docker exec "$C" ip -d link show awg0` фиксирует фактический kernel/userspace runtime без требования конкретной реализации.
|
||||
- [ ] `docker exec "$C" awg show all dump | awk -F '\t' '{print NR, NF, $1}'` для reference AWG 3.1 tools показывает 30 полей interface-row и 9 полей peer-row.
|
||||
- [ ] Width используется только как acceptance evidence; parser не определяет по нему версию и не классифицирует peer.
|
||||
- [ ] `awg2-harness status` показывает найденный контейнер.
|
||||
- [ ] `awg2-harness status` показывает PID/netns контейнера.
|
||||
- [ ] `awg2-harness status` показывает найденный интерфейс.
|
||||
@@ -171,7 +177,8 @@
|
||||
- [ ] Есть chain `forward_antitorrent` с hook `forward` и policy `accept`.
|
||||
- [ ] Правило ограничивает `ip saddr <peer_ipv4_cidr>`, default `10.8.1.0/24`.
|
||||
- [ ] Лимит считается per source VPN IP через meter/set, а не глобально по всей подсети.
|
||||
- [ ] Порог совпадает с `anti_torrent.max_connections_per_peer`; текущий пример config использует `150`, более строгий вариант — `100`.
|
||||
- [ ] Порог совпадает с `anti_torrent.max_connections_per_peer`; shipped production baseline — `500`.
|
||||
- [ ] В фактической nft rule присутствует `ct count over 500` для shipped config.
|
||||
- [ ] Drop counter виден в `status`.
|
||||
- [ ] На first-run без table `awg2-harness apply-firewall` создаёт `table inet awg2_harness`, а не падает.
|
||||
- [ ] При превышении порога новые flows дропаются, established flows ниже порога не ломаются.
|
||||
@@ -193,6 +200,7 @@
|
||||
- [ ] Package собирается на отдельной Debian 13 amd64 build-machine.
|
||||
- [ ] Production host не требует Rust/cargo/source tree.
|
||||
- [ ] `./tools/build.sh --package` создаёт `dist/awg2-harness_<version>_amd64.deb`.
|
||||
- [ ] Release package без `--version` получает версию `0.3.1` из `traffic_core/Cargo.toml`.
|
||||
- [ ] `dist/SHA256SUMS` валидирует checksum пакета.
|
||||
- [ ] Пакет ставит бинарь в `/usr/sbin/awg2-harness`.
|
||||
- [ ] Пакет ставит unit в `/lib/systemd/system/awg2-harness.service`.
|
||||
@@ -219,7 +227,7 @@
|
||||
- [ ] AmneziaDNS установлен из приложения AmneziaVPN.
|
||||
- [ ] Контейнер `amnezia-dns` в состоянии healthy.
|
||||
- [ ] `docker inspect amnezia-dns` показывает `"53/tcp":null` и `"53/udp":null`.
|
||||
- [ ] `amnezia-dns` и активный AWG-контейнер (`amnezia-awg2`, `amnezia-awg3` или `amnezia-awg`) подключены к одной Amnezia DNS Docker-сети.
|
||||
- [ ] `amnezia-dns` и активный AWG-контейнер (`amnezia-awg2` или осознанный legacy `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`.
|
||||
|
||||
+5
-10
@@ -4,7 +4,7 @@
|
||||
|
||||
## 1. Цель
|
||||
|
||||
Не детектить BitTorrent как протокол. Цель проще: ограничить количество одновременных conntrack flows на один VPN peer IP. Торрент-клиенты обычно пытаются держать сотни TCP/UDP peer-сессий, DHT/uTP/trackers. Лимит в диапазоне 100–250 одновременных flows заметно ухудшает P2P-поведение, но почти не затрагивает обычные сценарии при корректной настройке.
|
||||
Не детектить BitTorrent как протокол. Цель проще: ограничить количество одновременных conntrack flows на один VPN peer IP. Торрент-клиенты обычно пытаются держать сотни TCP/UDP peer-сессий, DHT/uTP/trackers. Штатный baseline `500` сохраняет мягкий connection guard, не вмешиваясь в нормальный повседневный профиль по результатам эксплуатационных измерений проекта.
|
||||
|
||||
Это мягкий технический барьер, а не abuse-система со страйками.
|
||||
|
||||
@@ -54,7 +54,7 @@ table inet awg2_harness {
|
||||
type filter hook forward priority filter; policy accept;
|
||||
|
||||
ip saddr 10.8.1.0/24 ct state new \
|
||||
meter awg2_peer_connlimit_v4 { ip saddr ct count over 100 } \
|
||||
meter awg2_peer_connlimit_v4 { ip saddr ct count over 500 } \
|
||||
counter name antitorrent_dropped_v4 \
|
||||
drop
|
||||
}
|
||||
@@ -70,15 +70,10 @@ table inet awg2_harness {
|
||||
```toml
|
||||
[anti_torrent]
|
||||
enabled = true
|
||||
max_connections_per_peer = 150
|
||||
max_connections_per_peer = 500
|
||||
```
|
||||
|
||||
Практические варианты:
|
||||
|
||||
- `100` — более строгий режим.
|
||||
- `150` — текущий рекомендуемый стартовый baseline, мягче к обычному browsing/mobile traffic.
|
||||
- `200/250` — ещё более permissive варианты.
|
||||
- `70` — агрессивный режим только после наблюдения реального трафика.
|
||||
`500` — production baseline, выбранный по прикладным и нагрузочным измерениям проекта. Connection guard остаётся включённым, но порог не должен мешать обычному browsing/mobile/application traffic. Любое значение ниже `500` является более агрессивной операторской политикой и требует отдельной проверки на реальных клиентах. Значение остаётся конфигурируемым и не зашито в алгоритм.
|
||||
|
||||
## 5. Почему это должно быть в orchestrator
|
||||
|
||||
@@ -92,7 +87,7 @@ max_connections_per_peer = 150
|
||||
|
||||
## 6. Conntrack и производительность
|
||||
|
||||
`ct count` использует conntrack. На текущем масштабе это нормально: даже 23 peers × 100 flows = около 2300 активных flows до ограничения. Это не выглядит опасно для production-хоста само по себе.
|
||||
`ct count` использует conntrack. Для примера 23 peers × 500 flows дают до 11 500 потенциальных flow slots перед ограничением каждого peer. Само по себе это не является доказательством достаточной ёмкости конкретного хоста, поэтому фактическое состояние conntrack обязательно наблюдается.
|
||||
|
||||
Что надо мониторить:
|
||||
|
||||
|
||||
+8
-10
@@ -1,6 +1,6 @@
|
||||
# Конфигурация AWG2 Harness
|
||||
|
||||
AWG2 Harness разрабатывался для self-hosted AmneziaWG/AWG 2.0 и совместимого legacy-сценария AmneziaWG/AWG 1.5. Конфиг живёт в `/etc/awg2-harness/config.toml`. Он общий для всего пакета и должен содержать только эксплуатационно значимые параметры.
|
||||
Основной target AWG2 Harness 0.3.1 — self-hosted AmneziaWG 3.1. AWG 3.0/2.x и `amnezia-awg` сохраняются как regression/legacy compatibility. Точная upstream-база описана в [`UPSTREAM_COMPATIBILITY.md`](UPSTREAM_COMPATIBILITY.md). Конфиг живёт в `/etc/awg2-harness/config.toml`, общий для всего пакета и содержит только эксплуатационно значимые параметры.
|
||||
|
||||
## Создание runtime config
|
||||
|
||||
@@ -24,9 +24,9 @@ nano /etc/awg2-harness/config.toml
|
||||
Discovery-команды:
|
||||
|
||||
```bash
|
||||
docker port amnezia-awg2 2>/dev/null || docker port amnezia-awg3 2>/dev/null || docker port amnezia-awg
|
||||
docker port amnezia-awg2 2>/dev/null || docker port amnezia-awg
|
||||
|
||||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
|
||||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||||
docker exec "$C" ip -4 addr
|
||||
docker exec "$C" awg show
|
||||
```
|
||||
@@ -35,7 +35,7 @@ docker exec "$C" awg show
|
||||
|
||||
```toml
|
||||
[amnezia]
|
||||
container_names = ["amnezia-awg2", "amnezia-awg3", "amnezia-awg"]
|
||||
container_names = ["amnezia-awg2", "amnezia-awg"]
|
||||
interface_candidates = ["awg0", "wg0", "amnezia0", "tun0"]
|
||||
interface_patterns = ["awg*", "wg*", "amnezia*", "tun*"]
|
||||
wg_binaries = ["awg", "wg"]
|
||||
@@ -73,7 +73,7 @@ default_input_policy = "drop"
|
||||
|
||||
[anti_torrent]
|
||||
enabled = true
|
||||
max_connections_per_peer = 150
|
||||
max_connections_per_peer = 500
|
||||
peer_ipv4_cidr = "10.8.1.0/24"
|
||||
apply_in_amnezia_netns = true
|
||||
|
||||
@@ -92,9 +92,7 @@ swappiness = 1
|
||||
|
||||
## Пояснения
|
||||
|
||||
`amnezia.container_names` — имена контейнеров, которые считаются Amnezia/AWG. Порядок важен, сопоставление точное. По текущему production-снимку основной вариант — `amnezia-awg2`, fallback — `amnezia-awg`.
|
||||
|
||||
`amnezia-awg3` перечислен на будущее и **не является подтверждённым официальным именем**: в проверенной версии AmneziaVPN `5.0.0.5` поддержка AWG 3.0 добавлена, но варианты контейнера по-прежнему представлены как `Awg` и `Awg2`, отдельного типа `Awg3` нет. Имя оставлено в примере потому, что несовпавшее имя не стоит ничего — поиск просто идёт дальше по списку, — тогда как отсутствующее в списке имя даст молчаливое «контейнер не найден». Если Amnezia введёт другое имя, его нужно будет дописать сюда.
|
||||
`amnezia.container_names` — упорядоченный список точных имён контейнеров Amnezia/AWG. Основной официальный вариант — `amnezia-awg2`, затем проверяется legacy `amnezia-awg`. Отдельного официального типа `amnezia-awg3` в зафиксированной upstream-версии нет. Другое имя можно явно добавить в runtime config; неизвестные имена автоматически не угадываются.
|
||||
|
||||
`amnezia.interface_candidates` — точные имена интерфейса, которые пробуются первыми.
|
||||
|
||||
@@ -102,7 +100,7 @@ swappiness = 1
|
||||
|
||||
`amnezia.wg_binaries` — утилита чтения peer state внутри контейнера, пробуется по порядку до первого успеха. Default — `["awg", "wg"]`. В официальном образе AmneziaWG реальный бинарь `/usr/bin/awg`, а `/usr/bin/wg` — symlink на него, поэтому `awg` идёт первым; `wg` остаётся для контейнеров с чистым WireGuard. Значения выполняются внутри контейнера и валидируются как имена команд: непустые, без пробелов и без разделителей пути. Параметр опциональный — конфиги, созданные до его появления, продолжают работать с default.
|
||||
|
||||
Хостовый `wireguard-tools` не нужен и не проверяется в preflight. Peer state читается только через `docker exec`: AmneziaWG — userspace-реализация, её UAPI-сокет находится в `RUNSTATEDIR/amneziawg/` внутри mount namespace контейнера, а `nsenter -n` входит только в network namespace, поэтому хостовый `wg` до него не достаёт.
|
||||
Хостовый `wireguard-tools` не нужен и не проверяется в preflight. Peer state читается через `docker exec` официальным `awg` внутри контейнера. Это единая container-side точка доступа для kernel `amneziawg` и fallback `amneziawg-go`, не зависящая от версии host-side tools.
|
||||
|
||||
`amnezia.peer_ipv4_cidr` — подсеть VPN peers. Production default — `10.8.1.0/24`; значение конфигурируемое.
|
||||
|
||||
@@ -177,7 +175,7 @@ swappiness = 1
|
||||
|
||||
`host_firewall.default_input_policy` — политика INPUT chain (`drop` или `accept`). Для production рекомендуется `drop`.
|
||||
|
||||
`anti_torrent.max_connections_per_peer` — максимум одновременных conntrack flows на один VPN peer IP. Текущий пример использует `150`: это мягче, чем строгий `100`, и обычно безопаснее как первый production baseline. `100` можно использовать как более жёсткий режим; `200/250` — более permissive варианты.
|
||||
`anti_torrent.max_connections_per_peer` — максимум одновременных conntrack flows на один VPN peer IP. Штатный production baseline — `500`, выбранный по эксплуатационным измерениям проекта так, чтобы connection guard оставался включённым и не вмешивался в нормальный повседневный профиль. Значение ниже `500` является сознательно более агрессивной политикой и требует проверки на реальных клиентах. Поле обязательное и не скрыто в Rust default.
|
||||
|
||||
`anti_torrent.peer_ipv4_cidr` — подсеть, на которую распространяется правило. Обычно должна совпадать с `amnezia.peer_ipv4_cidr`.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Production-пакет AWG2 Harness содержит два Rust-бинаря:
|
||||
- `awg2-harness` — host-side оркестратор traffic/firewall/status/swap;
|
||||
- `awg2-reboot-scheduler` — отдельный сервис планировщика перезагрузки.
|
||||
|
||||
`awg2-harness` остаётся основным host-side мульти-оркестратором для выделенного сервера Debian 13 amd64 с AmneziaWG/AWG 2.0.
|
||||
`awg2-harness` остаётся основным host-side мульти-оркестратором для выделенного сервера Debian 13 amd64. Основной upstream target релиза 0.3.1 — self-hosted AmneziaWG 3.1; AWG 3.0/2.x сохраняются как regression compatibility. Версии и source contract зафиксированы в [`UPSTREAM_COMPATIBILITY.md`](UPSTREAM_COMPATIBILITY.md).
|
||||
|
||||
Он владеет инфраструктурным состоянием, которое нужно VPN-сервису:
|
||||
|
||||
@@ -236,7 +236,7 @@ struct PeerTrafficStatus {
|
||||
|
||||
Это снижает эксплуатационный риск: если контейнер Amnezia перестанет содержать `tc` или `iproute2`, host-side утилиты всё равно применят правила внутри его netns.
|
||||
|
||||
Чтение состояния peers — единственное исключение, и его нельзя выполнять host-side бинарём. AmneziaWG — userspace-реализация, её UAPI-сокет находится в `RUNSTATEDIR/amneziawg/<iface>.sock` внутри mount namespace контейнера, тогда как хостовый `wireguard-tools` ищет сокет в `/var/run/wireguard/`. `nsenter -n` входит только в network namespace, поэтому хостовый `wg` не достаёт ни до сокета, ни до kernel-устройства и всегда возвращает пустой список peers. Поэтому обнаружение peers использует исключительно `docker exec`, а `wireguard-tools` не является зависимостью хоста и не проверяется в preflight.
|
||||
Чтение состояния peers — единственное исключение: harness намеренно использует официальный container-side `awg` через `docker exec`. `awg-quick` сначала пробует kernel interface типа `amneziawg`, а при его отсутствии запускает `amneziawg-go`. Container-side CLI является общей точкой доступа для обеих реализаций и изолирует harness от наличия и версии host-side `awg`/`wg`. Поэтому `wireguard-tools` не является зависимостью хоста и не проверяется в preflight.
|
||||
|
||||
## 6. Порядок discovery
|
||||
|
||||
@@ -290,10 +290,10 @@ Fallback-парсер разбирает текстовый вывод, извл
|
||||
Классификация строк `show all dump`:
|
||||
|
||||
- строка считается peer-строкой, только если в ней не менее 9 tab-колонок, колонка 5 (allowed ips) равна `(none)` или является списком CIDR через запятую, а колонки 6–8 (handshake, rx, tx) целиком парсятся как целые;
|
||||
- **количество колонок не является дискриминатором и не должно им становиться.** Ширину interface-строки определяет версия `amneziawg-tools`, которая её печатает, а не то, какие параметры протокола реально настроены в туннеле: AWG 3.0-утилиты печатают расширенную строку и для конфигурации AWG 2.0, просто с нулевыми или пустыми новыми полями. Любое правило вида «N колонок означает версию X» неверно по построению;
|
||||
- **количество колонок не является дискриминатором и не должно им становиться.** Исторически WireGuard/AWG 2.x/AWG 3.0/AWG 3.1 tools печатают interface-row шириной 5/14/28/30 полей, а текущий peer-row содержит 9. Ширину определяет producer `amneziawg-tools`, а не настроенная версия параметров: новые tools могут печатать широкую строку для старой конфигурации с нулевыми или пустыми новыми полями. Любое правило вида «N колонок означает версию X» неверно по построению;
|
||||
- interface-строка к тому же *длиннее* peer-строки, а на позициях handshake/rx/tx у неё стоят размеры junk-пакетов, которые тоже парсятся как целые, поэтому и эти колонки не разделяют два случая;
|
||||
- это важно не только для корректности: колонка 2 interface-строки — приватный ключ устройства, и ошибочно классифицированная interface-строка выдала бы его как public key peer;
|
||||
- AWG 3.0 печатает протокольные таймеры диапазонами (`20-30`). Колонка keepalive у peer не читается, и диапазон в ней не должен ломать разбор.
|
||||
- AWG 3.x печатает протокольные таймеры диапазонами (`20-30`). AWG 3.1 tools `v3.1.20260812` дополнительно печатают `RandomTrailers` и `DisableCookies` перед `fwmark`. Колонка keepalive у peer не читается, и диапазон в ней не должен ломать разбор.
|
||||
|
||||
Политика выполнения для production:
|
||||
|
||||
@@ -426,7 +426,7 @@ table inet awg2_harness {
|
||||
|
||||
Целевой namespace — тот же Amnezia network namespace, где применяется `tc` shaping. Нельзя предполагать, что начальный host namespace видит исходные source-адреса peers. Если Amnezia выполняет NAT внутри namespace контейнера, host Docker bridge может видеть только адрес контейнера, а не `10.8.1.x`.
|
||||
|
||||
Порог в примере конфигурации — `150` одновременных flows на peer IP. `100` — более строгий режим. `70` агрессивнее и применяется только после наблюдения реального трафика. `200`/`250` — более permissive варианты.
|
||||
Порог в примере конфигурации — `500` одновременных flows на peer IP. Это production baseline по эксплуатационным измерениям проекта: guard остаётся включённым, но не должен вмешиваться в нормальный повседневный профиль. Значение ниже `500` является более агрессивной политикой и требует отдельной проверки на реальных клиентах. Порог передаётся из config и не зашит в алгоритм.
|
||||
|
||||
Размещение правила: hook `forward` с приоритетом `filter` или любым приоритетом после conntrack lookup. Оценка ограничивается `ct state new`, чтобы установленные flows продолжали работать и дропались только новые попытки сверх порога.
|
||||
|
||||
@@ -696,10 +696,10 @@ inode = 123456
|
||||
Модульные тесты:
|
||||
|
||||
- валидация конфига, включая форму `amnezia.wg_binaries`;
|
||||
- разбор `config.example.toml` в актуальную схему;
|
||||
- разбор `config.example.toml` в актуальную схему с точным default-порядком контейнеров, `awg`/`wg` и anti-torrent baseline `500`;
|
||||
- парсер `awg|wg show all allowed-ips`, включая несколько allowed ips через пробел;
|
||||
- fallback-парсер `awg|wg show`;
|
||||
- классификация peer/interface строк `awg|wg show all dump` против interface-строк AWG 3.0 с включённой и с выключенной защитой заголовка, AWG 2.0, чистого WireGuard, а также конфигурации AWG 2.0, прочитанной утилитами AWG 3.0;
|
||||
- классификация peer/interface строк `awg|wg show all dump` против двух 30-полевых AWG 3.1 fixtures, AWG 3.0 с включённой и выключенной защитой заголовка, AWG 2.x, чистого WireGuard, а также конфигурации AWG 2.0, прочитанной tools AWG 3.0;
|
||||
- разбор dump с несколькими интерфейсами, с интерфейсом без peers и с повреждёнными строками;
|
||||
- порядок выбора бинаря wg и ошибка при отсутствии всех кандидатов;
|
||||
- фильтрация по CIDR;
|
||||
|
||||
+10
-8
@@ -5,14 +5,16 @@
|
||||
## Контракт развёртывания
|
||||
|
||||
- Целевой production-хост: Debian 13 amd64.
|
||||
- Amnezia ставится до AWG2 Harness официальным self-hosted способом через приложение AmneziaVPN.
|
||||
- Проект рассчитан на AmneziaWG/AWG 2.0 и compatible legacy-сценарий AmneziaWG/AWG 1.5.
|
||||
- Amnezia ставится до AWG2 Harness официальным self-hosted способом через AmneziaVPN 5.0.1.5 или новее.
|
||||
- Основной target релиза 0.3.1 — AmneziaWG 3.1; AWG 3.0/2.x остаются regression compatibility.
|
||||
- SSH должен быть заранее настроен. Production-пример: порт `2323`, вход по ключу, password login disabled.
|
||||
- Production-хост получает готовый Debian-пакет; Rust/cargo/source tree на нём не требуются.
|
||||
- `/etc/awg2-harness/config.toml` создаётся вручную. `config.example.toml` не копируется автоматически как боевой config.
|
||||
- Пакет не устанавливает Docker/Amnezia и не включает services автоматически.
|
||||
- `sysctl_tuning` не применяется в `postinst`; применение только на старте daemon или вручную через CLI.
|
||||
|
||||
Основной документированный сценарий — clean installation AWG 3.1. Официальный переход с AWG 2.0 требует пересоздания контейнера и перевыпуска пользователей; harness эту миграцию не выполняет. Версии и исходный контракт приведены в [`UPSTREAM_COMPATIBILITY.md`](UPSTREAM_COMPATIBILITY.md).
|
||||
|
||||
## A. Сборочная машина
|
||||
|
||||
### A1. Подготовить сборочное окружение
|
||||
@@ -40,10 +42,10 @@ cargo test --locked --workspace --release --manifest-path Cargo.toml
|
||||
### A3. Собрать Debian-пакет
|
||||
|
||||
```bash
|
||||
./tools/build.sh --package --version 0.3.0
|
||||
./tools/build.sh --package
|
||||
(cd dist && sha256sum -c SHA256SUMS)
|
||||
dpkg-deb -I dist/awg2-harness_0.3.0_amd64.deb
|
||||
dpkg-deb -c dist/awg2-harness_0.3.0_amd64.deb | sort
|
||||
dpkg-deb -I dist/awg2-harness_0.3.1_amd64.deb
|
||||
dpkg-deb -c dist/awg2-harness_0.3.1_amd64.deb | sort
|
||||
```
|
||||
|
||||
`--version` можно опустить, если версия в `traffic_core/Cargo.toml` уже равна release version. Version override влияет только на metadata `.deb`.
|
||||
@@ -127,7 +129,7 @@ Password or SSH private key:
|
||||
|
||||
```bash
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
|
||||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||||
echo "container=$C"
|
||||
docker port "$C"
|
||||
docker exec "$C" awg show
|
||||
@@ -166,7 +168,7 @@ amnezia-dns amnezia-dns Up ... (healthy) 53/tcp, 53/udp
|
||||
Проверка публикации портов:
|
||||
|
||||
```bash
|
||||
AWG="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
|
||||
AWG="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||||
echo "AWG=$AWG"
|
||||
|
||||
docker inspect -f 'ports={{json .NetworkSettings.Ports}}' amnezia-dns
|
||||
@@ -195,7 +197,7 @@ Optional deep-check DNS path (если нужна углублённая про
|
||||
```bash
|
||||
apt install -y dnsutils
|
||||
|
||||
AWG="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
|
||||
AWG="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||||
DNS_IP="$(docker inspect -f '{{range $n,$v := .NetworkSettings.Networks}}{{if $v.IPAddress}}{{println $v.IPAddress}}{{end}}{{end}}' amnezia-dns | head -n1)"
|
||||
DNS_PID="$(docker inspect -f '{{.State.Pid}}' amnezia-dns)"
|
||||
AWG_PID="$(docker inspect -f '{{.State.Pid}}' "$AWG")"
|
||||
|
||||
@@ -43,7 +43,7 @@ awg2-harness --config /etc/awg2-harness/config.toml status
|
||||
|
||||
```bash
|
||||
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
||||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg3|amnezia-awg)$' | head -n1)"
|
||||
C="$(docker ps --format '{{.Names}}' | grep -E '^(amnezia-awg2|amnezia-awg)$' | head -n1)"
|
||||
docker port "$C"
|
||||
docker exec "$C" awg show
|
||||
docker inspect -f 'ports={{json .NetworkSettings.Ports}}' amnezia-dns
|
||||
@@ -55,11 +55,12 @@ docker inspect -f 'ports={{json .NetworkSettings.Ports}}' amnezia-dns
|
||||
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 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-строки находится приватный ключ устройства.
|
||||
Reference AWG 3.1 tools `v3.1.20260812` дают 30 полей interface-row и 9 полей peer-row. Исторически WireGuard/AWG 2.x/AWG 3.0 interface-row имели 5/14/28 полей. Width используется только как acceptance evidence: harness не определяет по нему версию и не классифицирует peer. Полный вывод `awg show all dump` передавать нельзя: во второй колонке interface-row находится приватный ключ устройства. Точная upstream-база приведена в [`UPSTREAM_COMPATIBILITY.md`](UPSTREAM_COMPATIBILITY.md).
|
||||
|
||||
Проверка, что runtime config создан вручную (ожидаемое поведение):
|
||||
|
||||
|
||||
+6
-5
@@ -3,11 +3,12 @@
|
||||
Рекомендуемый порядок чтения:
|
||||
|
||||
1. [`../README.md`](../README.md) — общий runtime-план: SSH, официальная Amnezia, установка пакета, preflight, проверка перезагрузкой и CLI.
|
||||
2. [`INSTALLATION.md`](INSTALLATION.md) — сжатый порядок установки на production.
|
||||
3. [`CONFIGURATION.md`](CONFIGURATION.md) — параметры `/etc/awg2-harness/config.toml`.
|
||||
4. [`ACCEPTANCE_CHECKLIST.md`](ACCEPTANCE_CHECKLIST.md) — чек-лист приёмки перед статусом production-ready.
|
||||
5. [`ANTI_TORRENT.md`](ANTI_TORRENT.md) — ограничение числа соединений через nftables.
|
||||
6. [`IMPLEMENTATION_SPEC.md`](IMPLEMENTATION_SPEC.md) — архитектура и reconciliation состояния.
|
||||
2. [`UPSTREAM_COMPATIBILITY.md`](UPSTREAM_COMPATIBILITY.md) — канонический контракт совместимости с AmneziaWG.
|
||||
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. [`ANTI_TORRENT.md`](ANTI_TORRENT.md) — ограничение числа соединений через nftables.
|
||||
7. [`IMPLEMENTATION_SPEC.md`](IMPLEMENTATION_SPEC.md) — архитектура и reconciliation состояния.
|
||||
|
||||
Отдельно:
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# Совместимость с upstream AmneziaWG
|
||||
|
||||
Этот документ — канонический источник сведений о версиях AmneziaWG, с которыми сверяется AWG2 Harness. Остальная документация не должна дублировать плавающий набор upstream-версий: она ссылается сюда.
|
||||
|
||||
## Статус релиза 0.3.1
|
||||
|
||||
AWG2 Harness 0.3.1 проверен по официальной документации и исходникам AmneziaWG 3.1 по состоянию на 28 августа 2026 года. Это означает **source-validated against AWG 3.1**, но не заменяет live-приёмку на production-сервере.
|
||||
|
||||
Основной сценарий:
|
||||
|
||||
- self-hosted AmneziaWG 3.1;
|
||||
- AmneziaVPN 5.0.1.5 или новее;
|
||||
- чистая установка AWG 3.1 через AmneziaVPN;
|
||||
- контейнер `amnezia-awg2`;
|
||||
- интерфейс `awg0`;
|
||||
- чтение состояния через `awg`, с fallback на `wg`.
|
||||
|
||||
AWG 3.0 и 2.x остаются regression compatibility. Контейнер `amnezia-awg` поддерживается как legacy fallback. Название AWG2 Harness является именем продукта и пакета, а не ограничением на версию протокола.
|
||||
|
||||
## Зафиксированная upstream-база
|
||||
|
||||
| Компонент | Версия или ревизия | Назначение |
|
||||
|---|---|---|
|
||||
| AmneziaVPN | `5.0.1.5`, tag `7d4f3e0f5090b74903609179653d1f669d2ad08a` | Self-hosted deployment AWG 3.1 и container contract |
|
||||
| `amneziawg-tools` | `v3.1.20260812`, commit `ee0f0a9aa34ff0a0da4b3433b9512781cfe02843` | CLI, `awg-quick`, формат `show all dump` |
|
||||
| `amneziawg-go` | `v3.1.20260814`, commit `1b86b2ae0e493e7ea93f8c1a0f0cb6735b1551f1` | userspace fallback и reference container image |
|
||||
|
||||
Официальные источники:
|
||||
|
||||
- [FAQ: установка AWG 3.1 на self-hosted-сервер](https://docs.amnezia.org/ru/faq/);
|
||||
- [поддерживаемые серверные ОС и архитектуры](https://docs.amnezia.org/ru/documentation/supported-linux-os-for-vps/);
|
||||
- [отображение `DockerContainer::Awg2` в `amnezia-awg2`](https://github.com/amnezia-vpn/amnezia-client/blob/7d4f3e0f5090b74903609179653d1f669d2ad08a/client/core/utils/containers/containerUtils.cpp);
|
||||
- [`show all dump` в tools v3.1.20260812](https://github.com/amnezia-vpn/amneziawg-tools/blob/v3.1.20260812/src/show.c);
|
||||
- [kernel-first и userspace fallback в `awg-quick`](https://github.com/amnezia-vpn/amneziawg-tools/blob/v3.1.20260812/src/wg-quick/linux.bash);
|
||||
- [Dockerfile `amneziawg-go v3.1.20260814`](https://github.com/amnezia-vpn/amneziawg-go/blob/v3.1.20260814/Dockerfile).
|
||||
|
||||
Клиентский Dockerfile AmneziaVPN использует `amneziavpn/amneziawg-go:latest`. Поэтому перечисленные теги являются воспроизводимой reference/source baseline, но не обещанием, что любой будущий контейнер с тегом `latest` содержит те же сборки. Фактические версии проверяются во время live-приёмки.
|
||||
|
||||
## Контракт контейнера и tools
|
||||
|
||||
Default discovery имеет такой порядок:
|
||||
|
||||
```toml
|
||||
container_names = ["amnezia-awg2", "amnezia-awg"]
|
||||
wg_binaries = ["awg", "wg"]
|
||||
```
|
||||
|
||||
Отдельного официального типа или имени `amnezia-awg3` в зафиксированной версии клиента нет. Оператор может вручную указать другое корректное имя контейнера в `amnezia.container_names`.
|
||||
|
||||
Reference image содержит `/usr/bin/awg`, `/usr/bin/awg-quick` и symlinks `/usr/bin/wg -> /usr/bin/awg`, `/usr/bin/wg-quick -> /usr/bin/awg-quick`.
|
||||
|
||||
## Kernel и userspace
|
||||
|
||||
`awg-quick` сначала выполняет `ip link add <interface> type amneziawg`. Если kernel implementation недоступна, запускается `amneziawg-go`.
|
||||
|
||||
Harness не выбирает реализацию и не требует конкретную из них. Peer state читается через `docker exec` официальным `awg` внутри контейнера. Это единая container-side точка доступа для kernel и userspace вариантов и не создаёт зависимости от версии host-side tools.
|
||||
|
||||
## Контракт `show all dump`
|
||||
|
||||
Исторические widths являются диагностикой:
|
||||
|
||||
| Producer | Interface-row | Peer-row |
|
||||
|---|---:|---:|
|
||||
| WireGuard tools | 5 | 9 |
|
||||
| AWG 2.x tools | 14 | 9 |
|
||||
| AWG 3.0 tools | 28 | 9 |
|
||||
| AWG 3.1 tools `v3.1.20260812` | 30 | 9 |
|
||||
|
||||
В AWG 3.1 поля `RandomTrailers` и `DisableCookies` добавлены перед `fwmark`. Peer representation осталось девятиполевым.
|
||||
|
||||
**Количество колонок interface-row никогда не используется harness для определения версии протокола или классификации peer.** Версия tools определяет ширину interface-row, а новые tools могут печатать широкую строку и для конфигурации со старыми параметрами. Parser классифицирует peer семантически по allowed IPs и числовым handshake/RX/TX полям.
|
||||
|
||||
Полный interface-row нельзя публиковать в отчётах: во второй колонке находится приватный ключ устройства. Для диагностики выводятся только номер строки, число полей и имя интерфейса.
|
||||
|
||||
## Переход с AWG 2.0
|
||||
|
||||
Официальная модель перехода на AWG 3.1 — удалить AmneziaWG с сервера, установить заново новый контейнер, повторно создать пользователей и выпустить новые connection keys/configuration files.
|
||||
|
||||
Harness не выполняет эту миграцию, не читает и не меняет `awg0.conf`, не генерирует ключи и не управляет протокольными параметрами. Основной документированный путь для 0.3.1 — clean installation. Live acceptance выполняется после того, как AmneziaVPN завершила установку AWG 3.1.
|
||||
Reference in New Issue
Block a user