montana/Node/External-Audit/AUDIT-READINESS.md
2026-05-21 03:44:38 +03:00

7.1 KiB
Raw Blame History

Спецификация готовности к внешнему аудиту

Версия: 2026-05-18

Что мы гарантируем (must hold)

A. Архитектурные инварианты

# Инвариант Как проверить
A1 На каждом VPN-узле один inbound xray vless+reality :443, без посредников (нет haproxy, нет xray-pinned cascade) ss -tlnp | grep :443 → один процесс xray; systemctl is-active haproxy → inactive
A2 Все VPN-узлы используют один и тот же Reality keypair (privateKey, publicKey, shortId) и один UUID TLS-probe с тем же pbk к каждому IP проходит handshake → Verification: OK
A3 cdn.montana.quest resolves в multi-A pool из живых VPN-узлов, TTL ≤ 120s, не proxied через CF dig @1.1.1.1 cdn.montana.quest A показывает несколько IP; TTL ≤ 120
A4 /vpn/sub отдаёт ровно одну vless-ссылку с cdn.montana.quest:443 curl /vpn/sub | base64 -d — одна строка vless://…
A5 Клиент с одним профилем подключается к любому из IP pool без переустановки профиля iPhone Happ → connect; toggle airplane → reconnect; в xray access.log видно соединение

B. Самовосстановление

# Инвариант Как проверить
B1 При отказе узла его IP выпадает из multi-A не позже чем за 2 минуты E2E test: systemctl stop xray на узле → /vpn/node/pool через 60-90s не содержит IP
B2 При восстановлении узла IP возвращается в multi-A не позже чем за 2 минуты Обратный E2E
B3 Watchdog запускается автоматически при старте orchestrator; падение Flask → systemd restart systemctl is-enabled montana-orchestrator = enabled; Restart=on-failure в unit
B4 xray на узле имеет Restart=always с StartLimitBurst=10/300s (защита от крэш-цикла) cat /etc/systemd/system/xray.service.d/30-autorestart.conf

C. Секреты

# Инвариант Как проверить
C1 Reality privateKey отсутствует в публичных артефактах: git, hub.montana.quest, sub-endpoint, /vpn/, /net/ карта grep -r 'cL7D6FCqH5' Montana/ | grep -v External-Audit | grep -v memory ⇒ 0 совпадений (allowed только в Memory/internal)
C2 На узле privateKey лежит в /usr/local/etc/xray/config.json с правами 600 root:root ls -la /usr/local/etc/xray/config.json
C3 Cloudflare API token хранится только в macOS Keychain (cloudflare-api-token) и в /etc/montana/cf-api-token (0600) на orchestrator-узле ls -la /etc/montana/cf-api-token
C4 Admin secret для /register /deregister — random 32-byte hex, в Keychain montana-orchestrator-admin и /etc/montana/orchestrator-admin-token (0600) то же
C5 join.sh не содержит секретов; VPN_PRIVKEY передаётся через env или защищённый файл `grep -E 'privateKey

D. Минимальные привилегии и изоляция

# Инвариант Как проверить
D1 xray работает под dedicated user xray:xray, не nobody/root ps -ef | grep [x]ray run — owner = xray
D2 На узле ufw default deny incoming; открыты только 22, 80, 443, 8444 (p2p) ufw status verbose
D3 fail2ban активен с jail для sshd (maxretry=3, bantime≥1h) systemctl is-active fail2ban && fail2ban-client status sshd
D4 orchestrator слушает только 127.0.0.1:5020, наружу — через nginx ss -tlnp | grep :5020 — bound to 127.0.0.1

E. Производственное качество кода

# Инвариант Как проверить
E1 xray версия pinned (XRAY_PIN) в join.sh grep XRAY_PIN Montana/Node/join.sh
E2 Все systemd-units включены (enabled) systemctl is-enabled xray montana-orchestrator fail2ban
E3 Reality serverNames указывает на реальный публичный сайт с валидной CA-цепочкой openssl s_client -connect <IP>:443 -servername <SNI>Verification: OK

Что мы НЕ гарантируем (out of scope)

# Не гарантия Причина
N1 Защита от компрометации единого privateKey Reality по дизайну требует shared keypair для нескольких backends. Mitigation в OPERATIONS.md#rotation
N2 Защита от блокировки SNI www.googletagmanager.com Один SNI = single point. В roadmap — SNI pool (см. OPEN-RISKS.md R-1)
N3 Защита от DDoS на узлы Опирается на анти-DDoS хостинга. Mitigation: BGP-уровень провайдера
N4 Защита от компрометации Cloudflare API token Token — единственная точка управления DNS. Mitigation: scoped permissions, rotation
N5 Анонимность пользователя относительно exit-IP Узлы видят destination, как любой VPN
N6 Защита от атак на montana-node p2p :8444 (Montana TimeChain) Отдельный аудит TimeChain protocol (Montana-Protocol/Code/AUDIT.md)
N7 Защита от компрометации хостинга (image dump) Дано на уровне договора с провайдером, не на уровне кода

Критерии «mainnet-ready» (must pass)

  1. A1A5, B1B4, C1C5, D1D4, E1E3 — все проверки зелёные (см. scripts/audit-probe.sh).
  2. E2E auto-prune при отказе узла занимает ≤ 120 секунд (B1).
  3. E2E auto-restore при возврате узла занимает ≤ 120 секунд (B2).
  4. 0 секретов утекло в публичные артефакты (C1).
  5. Все P0/P1 риски из OPEN-RISKS.md закрыты или явно приняты с обоснованием.

История проверки

Дата Что проверено Результат
2026-05-18 E2E auto-prune US (down) 2 секунды
2026-05-18 E2E auto-restore US (up) 29 секунд
2026-05-18 Reality probe на всех 3 IP Verification: OK
2026-05-18 C1 grep на privateKey в публичных артефактах 0 (см. scripts/check-leaked-secrets.sh)