Полноценный VPN-сервис, не просто статистика. На mirkwood обрабатывает ~168 активных клиентов, биллинг через WhiteBox, мониторинг туннелей.
/Users/v.tatarnikov/Projects/AmneziaWGStatistic → деплой в /opt/AmneziaWGStatisticmirkwood.4gain.pro (94.25.50.91)awg_stats (user awg)https://dep816.ru/admin/... (через nginx) или прямо :5001/api/v1/* (X-API-Key или VPN admin IP)Не путать с forGain VPN AmneziaWG — это отдельный VPN-сервис под клиентов dep816.ru, живёт на своём хосте mirkwood. forGain VPN — отдельная инсталляция в forGain-инфре.
| Репо | Что | Ansible? |
|---|---|---|
AmneziaWGStatistic (этот) |
Application: gunicorn awg-web, billing, NetFlow, DNS-parser, тесты, healthcheck, web-admin | contrib/ansible/roles/central-server/ (только app-side) |
| AmneziaWGServer | Server bootstrap: OS, AWG kernel module, inter-server туннели, Xray, server-pinger | основной Ansible-проект |
AmneziaWGServer деплоит сами серверы (VPN endpoints, kernel modules, awg-quick конфиги). AWG-stats предполагает что туннели уже подняты, и работает поверх них.
awg1 — клиентский интерфейс, 10.9.0.0/21 (потолок ~2000 IP). Адрес сервера 10.9.0.1. Конфиг генерится awg-sync.timer из БД.awg0/awg2/awg3 — inter-server туннели до exit-нод (RU/EU маршрутизация трафика):
awg0 → nugush (DigitalOcean EU, маршрут eu-nugush, fwmark=0x2, table 202) — через Xray VLESS+Realityawg2 → syun (eu-syun, table 203) — прямой UDPawg3 → sakmara (eu-sakmara, table 204) — прямой UDPfwmark=0x1, table 201fwmark = 0x100 + index (потолок ~250)Полная карта inter-server: inter-server-topology. Полный список fwmark и таблиц — см. firewall.
| Юнит | Что делает |
|---|---|
awg-web.service |
Web/admin/API gunicorn :5001 |
awg-pinger.service |
Ping всех клиентов (60с цикл, 20 воркеров) — liveness, GeoIP, port-scan, mDNS |
awg-netflow.service |
conntrack → netflow_log (per-flow трафик) |
awg-dns-parser.service |
journalctl coredns → dns_query_log |
awg-dns-prefetch.service |
warm-up топ-доменов |
awg-telegram-bot.service |
Бот @forGainElinkBot (свой webhook через nugush) |
| Таймер | Период | Что делает |
|---|---|---|
awg-fetcher.timer |
1 мин | awg show dump → БД (handshake/rx/tx/endpoint) |
awg-sync.timer |
1 мин | DB → awg1.conf (peers) + awg syncconf |
awg-firewall.timer |
1 мин | iptables + ipset (генерация по hash, skip если БД не менялась) |
awg-traffic-aggregate.timer |
5 мин | Sessions → traffic_usage (daily) |
awg-cachewarmer.timer |
4 мин | Прогрев memcached для дашбордов |
awg-billing.timer |
5 мин | BillingProcessor — списания, throttle, trial |
awg-state-check.timer |
5 мин | health-check kernel ↔ DB |
awg-uptime-monitor.timer |
1 мин | server_down/tunnel_down/handshake_stale |
awg-prune.timer |
24 ч | Ротация sessions, traffic_usage, dns_query_log, netflow_log, monitoring_alerts |
awg-backup.timer |
6 ч | Дамп 22 критических таблиц |
awg-backup-full.timer |
24 ч | Полный mysqldump |
awg-ipset-update.timer |
24 ч | Обновление гео-зон |
server-pinger.timer |
30 с | Ping серверов → memcached (TTL 300с — больше threshold 180с) |
awg-dns-prefetch.timer |
15 мин | DNS warmup |
awg-support-diag@<ticket_id>.service — template, запускается из API при создании support-тикета. Раньше был subprocess.Popen из gunicorn, терялся молча → переписан на systemd 2026-04-23.Полный список критичных юнитов: Applications/critical_units.py.
users — peers VPN (sid, public_key, address, plan_id, telegram_id, privacy_mode, ...)sessions — активные/завершённые сессии (с индексами idx_session_user_active, idx_session_started_at)traffic_usage — daily агрегаты per usersubscriptions — активная подписка (trial/paid_period/promo/active/throttled/free)payments — все списания/пополненияpayers — плательщики (1 plate ↔ N users через payer_users)plans — тарифы (speed_rx/tx, traffic_*_limit, price_monthly/6m/12m, trial_period_days, duration_days)tunnels, servers — exit-сервера и inter-server туннелиrouting_groups — группы маршрутизации (eu-nugush и т.п.) + ipset awg_rg_<id8>support_tickets — тикеты + PDF-диагностикаdns_query_log, netflow_log — телеметрия (отключается по User.privacy_mode)user_endpoint_sessions — endpoint-history (для GeoIP/портсканов)monitoring_alerts — алерты с дедупликациейСм. отдельную страницу: billing. Кратко:
Applications/billing_core.py — без I/O/ORM, импортируется тремя потребителями (создание подписки, рантайм процессор, симулятор).STATE_TRIAL, STATE_PAID_PERIOD, STATE_PROMO, STATE_ACTIVE, STATE_THROTTLED, STATE_FREE.tariff_expires_at → throttle 128 кбит/с (configurable: config.yml → billing.debt_throttle_kbit).User.privacy_mode = True отключает: DnsLogParser, NetflowCollector, GeoIP-lookup, port-scan публичного IP, mDNS-discovery, endpoint-tracking. Остаётся: ping, awg show, sessions, traffic_usage. Достаточно для биллинга.
Особенности — см. privacy. При новых коллекторах обязательно проверить privacy_user_sids(db) / privacy_user_ips(db).
См. qos. Кратко:
awg0/2/3 стоит HTB rate-limit (300 Mbps на mirkwood; 150 на sakmara — реальный канал DC ~340).Interfaces/Firewall/shaper.py.qos.conf для amneziawg-awgX.service авто-восстанавливает HTB после рестарта.route.conf авто-восстанавливает default route в table 20X.См. firewall. Кратко:
172.30.0.0/16 (обход Docker ICC drop)-C || -I (иначе дубли множатся).NAT MASQUERADE для 172.30.0.0/16 → WAN. ipset awg_iot — DROP iot/blocked к хосту.
nugush.4gain.pro/awg-webhook → mirkwood :8443/awg-webhookcd /Users/v.tatarnikov/Projects/AmneziaWGStatistic
# Ручной rsync файлов или через scp + systemctl restart awg-web
ssh root@94.25.50.91
cd /opt/AmneziaWGStatistic
python3 contrib/bin/apply-firewall.py --force # форсированная регенерация
Ansible-роль: contrib/ansible/roles/central-server (templates systemd/*.j2, tasks systemd-timers.yml, app.yml, coredns.yml, billing.yml, telegram.yml).
tests/ — 957+ тестов (api, views, billing, privacy, firewall/shaper, security, support, csrf, security-headers, error-handlers)python3 -m pytest tests/ -qtests/test_billing_simulator_parity.py (3 сценария — день за днём BillingProcessor vs simulator должны совпасть)/api/v1/* с заголовком X-API-Key. Ключи в config.yml → api_keys. WhiteBox-ключ: whitebox-internal-key.
Базовые endpoints:
/users, /users/{sid} — CRUD пиров/payers, /payers/{id}/auth — плательщики и проверка пароля/admin-users, /admin-users/auth — список админов и проверка пароля (используется в WhiteBox /admin/login)/payments — создание payment (включая period_months 1/6/12 со скидкой)/plans — тарифы/system/services — статус всех systemd/support/tickets — создание тикета (auth по VPN-IP)Примечание: до 2026-04-23 API_KEYS был пустой dict — ключи нигде не загружались. Теперь читаются из config.yml при старте AmneziaWGStatistic.__init__.
Полный аудит: docs/21-security-audit.md в репо. Реализовано из 16 пунктов туннельной производительности:
ipset restore батч (1 syscall вместо N)DEBT_THROTTLE_KBIT из config.ymlidx_session_started_atОсталось: T2 (pinger workers 20→100), T6 (TOTAL_BANDWIDTH в config), T8 (доп. индексы), T10 (RandomizedDelaySec в таймерах), и др.
Безопасность: SECRET_KEY персистентный, CSRF, sysctl-hardening, security-headers (X-Frame-Options, CSP, и т.д.), error-handlers (404/500/405 → JSON для API, cyber-template для UI).
94.25.50.91/27 public, gateway 94.25.50.65. VLAN 10 — 10.0.0.12/24 внутренняя.awg_stats), nginx 1.26, docker 29.3/opt/monitoring/docker-compose.ymlРаньше был хост
lojump.4gain.pro(тот же IP94.25.50.91). Миграция 2026-03 — VM пересоздана, hostname сменился наmirkwood. В Ansible-инвентареAmneziaWGServerещё может встречатьсяlojump.
forGain admin VPN — это тот же awg1 интерфейс на mirkwood, та же подсеть 10.9.0.0/21. Peers forGain-сторон:
Inter-server туннели mirkwood ↔ exit-нод (nugush/syun/sakmara) — отдельная схема (не mesh). Подробно: inter-server-topology. Конфиги — в репозитории AmneziaWGServer (Ansible).
Changelog