Весь разговор с ядром 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)
- Версия движка Steer — 1.5.8: таблица правил заменяется одним действием, при упавших
туннелях трафик каналов идёт через zapret. Запасная версия tgws — 0.3.1.
- Установленный движок раньше не обновлялся никогда: при «уже установлен» установка
выходила сразу. Теперь движок, который поставил Zapret Manager, обновляется до его
версии — при установке Steer и в начале автообхода. Чужой движок (splify2) не трогается.
Работающий Steer после обновления перезапускается, а не выключается.
Сторож DNS для ИИ-сервисов шёл задачей redbtn: затирал журнал последнего автообхода и выглядел
на странице идущим автообходом. Теперь у него своя задача redbtn_geo; автообход и кнопка
«Подобрать DNS заново» ждут его, «Выключить» просит повторить. После неудачного подбора резолвер
снимался, и сторож молчал навсегда при живой строке cron — теперь пробует снова раз в два часа,
а если пакет удалён или zm-geodns выключен в автозапуске, снимает свою строку сам. Подбор
резолвера — не больше RB_PARALLEL проб разом.
Удаление панели зовёт redbtn_panel_gone: служба zm-geodns, её файл dnsmasq и строка cron
снимаются. Steer, туннели и warp.lst моста остаются — они переживают удаление панели намеренно.
Замер стратегий: цели внешнего набора без схемы идут по https://, а не по HTTP на 80-й; 451 и
000 — отказ, как в _rb_check_one; файл исключений качается, только если его нет или он пуст.
Мёртвое: запись «pkg tgws» в owned, geoblock.lst в установщике, состояние off и ветка для
снятых в Steer сервисов, до которой подбор не доходил.
warp.up писался в порядке номеров туннелей, хотя комментарий обещал «лучший первым», а порядок
читают все, кому нужен один туннель: _st_warp_first, мост Telegram (warp.lst — первый живой) и
движок (devices в spec решают ничьи в пределах допуска prefer: latency). Разведка теперь отдаёт
ключ качества (разряд запаса, потери, круг), и _st_warp_order ставит туннели по нему. Если ни
один туннель не разведан заново, порядок прежний: перестановка по дрожанию пинга меняла бы spec
и перезапускала движок на каждом «Применить».
Второй найденный порт из warp.ports стал запасным: не дала точка рукопожатия при окончательной
привязке — тот же адрес пробуется на нём, прежде чем туннель сдаётся.
_st_warp_handshake, _st_warp_hs_epoch и _st_warp_colo нигде не вызывались — убраны.
- Фоновое сравнение при равном итоге переключало на стратегию, которая шла в списке первой:
на тестовом роутере v4 и v7 сошлись на 137, подбор ставил v7, видел, что сервисов
открывается меньше, и возвращал v4. Теперь при равенстве применённая остаётся.
- Российская колония: выход у неё внутри страны, за теми же ТСПУ, — через неё не
снимается ни геоблок, ни остальные блокировки. Так и сказано в журнале.
- docs/autobypass.md — как устроен автообход: порядок подбора, перебор стратегий и счёт,
сравнение близких, выбор колоний WARP, списки, ИИ-сервисы, мост Telegram, ограничения.
- Список туннелей WARP для stgws (/etc/stgws/warp.lst, без российских колоний) пишется
после подъёма туннелей и стирается при выключении и удалении Steer.
- Туннели проверяются в конце любого подбора, если стоит Steer, даже когда сервисам WARP
не понадобился: мосту они нужны всегда, а российский туннель так разводится заново.
- Нажатая кнопка снимает ручные выключения: выключенный Steer и сервисы, снятые на его
странице, снова участвуют в подборе.
- Дополнительный замер: --fail-early и пять секунд на запрос — срок curl считался на
каждый из десяти запросов, и стратегия, рвущая соединения, мерилась по часу.
- pkill в busybox OpenWrt нет — процессы ищутся через ps; установщик снимает фоновое
сравнение всем деревом процессов, иначе его цикл продолжал запускать curl.
- В фоновое сравнение идут стратегии не ниже 90 % от основного счёта лучшей; первыми —
открывшие больше адресов неоткрывшихся сервисов, всего до шести. Итоговый счёт =
основной + дополнительный, побеждает больший.
- Дополнительный замер — как в dpi-detector (core/tcp16_scanner.py): по одному
соединению десять запросов HEAD с X-Pad по 4 КБ, SNI из списка или example.com, узел
засчитывается, если соединение пережило все десять. Прежнее «скачать 64 КБ с голого
адреса» у всех стратегий давало одинаковые 3 из 37. Узлы — весь список, 110.
- Живой туннель WARP в российской колонии разводится заново: Cloudflare со временем
стал отвечать на прежний адрес из DME, а туннель держался, потому что жив.
- Задача считается живой, только пока в её журнале нет __DONE__: номер завершившегося
подбора достался проверке гео-DNS из cron, и установщик отказывался ставиться.
- Установщик под set -e молча обрывался на kill уже завершившегося фонового сравнения.
- Полный подбор после быстрого не проверял ни одной стратегии: перебор шёл только когда
что-то не открывалось, а после быстрого открывалось всё. Теперь полный идёт всегда.
- Бэкенд из rpcd работал с umask 077, и списки zapret, которые он переписывал, получали
права 600: nfqws после сброса прав их не читал, и каждая стратегия «не запустилась», а
общий обход после перезапуска молча терял списки. umask 022, права чинятся при
перезапуске zapret и перед подбором.
- Счёт стратегий — общий («открылось N из 54»); при равном выше та, что открыла больше
адресов неоткрывшихся сервисов.
- Равные лучшие сравниваются уже после подбора, в фоне, по узлам CDN из списка
dpi-detector (Runnin4ik): обход к этому моменту работает, на странице — «Лучшая
стратегия определится позже». Стратегия меняется, только если другая набрала строго
больше и сервисов открывается не меньше.
- На роутерах меньше 256 МБ пробы идут по четыре, а не по восемь.
- Запасная версия tgws — 0.2.9.
Градиент кнопки повторялся под прозрачной рамкой, и слева виднелся его
противоположный конец. Фон теперь начинается от края рамки и не повторяется.
Название движка в текстах интерфейса — Steer.
Живой туннель считался негодным, если его колония совпала с соседней, и на каждом
применении правил его заново сканировали и переподключали — хотя такую колонию и выбрала
разведка, когда другой не нашлось. Автообход вдобавок звал подъём туннелей второй раз через
_st_apply, сразу после своего. Развести туннели по колониям заново — «Сменить точки входа».
Автообход:
- «Стоп» оставлял флаг остановки страницы steer, и следующий подбор сразу гасил все туннели
WARP — теперь проход снимает все три флага.
- Имена из чужого hosts-файла (dns.malw.link) шли в конфиг dnsmasq без проверки: `#`, `*`,
`\r` от CRLF уводили весь DNS в георезолвер или ломали dnsmasq. Фильтр имён хостов —
при скачивании и ещё раз в init zm-geodns.
- trap по INT/TERM теперь с выходом; пробы ждут свои процессы, а не всех детей (рядом живёт
nfqws стратегии); остатки прошлого подбора (nfqws на очереди 8397) убираются в начале;
не встали правила изоляции — подбор честно отказывает.
- DNS для ИИ-сервисов: резолвер, не открывший их, выключается; пропал резолвер — снимается
и файл dnsmasq; порт 5359 вне серии https-dns-proxy человека; restart не перезапускает
dnsmasq дважды; «Выключить» не удаляет https-dns-proxy, если им пользуется страница DoH;
сторож и кнопка идут задачей и сторож ставится и с кнопки.
- Стоп посреди перепроверок возвращает прежнюю стратегию; стратегия для YouTube
сравнивается с контролем; имена стратегий Flowseal в журнале целиком.
steer:
- Лучшая точка ставилась без нового рукопожатия — туннель оставался на последнем
опробованном адресе; теперь сессия сбрасывается.
- «Стоп» гасил живые туннели и не прерывал задачу — теперь ничего не пишется и не гасится.
- После перезапуска туннелей спека пересобирается (новые туннели попадают в devices).
- Перебор портов слышит «стоп» и ограничен тремя адресами; кэш портов сбрасывается при
подборе заново; при splify2 удаление не трогает его движок и спеку; выключенный steer не
поднимается «Исправить DNS»; после «Стопа» туннели не встают при перезагрузке (auto=0);
сбой одного набора .srs не лишает списков соседний сервис; списки свежие на каждое
«Применить»; имена в спеке экранируются; id сервисов проверяются.
Интерфейс: «работает» не показывается при мёртвом туннеле; «Через WARP» считает сервисы,
а не каналы; после «Выключить» автопроверка не рисует поломку; при splify2 карточки и
кнопки скрыты; выбор не теряется при ошибке; перезагрузка страницы показывает текущую
операцию; звук не выключается навсегда без нажатия; подсказка «установите steer» не
показывается, когда steer стоит; .catch у запросов.
Стояла на left: -14px — ровно на ширину отступа боковой панели, то есть вплотную к краю окна,
и со скруглением только справа выглядела обрезанной. Теперь в зазоре, скруглена целиком.
Страница steer была рассчитана на один туннель: одна точка входа, один сервер, одна
«последняя связь», а «Проверить» смотрело только первый туннель. Теперь:
- steer_status отдаёт tunnels[] — у каждого туннеля точка, колония из последней разведки,
свежесть рукопожатия и трафик; карточка «Туннели WARP» показывает их по одному, в шапке —
«работает N из 3» и колонии живых. Один туннель — прежний вид.
- «Проверить» проверяет каждый туннель: HTTPS-трассировка с warp=on — ок; не прошла, но
CF-RAY по HTTP отвечает — «соединение есть, но HTTPS через туннель не проходит» (другая
поломка и другое действие); иначе — трафик не идёт. Упал один из трёх при живых остальных —
замечание, а не поломка: steer переключится сам.
- Кнопки названы во множественном числе: «Перезапустить туннели», «Сменить точки входа».
- Разведка требует HTTPS через туннель: на части сетей через туннель проходят только мелкие
пакеты и порт 80, и точка, годная по рукопожатию, потерям и CF-RAY, сайтов на устройствах
не открывала. Такие точки — в последний запас.
Код 1.38 ищет ролики в files/AutoBypass и их список в videos.txt — ролик переехал туда из
files/RedButton, каталог заведён. Запасной источник в форке смотрит туда же.
Запасная версия tgws (если GitLab не ответил) — 0.2.8: в ней починены картинки Telegram (ДЦ203).
Поверх интерфейса 1.38 — то, чего ему не хватало в бэкенде:
- Подбор стратегий zapret больше не перебирает их на всей сети. Кандидаты и цели те же,
менеджерские, но каждая стратегия мерится своим nfqws на очереди 8397, куда попадает
только трафик проверки (порты 20000-20999); сеть до конца подбора живёт на прежней
настройке, победитель уходит один раз, в конце. Устройство — как у тестера splify2.
- Страница steer держит три туннеля WARP (zmwarp, zmwarp2, zmwarp3) со своими
регистрациями. Точка выбирается методом warpscout, как в brb: настоящее рукопожатие на
живом интерфейсе, потери и круг, колония изнутри туннеля по CF-RAY; колонии разводятся,
российские — в запас, при нехватке — та же колония через другой адрес. В спеке один выход
со всеми живыми туннелями и prefer: latency. Все интерфейсы заводятся одним reload до
разведки — иначе netifd перезапускал соседние туннели посреди неё. Кнопки перезапуска,
смены точки и новых ключей действуют на все три; статус показывает колонии живых.
- Списки для туннеля — наборы .srs каталога splify2-lists (itdoginfo) с тегом из lists.json,
разложенные steer srs-read; качаются напрямую или через уже поднятый туннель, при неудаче —
списки пакета. Сужение Discord (udp и порты голоса) — отдельным каналом схемы 2.
- ИИ-сервисы открывает DNS, а не туннель: в WARP они больше не идут. Резолвер выбирается из
пула geo (brb плюс dns.yo1nk.app) настоящим запросом к chatgpt.com через его DoH и
работает своим экземпляром https-dns-proxy (zm-geodns) только для доменов списка
dns.malw.link; остальной DNS и /etc/config/https-dns-proxy не меняются. Сторож раз в
30 минут подбирает заново, если сервисы перестали открываться. На странице — «через DoH»,
какой DNS выбран, «Подобрать DNS заново» и «Выключить».
- Проверка «DoH перехватывает DNS» смотрела на любой процесс https-dns-proxy и принимала
zm-geodns за перехват; теперь — на службу пакета, и выключенную службу не поднимает.
Проверено на OpenWrt 25.12.5 в QEMU с чистого образа: steer поставил три туннеля,
автообход открыл закрытые по адресам Instagram и WhatsApp через WARP (клиент за LAN — 200),
ИИ-сервисы — через DoH, страницы автообхода и steer в Web UI без ошибок.
- ИИ-сервисы больше не идут в подбор zapret и WARP: геоблок снимает только резолвер.
Резолвер выбирается из пула geo BigRedButton плюс dns.yo1nk.app: каждому шлётся
настоящий запрос к chatgpt.com через его DoH (curl --doh-url), и берётся самый быстрый
из тех, чей прокси ответил без отказа. Он работает своим экземпляром https-dns-proxy
(служба zm-geodns, 127.0.0.1:5055), а dnsmasq отдаёт ему только домены из списка
dns.malw.link (файл hosts его репозитория, 17 тысяч имён после сворачивания поддоменов).
Остальной DNS роутера и настройка /etc/config/https-dns-proxy не меняются. Раз в 30 минут
сторож проверяет, открываются ли сервисы, и при отказе подбирает резолвер заново.
- Если пакет https-dns-proxy ставит кнопка, его служба выключается, только когда настройки
до установки не было: иначе dnsmasq оставался бы на мёртвых портах.
- Пробы остальных сервисов разрешают имена своим DoH (Cloudflare, Google, Яндекс — первый
ответивший), а не системным DNS: тот может отдавать подмену провайдера или fakeip
вышестоящего роутера.
- Списки для туннеля — наборы .srs каталога splify2-lists (itdoginfo: youtube, discord,
meta, twitter) с тегом из lists.json, разложенные `steer srs-read`; качаются напрямую или
через уже поднятый туннель, при неудаче — списки из пакета. Сужение Discord (udp и порты
голоса) — отдельным каналом схемы 2; общий набор двух сервисов попадает в спеку один раз.
- Движок, поставленный кнопкой, включается только вместе с правилами: с пустой спекой он
всё равно заворачивает DNS сети на свой резолвер, и на тестовом роутере запросы клиентов
к роутеру по IPv6 уходили в тайм-аут.
- После установки пакетов бэкенд проверяет, что объект zapret-manager есть в ubus:
post-install luci-proto-amneziawg перезагружает rpcd, и страница получала «Object not
found». Страница, потеряв роутер, ждёт его и продолжает следить за подбором.
- Журнал: каждый сервис сразу после проверки, стратегии тестера, подбор для YouTube,
точки WARP.
- Плеер вынесен в отдельный блок «А пока подбираем…» на всю ширину страницы, журнал —
своим блоком под ним.
- Остановка срабатывает между сервисами, а неполный победитель остановленного тестера не
применяется. Раньше после «Остановить» подбор успевал применить стратегию и перепроверить
сервисы.
- Установщик отказывает, пока идёт подбор: он стирает каталог задач, и вместе с ним
пропадали журнал и флаг остановки — подбор продолжался невидимым и не останавливался.
- Пока идёт подбор, над журналом играет ролик; после окончания плеер убирается и ничего
не качает. Звук выключается отдельной кнопкой рядом с плеером, выбор запоминается.
Если браузер не даёт играть со звуком, ролик идёт без звука.
- Журнал пишет по ходу: каждый сервис сразу после проверки, каждую стратегию тестера и
сколько она открыла, подбор для YouTube (раньше шёл молча, минутами), каждую
пробуемую точку WARP. На стенде самая длинная пауза без новых строк — 15 секунд.
- Снятие настроек помечается своей фазой, и открытая в это время страница не включает
ролик.
erdekagi — «Больше чем цена на Aviasales», с разрешения автора. H.264 480p и AAC,
2 МБ, с быстрым стартом: страница кнопки показывает его, пока идёт подбор.
Новый раздел «Красная кнопка» в LuCI и в Web UI на порту 7788. Роутер сам проверяет
восемь сервисов (YouTube, Discord, Instagram, WhatsApp, X, GitHub, ИИ-сервисы, Telegram)
и берёт каждому самый дешёвый работающий способ: напрямую, через Zapret, через WARP или,
для Telegram, через веб-сокет. Каталог сервисов и идея — из BigRedButton
(gitlab.com/xyzmean/brb), логика переписана:
- Стратегию zapret подбирает тестер менеджера (do_test_run), а применяют его же функции
strategy_set_v / strategy_set_flowseal / strategy_set_youtube. Своего перебора nfqws,
как в brb, нет. Если стратегия открыла меньше сервисов, чем было, прежняя настройка
возвращается.
- То, что zapret не открыл, уходит в туннель AmneziaWG к WARP через движок steer 1.5.7
(спека с выходом kind=interface). Точка входа выбирается по рукопожатию и данным через
туннель; российские колонии берутся только в запас. Туннелю заводится зона firewall
с NAT и mtu_fix, без которой устройства сети через туннель не ходили.
- Telegram проверяется настоящим запросом MTProto (req_pq_multi) к пяти дата-центрам;
при молчании ставится микропакет tgws.
- DNS роутера кнопка не трогает. Если DNS over HTTPS перехватывает порт 53 у резолвера
движка, это показывается на странице, а исправляется только по нажатию.
- Чужая спека steer и splify2 не перезаписываются. Всё, что поставлено и изменено,
записывается в /etc/zm-redbtn/owned; «Снять настройки» снимает ровно это.
- Тест стратегий на странице Zapret не запускается, пока идёт подбор кнопки.
Проверено на OpenWrt 25.12.5 x86_64 в QEMU: быстрый подбор около шести минут; сервис,
закрытый по адресам, открылся через WARP у клиента за LAN (fakeip, счётчики канала и
трафик туннеля растут); снятие убирает интерфейс, зону, steer, tgws и AmneziaWG.