97 lines
6.1 KiB
Markdown
97 lines
6.1 KiB
Markdown
# Архитектура VPN-сети Montana
|
||
|
||
Версия: **2026-05-18**
|
||
|
||
## Поток подключения клиента
|
||
|
||
```
|
||
┌──────────────┐ 1. DNS resolve cdn.montana.quest
|
||
│ iPhone Happ │ ─────────────────────────────────────┐
|
||
└──────┬───────┘ │
|
||
│ ▼
|
||
│ ┌──────────────────────────┐
|
||
│ │ Cloudflare DNS multi-A │
|
||
│ │ TTL=120, не proxied │
|
||
│ │ → FI 91.132.142.42 │
|
||
│ │ → FRA 89.19.208.158 │
|
||
│ │ → US 86.104.72.12 │
|
||
│ └────────┬─────────────────┘
|
||
│ │
|
||
│ 2. TLS handshake (Reality) ───────────┘
|
||
│ SNI=www.googletagmanager.com
|
||
│ pbk=EkTs2aGKnFNgFZ0f7wgft2sJp3VjwFQqIrwkZKM4gD8
|
||
▼
|
||
┌────────────────────────────────────────────────────┐
|
||
│ xray :443 на одном из узлов (любом — один keypair) │
|
||
│ vless + xtls-rprx-vision + reality │
|
||
│ user=xray:xray, Restart=always, StartLimitBurst │
|
||
│ outbound: freedom (direct internet) │
|
||
└────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
## Поток управления (health watchdog)
|
||
|
||
```
|
||
┌────────────────────────────────────────────────┐
|
||
│ montana-orchestrator.service на Moscow │
|
||
│ /opt/montana-orchestrator/server.py :5020 │
|
||
│ │
|
||
│ Flask: │
|
||
│ POST /register {ip, alias, …, secret} │ ← admin
|
||
│ POST /deregister {ip, secret} │ ← узел при shutdown
|
||
│ GET /pool — CF records + state │ ← аудитор
|
||
│ GET /health — кол-во live │ ← мониторинг
|
||
│ │
|
||
│ Background thread (каждые 30 сек): │
|
||
│ for ip in registry∪pool: │
|
||
│ ok = tls_probe(ip:443, SNI) │
|
||
│ if ok && success≥2 && not in_pool: │
|
||
│ cf_api POST /dns_records │
|
||
│ if !ok && fails≥2 && in_pool: │
|
||
│ cf_api DELETE /dns_records/<id> │
|
||
└────────────────────────────────────────────────┘
|
||
│
|
||
▼
|
||
Cloudflare API
|
||
```
|
||
|
||
## Компоненты
|
||
|
||
| Узел | Хост | Роль | Сервисы |
|
||
|---|---|---|---|
|
||
| Helsinki | 91.132.142.42 | VPN-backend | xray |
|
||
| Frankfurt | 89.19.208.158 | VPN-backend | xray |
|
||
| New York | 86.104.72.12 | VPN-backend | xray |
|
||
| Moscow | 176.124.208.93 | orchestrator + landing + p2p (НЕ VPN) | nginx, montana-orchestrator, montana-node |
|
||
|
||
## Криптографические параметры
|
||
|
||
| Параметр | Значение | Где |
|
||
|---|---|---|
|
||
| Reality protocol | `vless + xtls-rprx-vision` | inbound config |
|
||
| Server SNI / dest | `www.googletagmanager.com:443` | realitySettings.dest |
|
||
| Universal UUID | `e6d355e2-2d79-4c96-a373-3b0e6b6f4b0d` | clients[0].id |
|
||
| Reality publicKey | `EkTs2aGKnFNgFZ0f7wgft2sJp3VjwFQqIrwkZKM4gD8` | URL `pbk=` |
|
||
| Reality shortId | `302805bc0c25e504` | URL `sid=` |
|
||
| Reality privateKey | (хранится только на узлах) | `/usr/local/etc/xray/config.json` (600) |
|
||
|
||
## Сетевые потоки
|
||
|
||
| От | До | Порт | Назначение |
|
||
|---|---|---|---|
|
||
| Любой клиент | VPN-узел | 443/tcp | Reality VPN |
|
||
| Moscow orchestrator | VPN-узел | 443/tcp | watchdog TLS-probe |
|
||
| Moscow orchestrator | api.cloudflare.com | 443/tcp | DNS API |
|
||
| Узел | Любой destination | 443/tcp etc. | freedom outbound |
|
||
| Любой p2p-узел | Любой узел | 8444/tcp | montana-node Bootstrap+VDF |
|
||
| Admin | Moscow `montana.quest/vpn/node/register` | 443/tcp | POST с secret |
|
||
|
||
## Решения и обоснования
|
||
|
||
- **Universal keypair на всех backends** — Reality требует, чтобы клиент знал `publicKey` сервера. Multi-A pool с разными keypair невозможен без подписки с несколькими `vless://`. Принято: один keypair с trade-off shared-secret (см. THREAT-MODEL.md T-2).
|
||
- **DNS multi-A вместо подписки с несколькими URL** — даёт «один ключ распределяет» без логики на клиенте; iOS native resolver сам ротирует ANSWER.
|
||
- **TTL 120s** — баланс между скоростью переключения при отказе и нагрузкой на DNS.
|
||
- **Watchdog interval 30s, threshold 2** — реакция за 60–120 секунд при минимальной нагрузке на узлы (≈ 1 probe в минуту с одной точки).
|
||
- **orchestrator на Moscow, не на VPN-узле** — изоляция управления от data-plane; падение orchestrator не роняет существующие подключения.
|
||
- **Moscow исключена из VPN pool** — на :443 nginx (efir.org), :2053 — отдельный xray не для публики.
|