Весь разговор с ядром steer — в одном блоке функций stl_* (слой steer): бекенд отдаёт ему свою модель (выход WARP или VPN, сервисы и их списки, подписка с узлом и маркерами) и спрашивает состояние на своём языке, а слой пишет спеку v2 в /etc/steer/spec.json и зовёт клиент steer, который отдаёт команды демону steerd. - Ядро: steer-core и только нужные модули (VLESS — когда есть подписка) вместо steer-extended; версия — stable 2.x из splify2/releases (version.json, с проверкой sha256), не ниже 2.0.0. Переход с 1.x: apk — одной транзакцией, opkg — снятием прежнего пакета; спека остаётся. Удаляются только пакеты, которые ставил Zapret Manager. - Применение: проверка демоном (ctl check), затем steer apply через демона — он сам трогает только изменившееся. Убраны костыли 1.5.9: srs-read и перевод .srs в текст, сумма спеки и сверка outputs, выбор между reload и restart, перезапуск при fail-open, kmod-tun руками, чтение набора nft. - WARP — группа pick: latency из туннелей (один туннель — выход-устройство), без IPv6, как и прежде. VPN — tunnel vless: маркеры узлов уходят в exclude_name, скрытые и закреплённый узел — в nodes без предела 16. - Состояние — из steer status (failed, device, probe), diag и explain — через слой. Блокер: ядро ведёт steer-box-connector (podkop, forkop) или чужая спека v1/v2/yaml. - Прежняя спека ZM (v1) ядро 2.0 читает как есть; при первом применении слой пишет её заново в v2. Автоперезапуск по cron и обновление панели идут через backend.sh. - Фронтенд: три подсказки про steer-extended переписаны под ядро 2.0. - docs/autobypass: перестановка туннелей рвёт соединения сменой туннеля, а не перезапуском ядра. Committed-by: agy-cli (autonomous, run #96)
63 KiB
Как работает автообход
Автообход — одна кнопка в Zapret Manager. Роутер сам проверяет популярные сервисы и каждому подбирает самый дешёвый способ, при котором сервис открывается: напрямую, через стратегию zapret, через туннель WARP или через свой DNS. Ниже — что именно происходит после нажатия, как перебираются стратегии, как выбираются колонии WARP и как потом ходит трафик.
Коротко о словах, которые встретятся дальше:
| Слово | Что это |
|---|---|
| zapret | обход DPI провайдера: первые пакеты соединения подправляются так, чтобы фильтр их не узнал |
| стратегия | набор настроек zapret. Здесь есть наборы v (v1–v10), Flowseal, Yv (для YouTube), Dv (для голоса Discord) |
| WARP | бесплатный туннель Cloudflare. Весь трафик сервиса уходит в него и выходит у Cloudflare |
| колония | узел Cloudflare, через который выходит туннель; обозначается кодом аэропорта: HEL — Хельсинки, DME — Москва |
| Steer | движок, который решает, какой сервис идёт в WARP, а какой — обычным путём |
| fakeip | подставной адрес, который Steer выдаёт в ответ на DNS-запрос, чтобы потом узнать соединение этого сервиса |
| DoH | DNS поверх HTTPS: запрос имени, который провайдер не видит и не подменяет |
| stgws | мост Telegram на роутере: прячет протокол Telegram в веб-сокет или ведёт его через WARP |
1. Что делает кнопка
┌──────────────────────────────┐
│ нажата кнопка «Автообход» │
└──────────────┬───────────────┘
│
┌─────────────────────────┼─────────────────────────┐
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ zapret не стоит │ │ zapret выключен │ │ Steer выключен или │
│ → ставится │ │ → включается │ │ сервис снят на его │
│ │ │ и запускается │ │ странице → запрет │
│ │ │ │ │ снимается │
└──────────────────┘ └──────────────────────┘ └──────────────────────┘
│
▼
┌──────────────────────────────┐
│ подбор (раздел 2), затем │
│ фоновое сравнение (разд. 4)│
└──────────────────────────────┘
Нажатая кнопка — согласие на всё, что автообход умеет. То, что было выключено руками, снова участвует в подборе: иначе подбор находил бы, что сервис открывается через WARP, и не включал бы его.
Есть два режима:
| Режим | Какие стратегии перебираются | Сколько идёт |
|---|---|---|
| Быстрый | набор v (10 стратегий) | обычно 5–15 минут |
| Полный | Flowseal и v | дольше, до получаса |
Полный подбор перебирает стратегии всегда, даже если при текущей настройке всё открывается: его выбирают, чтобы найти вариант лучше. Быстрый перебирает, только если какой-то сервис не открылся.
Пока подбор идёт, сеть работает на прежней настройке: стратегии проверяются в стороне и клиентов не касаются (раздел 3). Автообход нельзя запустить, пока идёт тест стратегий Zapret Manager или операция на странице Steer.
2. Порядок подбора
┌───────────────────────────────────────────────────────────────────────────┐
│ ① Проверка при текущей настройке │
│ YouTube, Discord, Instagram, WhatsApp, X, GitHub │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ② Подбор стратегии zapret │
│ быстрый — если что-то не открылось; полный — всегда │
│ победитель применяется, сервисы перепроверяются, хуже — откат │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ③ YouTube отдельно — если всё ещё не открывается: свой набор Yv │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ④ «Напрямую или через zapret» — открывшиеся сервисы проверяются в обход │
│ zapret, чтобы знать, нужен ли он им вообще │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ⑤ WARP — для того, что не открылось, если стоит Steer │
│ три туннеля в разных колониях (раздел 5), сервис проверяется через │
│ туннель и, если открылся, добавляется в Steer │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ⑥ Туннели для моста Telegram — если шаг ⑤ не понадобился, туннели всё │
│ равно проверяются: мост ходит через WARP сам │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ⑦ ИИ-сервисы — не открываются → DoH только для их доменов (раздел 7) │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ ⑧ Telegram — напрямую, через мост stgws или через WARP (раздел 8) │
└─────────────────────────────────┬─────────────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ «Готово, обход подобран» │
│ ⑨ в фоне — сравнение близких стратегий (раздел 4), если такие нашлись │
└───────────────────────────────────────────────────────────────────────────┘
Лестница стоимости
Каждому сервису достаётся первая ступень снизу, на которой он открывается. Чем выше ступень, тем больше вмешательства в трафик.
дороже ▲
│ ┌──────────────────────┐
│ │ туннель WARP │ весь трафик сервиса уходит в туннель
│ ├──────────────────────┤
│ │ стратегия zapret │ подправляются первые пакеты соединения
│ ├──────────────────────┤
│ │ DoH для доменов │ меняется только ответ DNS (ИИ-сервисы)
│ ├──────────────────────┤
│ │ напрямую │ ничего не делается
дешевле └──────────────────────┘
У Telegram лестница своя, и WARP на ней не наверху. Веб-сокет через домены-посредники за Cloudflare дороже туннеля: на каждое соединение — рукопожатие TLS с чужим доменом, отказы 503, лишний слой TLS поверх всего потока, и не у каждого домена есть все дата-центры. Прямой путь к настоящему дата-центру через WARP — это просто туннель. Поэтому мост пробует его раньше веб-сокета (раздел 8).
┌──────────┐
│ сервис │
└────┬─────┘
▼
┌──────────────────────────┐
│ открывается как есть? │
└──────┬────────────┬──────┘
да │ │ нет
▼ ▼
┌────────────────────────┐ ┌──────────────────────────┐
│ и в обход zapret тоже? │ │ подбор zapret помог? │
└──┬──────────────┬──────┘ └──────┬────────────┬──────┘
да │ │ нет да │ │ нет
▼ ▼ ▼ ▼
┌───────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────────────────┐
│ напрямую │ │ через zapret│ │ через zapret│ │ Steer стоит и через │
└───────────┘ └─────────────┘ └─────────────┘ │ WARP открывается? │
└──────┬───────────┬───┘
да │ │ нет
▼ ▼
┌───────────┐ ┌──────────────┐
│ через WARP│ │не открывается│
└───────────┘ └──────────────┘
Когда сервис считается открытым
У каждого сервиса два списка адресов:
| Список | Что должно открыться | Пример |
|---|---|---|
| обязательные | все до одного | у YouTube — сайт, API и узел видео; у Discord — сайт, шлюз и узел обновлений |
| дополнительные | не меньше 60 % | картинки, CDN, статика |
Одного главного адреса мало: страница YouTube открывается, а видео — нет. Адрес считается открытым, если сервер ответил каким-то кодом, кроме «451, недоступно по закону», и в ответе нет фраз геоблока вроде «not available in your country». Ответ, оборвавшийся на 16–20 КБ, открытым не считается: так выглядит блокировка «на середине страницы».
Все проверки разрешают имена через свой DoH (1.1.1.1, 8.8.8.8 или 77.88.8.8 — первый, что ответил), а не через DNS роутера: провайдер может подменять ответы. Исключение — ИИ-сервисы: их проверяют именно DNS роутера, потому что лечит их как раз он (раздел 7).
3. Перебор стратегий
Проверка в стороне
Обычный тестер Zapret Manager переписывает настройку zapret каждой новой стратегией и перезапускает обход. Все минуты теста клиенты сети живут то на одной случайной стратегии, то на другой. Автообход так не делает:
┌──────────────── ОБЫЧНЫЙ ТРАФИК СЕТИ ─────────────────┐
│ телефоны, ноутбуки │
│ │ │
│ ▼ │
│ zapret на ПРЕЖНЕЙ стратегии ──► интернет │ ← не меняется до конца подбора
└──────────────────────────────────────────────────────┘
┌──────────────── ПРОВЕРКА СТРАТЕГИИ ──────────────────┐
│ запросы самого роутера с портов 20000–20999 │
│ │ │
│ ▼ │
│ свой экземпляр zapret со СВОЕЙ стратегией │ ← только эти запросы
│ на своей очереди пакетов │
│ │ │
│ ▼ │
│ пакеты помечены — общий zapret их пропускает │
│ │ │
│ ▼ │
│ интернет │
└──────────────────────────────────────────────────────┘
Проверочный трафик отличается от клиентского портами отправителя. Он попадает только в свой экземпляр zapret, а общий zapret его не трогает. Настройка zapret роутера меняется один раз, в конце, и только если победитель действительно лучше.
Что перебирается и на чём
┌───────────────────┐ ┌──────────────────────────────────────────────┐
│ стратегии │ │ цели проверки │
│ │ │ │
│ быстрый: v1–v10 │ │ ▸ общий список Zapret Manager: госуслуги, │
│ │ × │ налоговая, rutube, instagram, discord, x, │
│ полный: Flowseal │ │ rutracker, openwrt и др. + внешний набор │
│ + v1–v10 │ │ сайтов с проверкой «16–20 КБ» │
│ │ │ (на момент написания — 54 адреса) │
│ │ │ ▸ адреса сервисов, которые не открылись │
│ │ │ на шаге ① (считаются отдельно) │
└───────────────────┘ └──────────────────────────────────────────────┘
Число стратегий Flowseal и часть целей приходят из внешних списков, поэтому они меняются со временем. Первым идёт контроль: те же цели без zapret. С ним сравнивается каждая стратегия.
Для каждой стратегии:
запустить свой zapret со стратегией ──► не запустился? ──► «не запустилась», дальше
│
▼
все цели параллельно (по 8 разом; на роутере меньше 256 МБ — по 4)
│
▼
основной счёт: «открылось N из 54»
хвост: сколько адресов неоткрывшихся сервисов открылось
Цель считается открытой так же, как при проверке сервисов: сервер ответил каким-то кодом,
кроме «451, недоступно по закону». Адреса из внешнего набора приходят голыми именами, без
https://, и проверяются по HTTPS, как остальные цели.
Как выбирается победитель
1. сортировка: по основному счёту, при равном — по хвосту
│
▼
2. лучшая лучше контроля? ├── основной больше, чем без zapret ──► да
├── основной равен, но хвост больше ──► да
└── иначе ──► «Ни одна стратегия не открыла больше,
чем без Zapret — настройку не меняем»
│
▼
3. применяется к zapret роутера
│
▼
4. все сервисы проверяются заново
открылось меньше, чем до подбора? ──► проверка ещё раз (одна проба шумит)
всё равно меньше ──► откат к прежней настройке
│
▼
5. «Стратегия … применена»
Если подбор остановили на середине, неполный победитель не применяется. Если остановили во время перепроверки, прежняя настройка возвращается.
YouTube подбирается отдельно, если после общего подбора он всё ещё не открывается. Для него перебирается свой набор Yv на адресах YouTube и видеоузлов. Применяется он так же — только если лучше контроля, с перепроверкой и откатом.
4. Фоновое сравнение близких стратегий
Короткие запросы основного прохода плохо различают стратегии: разница в пару целей из полусотни — это шум. При этом провайдер часто рвёт соединение к CDN и хостингам уже после того, как через него ушло 16–20 КБ. Страница успела «открыться», а дальше замерла. Поэтому после «Готово» близкие к победителю стратегии ещё раз сравниваются в фоне другим замером.
результаты основного прохода
│
▼
┌───────────────────────────────────────────────────────────────┐
│ близкие: основной счёт не ниже 90 % от счёта лучшей │
│ первой — применённая, за ней открывшие больше адресов │
│ неоткрывшихся сервисов; всего не больше 6 │
└───────────────────────────┬───────────────────────────────────┘
одна — сравнивать не с кем, фона нет
│ больше одной
▼
┌───────────────────────────────────────────────────────────────┐
│ у каждой — дополнительный счёт по узлам CDN (метод ниже) │
│ ИТОГ = основной + дополнительный │
└───────────────────────────┬───────────────────────────────────┘
▼
┌───────────────────────────────────────────────────────────────┐
│ победитель по итогу — другая стратегия, итог СТРОГО больше? │
│ нет → «Оставляем …» │
│ да → настройку за это время не меняли руками? │
│ → применить, проверить сервисы │
│ → открывается меньше? вернуть прежнюю │
└───────────────────────────────────────────────────────────────┘
Дополнительный замер — как у dpi-detector
Способ взят у проекта dpi-detector (Runnin4ik), и узлы — из его списка: адреса Hetzner, Cloudflare, CDN77, Akamai, AWS, Fastly, Oracle, OVH и других провайдеров. На момент написания их 110.
роутер ──────── одно соединение ──────────► узел CDN
│
│ запрос 1 HEAD + заголовок 4 КБ случайных символов ──► ответ
│ запрос 2 HEAD + ещё 4 КБ ──► ответ
│ …
│ запрос 10 HEAD + ещё 4 КБ (всего ≈ 40 КБ от нас) ──► ответ
│
▼
все 10 ответов → узел «выдержал» первый обрыв → узел не выдержал, дальше не ждём
Меряется то, что режет DPI, — объём, ушедший от нас по одному соединению. У узлов, для которых в списке указано имя сайта, оно подставляется в TLS; у остальных — example.com, как у dpi-detector. Сертификат не проверяется: важно, дожило ли соединение, а не чей это узел. На один запрос даётся 5 секунд.
Пример с тестового роутера, все 110 узлов, применена v4:
| Стратегия | Основной | Дополнительный | Итог |
|---|---|---|---|
| v4 (применена) | 40 | 97 из 110 | 137 |
| v7 | 41 | 96 из 110 | 137 |
| v1 | 39 | 96 из 110 | 135 |
| general (ALT13) | 40 | 85 из 110 | 125 |
| general (EXP) | 38 | 85 из 110 | 123 |
| v8 | 40 | 81 из 110 | 121 |
Здесь v7 выиграла основной проход на одну цель, а v4 отыграла её на дополнительном замере, и итог вышел равным. При равном итоге остаётся применённая стратегия — v4. Замер одной стратегии по 110 узлам занимает на роутере со 128 МБ несколько минут, а обход всё это время уже работает.
На странице автообхода, пока идёт сравнение: «Лучшая стратегия определится позже — идёт сравнение близких». Если стратегия сменилась: «Лучшая стратегия: …». Новый подбор или переустановка Zapret Manager фоновое сравнение прерывают. Настройка при этом не страдает: меняется она только в самом конце.
5. WARP: три туннеля и выбор колоний
WARP ставится со Steer. Туннелей три: у каждого свои ключи и своя точка входа, и все три в разных колониях, если это возможно. Трафик идёт через самый быстрый живой. Упал один — Steer сам переключается на другой. Упали все — трафик сервиса идёт напрямую, без туннеля.
Ключи
Cloudflare API ──► ключи выданы? ──► да ──► туннель готов
│ нет
▼
запасные генераторы (как на странице Mixomo)
Туннель — AmneziaWG, то есть WireGuard с маскировкой рукопожатия.
Разведка точки входа
Годность точки решает только поднятый туннель. Проверка по обычному HTTP к Cloudflare меряет не то: она идёт по TCP, а туннель — по UDP, и провайдер режет их по-разному. А колония в ответе — это колония входа, а не выхода. Поэтому каждая точка ставится на живой туннель и проверяется изнутри.
┌──────────────────────────────────────────────────────────────────────────┐
│ кандидаты: 14 подсетей Cloudflare │
│ 188.114.96–99.x · 162.159.192/193/195.x · 8.34.146.x · 8.39.x · … │
│ сначала «якоря» .1 каждой подсети, затем 10 случайных адресов │
│ (всего 24) │
└──────────────────────────────────┬───────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────────────┐
│ порты: 2408 · 500 · 4500 · 987 (вне игрового фильтра zapret) │
│ пробуются на первых трёх якорях, нужно два работающих: │
│ разведка идёт по первому, второй — запасной; │
│ ни один не ответил — «провайдер не выпускает ни один порт» │
└──────────────────────────────────┬───────────────────────────────────────┘
▼
для каждого кандидата:
┌──────────────────────────────────────────────────────────────────────────┐
│ а) поставить точку и дождаться рукопожатия (до 8 с) │
│ б) 3 пинга через туннель → потери и круг │
│ в) колония ИЗНУТРИ туннеля — по заголовку ответа Cloudflare │
│ г) HTTPS через туннель обязан проходить │
└──────────────────────────────────┬───────────────────────────────────────┘
▼
нашлись 3 точки вне колоний соседних туннелей — разведка останавливается,
туннель берёт лучшую из них по потерям и кругу
Про пункт г. На части сетей через туннель проходят только мелкие пакеты и порт 80, а TLS молчит. Такая точка «работает» по всем замерам, но сайты через неё не открываются.
Какую точку взять
Кандидаты раскладываются по корзинам. Берётся первая непустая, в ней — лучшая по потерям, а при равных потерях — по кругу.
┌───────────────────────────────┐
1 │ новая колония, HTTPS есть │ ← лучший вариант
├───────────────────────────────┤
2 │ та же колония, что у соседнего│ ← другой адрес в той же колонии лучше никакого
│ туннеля, но другой адрес │
├───────────────────────────────┤
3 │ колония не узналась │
├───────────────────────────────┤
4 │ российская колония │ ← выход внутри страны, за ТСПУ
│ DME SVX LED KJA REN OVB KZN │
│ AER VVO │
├───────────────────────────────┤
5 │ HTTPS через туннель не идёт │ ← последний запас
└───────────────────────────────┘
Российская колония выводит трафик из Cloudflare внутри страны, и дальше он идёт через те же ТСПУ, что и без туннеля. Поэтому через неё не снимается ни геоблок, ни остальные блокировки: туннель в DME работает, но пользы от него почти нет. Если часть туннелей всё же оказалась в российских колониях, журнал об этом предупреждает.
Живые туннели
Туннель, у которого рукопожатие было меньше трёх минут назад, при следующем подборе или «Применить» не пересканируется: это рвало бы соединения ради того же результата. Исключение — российская колония. Адреса WARP общие для многих колоний (anycast): на один и тот же адрес Cloudflare может со временем начать отвечать из другой колонии. На тестовом роутере туннель, выбранный в Хельсинки, через некоторое время стал выходить в Москве (DME). Поэтому колония живого туннеля каждый раз узнаётся заново, и российская разводится с нуля. Принудительно развести все три заново можно кнопкой «Сменить точки входа».
Запасной порт
Выбранная точка ставится на туннель ещё раз, уже насовсем. Если на этот раз рукопожатия нет, тот же адрес пробуется на втором найденном порту. Колония от этого не меняется: она зависит от адреса, а не от порта. Не ответил и второй — туннель в этот раз не поднимается.
Какой туннель первый
Туннели записываются в список лучшим первым: сначала по корзине, в которой нашлась точка (российская и «HTTPS не идёт» — в конце), потом по потерям и кругу. Первый живой из списка берут все, кому нужен один туннель: через него пробуются сервисы и качаются списки, мост Telegram идёт через него, пока тот отвечает. Steer сам меряет задержку и идёт через самый быстрый, а порядок решает, когда разница меньше 50 мс.
Если в этот раз ни один туннель не разведывался заново, порядок остаётся прежним. Иначе каждое «Применить» переставляло бы туннели по случайному дрожанию пинга, и ядро steer переводило бы трафик на другой туннель с обрывом соединений. Если хоть один туннель разведан заново, остальные перемеряются тремя пингами изнутри, и список строится с нуля.
6. Списки сервисов
Чтобы Steer знал, какой трафик вести в WARP, у каждого сервиса есть список доменов и подсетей.
каталог splify2-lists ──► ссылка на набор .srs издателя itdoginfo
(конкретная версия, одинаковая у всех роутеров)
│
▼
Steer разбирает набор на:
┌─────────────────┼──────────────────────────┐
▼ ▼ ▼
домены подсети подсети с сужением
│ │ по протоколу и портам
▼ ▼ │
fakeip в ответ DNS по адресу назначения ▼
голос Discord: в туннель идёт
только он, а не весь TCP к
подсетям Cloudflare
| Сервис | Набор |
|---|---|
| YouTube | youtube |
| Discord | discord (с сужением голоса) |
| Instagram, WhatsApp | meta (один набор на оба) |
| X | |
| Telegram | telegram |
| GitHub, ИИ-сервисы | своих наборов для туннеля нет |
Список скачивается сначала напрямую, потом через уже поднятый туннель: GitHub у многих закрыт. Если не скачался вовсе, берётся список, встроенный в Zapret Manager. Он хуже свежего, но лучше никакого.
7. ИИ-сервисы
ChatGPT, Claude, Gemini и похожие закрыты не провайдером, а самим сервисом: он смотрит, откуда пришли. Ни стратегия zapret, ни WARP в российской колонии (выход там внутри страны) это не снимают. Снимает DNS, который на имя сервиса отдаёт адрес своего прокси за границей.
запрос имени от устройства
│
▼
┌────────────────────────┐
│ DNS роутера (dnsmasq) │
└───┬────────────────┬───┘
│ домен из списка│ всё остальное
│ ИИ-сервисов │
▼ ▼
┌────────────────┐ ┌─────────────────────┐
│ свой DoH-клиент│ │ как раньше, ничего │
│ на порту 5359 │ │ не меняется │
│ → выбранный │ └─────────────────────┘
│ гео-резолвер│
└────────────────┘
- Только для доменов списка. Список публикует dns.malw.link (на момент написания — около 17 тысяч доменов после свёртки поддоменов). Остальной DNS роутера не меняется.
- Выбор резолвера. Гео-резолверы пула (на момент написания их 12) проверяются параллельно, по 8 разом (на роутере меньше 256 МБ — по 4), настоящим запросом к chatgpt.com. Берётся самый быстрый из тех, у кого ответил выданный прокси.
- Свой экземпляр. DoH-клиент для ИИ-доменов — отдельная служба. Чужую настройку https-dns-proxy (страница DoH, свои резолверы) она не трогает. Если пакет ставил сам автообход, а своей настройки до этого не было, служба пакета выключается: иначе она забрала бы весь DNS роутера.
- Сторож раз в 30 минут. Проверяет, открываются ли ИИ-сервисы. Перестали — резолвер подбирается заново. Если годного не нашлось, резолвер снимается, а сторож пробует снова раз в два часа. Сторож идёт своей задачей: журнал последнего автообхода он не трогает, и страница не показывает его как идущий автообход. Автообход, запущенный, пока сторож подбирает резолвер, сначала ждёт, когда тот закончит.
- Выключение. Кнопка «Выключить» снимает службу, файл dnsmasq и сторожа. Если удалить пакет https-dns-proxy или выключить службу zm-geodns в автозапуске, сторож при следующей проверке снимет себя сам.
- Удаление панели. DNS для ИИ-сервисов снимается целиком, вместе со службой: без сторожа умерший резолвер некому было бы заменить. Steer, туннели WARP и мост Telegram остаются.
8. Telegram и мост stgws
Когда нужен мост
Открытый сайт ещё не значит, что работает приложение: оно ходит к дата-центрам (ДЦ) Telegram по своему протоколу MTProto, и режут именно его. Поэтому автообход шлёт пяти ДЦ настоящий первый запрос протокола и ждёт ответа 5 секунд.
Telegram отмечен на странице Steer ──► через WARP
│ нет
▼
мост уже стоит и работает ──────────► через мост
│ нет
▼
сайт и все 5 ДЦ ответили ──────────► напрямую
│ нет
▼
ставится мост ──────────────────────► через мост
Как мост выбирает путь
Соединения устройств к адресам ДЦ Telegram роутер перехватывает и отдаёт мосту. Для каждого соединения мост идёт по цепочке от дешёвого к дорогому. Дешевле всего — напрямую к дата-центру: сначала без туннеля, потом через WARP. Веб-сокет через Cloudflare дороже любого из них, поэтому он идёт после:
┌──────────────────────────────┐
│ перехвачено — это MTProto? │
└──────┬────────────────┬──────┘
нет │ │ да
▼ ▼
┌────────────────────┐ ┌──────────────────────────────┐
│ насквозь как есть │ │ ① напрямую к ДЦ без WARP │
│ (через WARP, если │ │ если по замеру ДЦ открыт │
│ он есть) │ └──────┬────────────────┬──────┘
└────────────────────┘ ответил│ │ молчит / по замеру закрыт
▼ ▼
┌──────────┐ ┌──────────────────────────────┐
│ сессия │ │ ② напрямую к ДЦ через WARP │
└──────────┘ └──────┬────────────────┬──────┘
ответил│ │ молчит / нет WARP
▼ ▼
┌──────────┐ ┌─────────────────────────┐
│ сессия │ │ ③ веб-сокет через WARP │
└──────────┘ └──────┬───────────┬──────┘
поднялся│ │ нет / нет WARP
▼ ▼
┌──────────┐ ┌────────────────────┐
│ сессия │ │ ③ веб-сокет без │
└──────────┘ │ WARP, мимо zapret │
└──┬──────────┬──────┘
поднялся│ │ ни один путь
▼ ▼
┌──────────┐ ┌──────────────────┐
│ сессия │ │ ④ насквозь к ДЦ │
└──────────┘ │ как есть │
└──────────────────┘
- «ДЦ ответил» — прямые пути проверяются боем. Соединение по TCP ещё ничего не значит: при блокировке по адресу TCP обычно устанавливается, а дальше тишина. Путь живой, только если ДЦ заговорил в течение 4 секунд.
- Молчание не ломает следующий шаг. Пока ДЦ молчит, клиент успевает что-то отправить. Следующий путь получает начало разговора вместе с этими байтами, и для ДЦ поток начинается с начала.
- Веб-сокет. ДЦ2 и ДЦ4 идут на веб-сокет самого Telegram (web.telegram.org). ДЦ1, 3, 5 и отдельный ДЦ203, где тоже лежат файлы, — на домены-посредники за Cloudflare, как у tg-ws-proxy (Flowseal). На каждое соединение пробуется не больше трёх доменов, по две точки у каждого.
- Запас. Мост держит до 8 поднятых веб-сокетов наготове, по 2 на ДЦ, каждый не старше 40 секунд. Клиент получает соединение сразу, без рукопожатия. Запас пополняется только минуту после последнего обращения клиента.
- Мимо zapret. Соединения моста наверх идут в обход zapret роутера. Стратегия, подобранная под сайты, может портить TLS к Cloudflare: на тестовом роутере с одной из стратегий TCP к доменам-посредникам поднимался, а на TLS не приходило ни байта, и не грузились картинки из ДЦ1, 3, 5 и 203. Посредники для того и подобраны, чтобы открываться без ухищрений.
- Туннели для моста. Мост ходит через WARP сам, по списку туннелей, который пишет Zapret Manager после подъёма туннелей. Российские колонии в список не попадают. Список перечитывается, как только меняется, — мост перезапускать не нужно.
Отставки
Чтобы не платить ожиданием на каждом соединении, неудачный путь на время уходит в сторону:
| Что случилось | На сколько |
|---|---|
| ДЦ промолчал напрямую | 5 минут без шага ① для этого ДЦ |
| ДЦ промолчал через WARP | 5 минут без шага ② для этого ДЦ |
| к туннелю не дошло даже TCP | 30 секунд без WARP вовсе |
| домен-посредник отказал или не отдал данные | 1 минута без этого домена |
| web.telegram.org отказал | 20 секунд |
| клиент дважды за минуту ждал больше 3 секунд и ничего не получил | путь отставляется, как при отказе |
Когда все посредники на паузе, пробуется один, а не три. Неудавшееся соединение закрывается сразу, чтобы роутер не держал его минутами.
9. Как потом ходит трафик
Имя → адрес
┌──────────────────────────┐
│ УСТРОЙСТВО В СЕТИ │
└────────────┬─────────────┘
│ запрос DNS
▼
┌──────────────────────────┐
│ у Steer есть сервисы │
│ для WARP? │
└──────┬────────────┬──────┘
да │ │ нет
▼ │
┌─────────────────────┐ │
│ DNS-сервер Steer │ │
└──┬──────────────┬───┘ │
домен сервиса │ │ прочее│
для WARP ▼ ▼ ▼
┌──────────────┐ ┌─────────────────────┐
│ fakeip │ │ DNS роутера │
│ → потом WARP │ └──┬───────────────┬──┘
└──────────────┘ │ ИИ-домен │ прочее
▼ ▼
┌────────────────────┐ ┌────────────────────┐
│ свой DoH → │ │ обычный DNS │
│ гео-резолвер │ │ │
└────────────────────┘ └────────────────────┘
Соединения
┌──────────────────────────┐
│ УСТРОЙСТВО В СЕТИ │
└────────────┬─────────────┘
▼
┌──────────────────────────┐
│ куда идёт соединение? │
└──┬───────────┬────────┬──┘
адрес ДЦ Telegram, │ │ │ всё остальное
стоит мост │ fakeip или │
│ подсеть сервиса │
│ для WARP │
▼ ▼ ▼
┌─────────────┐ ┌───────┐ ┌──────────────┐
│ мост stgws │ │ WARP │ │ zapret │
│ (раздел 8) │ │ │ │ │
└─────────────┘ └───┬───┘ └──────┬───────┘
▼ ▼
┌───────────────────────────┐ ┌────────────────────────────────┐
│ самый быстрый живой │ │ устройство в исключениях или │
│ туннель │ │ трафик помечен «мимо zapret»? │
│ упал → следующий │ │ да → как есть │
│ упали все → напрямую, │ │ нет → первая подходящая │
│ без туннеля │ │ стратегия сверху: │
└───────────────────────────┘ │ Yv — YouTube │
│ Dv — голос Discord │
│ v / Flowseal — остальное │
└────────────────────────────────┘
10. Ограничения и оговорки
- Слабые роутеры. Каждая проверка — отдельный процесс на 3–4 МБ памяти. На роутере меньше 256 МБ проверки идут по 4 разом, а не по 8, поэтому подбор там дольше. На 128 МБ, где рядом работают Steer, мост Telegram и DNS со списком ИИ-доменов, восемь разом доводили до нехватки памяти.
- Путь моста через WARP — с tgws 0.3.0. В более ранних выпусках моста шагов через WARP из раздела 8 нет: там он ходит только веб-сокетом, мимо zapret.
- Фоновое сравнение различает немного. На тестовом роутере итоги лучших близких стратегий разошлись на единицы или совпали вовсе: 137 и 137, дальше 135. Такая разница близка к шуму, поэтому переключение требует строго большего итога и перепроверки сервисов.
- Внешние списки. Общий список целей, стратегии Flowseal и Yv, узлы dpi-detector, домены ИИ-сервисов и наборы .srs приходят из чужих репозиториев. Их состав и числа меняются без нашего участия.
- Проверка идёт с роутера. Автообход открывает сервисы запросами самого роутера. Путь устройства в сети может отличаться: например, у устройства из исключений zapret.
- Российская колония — только запас. Выход у неё внутри страны, за теми же ТСПУ, что и без туннеля: через неё не снимается ни геоблок, ни остальные блокировки, и мост Telegram через неё не ходит.