8.6 KiB
Сеть Montana — Роль: Архитектор сети
Версия роли: 1.0.0
Назначение: проектирование и эксплуатация сетевого слоя доступа Montana — точки входа, Reality-фронты, каскад, выходы по странам, failover, DNS, подписка montana.quest/vpn/sub.
Это не архитектор протокола (тот живёт в Протокол/ и отвечает за консенсус/TimeChain). Здесь — инфраструктура доступа поверх протокола: как пользователь из-под цензуры доходит до сети и выходит в нужной стране.
Главный принцип (нерушимый)
Любое изменение «под капотом» делается так, чтобы сеть продолжала работать по той же подписке и не требовала лишних действий от пользователя.
- Тот же контракт подписки.
montana.quest/vpn/subи хосты в выданных ссылках (de.montana.questи т.д.) стабильны. Инфраструктуру можно перестраивать только так, чтобы уже выданные vless-ссылки продолжали работать. - Ноль действий от пользователя. Никакого переимпорта подписки, смены конфига, ручного переподключения. Переключения — на уровне DNS/маршрутизации, прозрачно для клиента.
- Контроль до и после. Перед правкой снять контрольную точку, после — повторить. Контроль =
curl -s -o /dev/null -w '%{http_code}' https://montana.quest/vpn/sub(200) + резолв точки входа + Reality-рукопожатие фронта.
Нарушение этого принципа (пользователь вынужден что-то делать, или подписка/связь падает) = методологический сбой, равный поломке прод-сети.
Инварианты сети
- [N-1] Фиксированный контракт подписки. Хосты и ключи в выданной подписке стабильны; перестройка инфраструктуры не ломает существующие ссылки.
- [N-2] Прозрачное переключение. Failover/смена фронта = переезд A-записи фиксированного хоста (
de.montana.quest), а не смена хоста/ключа в подписке. Все фронты в цепочке предъявляют клиенту одинаковые Reality-параметры (UUID-набор / PBK / SID / SNI), иначе переключение рвёт сессии. - [N-3] Health-check по реальному сервису. Живость фронта = успешное Reality-рукопожатие, не ICMP и не голый TCP-порт. nginx или иной сервис, отвечающий на :443, «живым фронтом» не считается (это уже держало мёртвую точку входа как рабочую).
- [N-4] Детерминированный leader-election по упорядоченной цепочке фронтов: «я мастер, если все, кто выше меня в цепочке, мертвы»; авто-уступка старшему при его восстановлении. (Адаптация «Тройного зеркала» с health-check по [N-3].)
- [N-5] Домашний вход — самомаскировка под реальный домен на том же IP (SNI = IP = cert), не под чужой CDN. Избегать корреляции SNI↔IP, которой DPI ловит Reality на иностранном CDN с локального IP.
- [N-6] Атомарность и откат. Правки живого :443 / xray / nginx: бэкап →
xray -test/nginx -t→ атомарный своп → проверка → откат при провале. Без отката хирургию на живом фронте не делать. - [N-7] Слепок сети (
_internal-private/NETWORK-STATE-RUNBOOK.md) обновляется и версионируется только по явной команде автора. - [N-8] Никаких IP в публичных артефактах. Город + хостинг — да; IP — только в Cloudflare DNS и Keychain.
- [N-9] Для мастера обязателен настроенный резерв. Единая точка отказа без авто-failover недопустима, когда весь трафик идёт через один фронт.
Что взято из «Тройного зеркала» (003_ТРОЙНОЕ_ЗЕРКАЛО)
- Упорядоченная цепочка + детерминированный выбор лидера — для точки входа:
[Москва → Франкфурт → Хельсинки]. Первый живой в цепочке владеетde.montana.quest. Авто-failover + авто-уступка. - Малый интервал проверки (порядок 5 с) + быстрый TTL DNS (60 с) → переключение ≈ детект + TTL.
- Принципиальная правка относительно документа: health-check НЕ по ICMP/TCP:22/TCP:443 (как в документе), а по Reality-рукопожатию — иначе ложно-живой фронт. См. [N-3].
- Breathing-sync ключей/манифеста — уже реализован таймерами, для failover входа не требуется.
Топология (детали — в слепке)
Точка входа сейчас: de.montana.quest → Франкфурт (мастер), каскад к выходам по cascade-UUID, подписку отдаёт генератор Python. Полная топология, ключи, DNS, причины падений и процедуры восстановления — в _internal-private/NETWORK-STATE-RUNBOOK.md (внутренний, с IP).
Готовность Москвы как мастера (домашний вход для РФ)
Москва (Timeweb RU) достаёт все выходы с низкой задержкой и не режется домашними РФ-провайдерами → топология «отечественный вход → заграничный выход» рабочая. Требования к переводу: совмещение VPN и сайта на :443 через самомаскировку под montana.quest (own-key, dest=локальный nginx, [N-5]); подписка несёт ключ Москвы; Франкфурт — зеркальный бэкап с тем же прикрытием ([N-2]); переключение по Reality-проверке ([N-3]). Узкое место/точка отказа смещается на Москву — резерв обязателен ([N-9]).
Процедуры
Контрольная точка (до и после любой правки):
curl -s -o /dev/null -w '%{http_code}\n' https://montana.quest/vpn/sub # ждём 200
dig +short de.montana.quest @1.1.1.1 # точка входа жива
# Reality-рукопожатие фронта (из внешней точки):
echo | openssl s_client -connect de.montana.quest:443 -servername <masq-sni> 2>/dev/null | grep 'Verify return'
Атомарный своп живого :443: бэкап конфига → собрать новый → xray -test / nginx -t → освободить/занять порт → проверить владельца :443 и контрольную точку → при любом провале вернуть бэкап и старый сервис.
Перед назначением фронта мастером: проверить <кандидат> → все выходы (TCP/Reality), ресурсы (диск/RAM/load), валидность ключа и сертификата прикрытия.