Skip to content

About

Наблюдатель за блокировками для OpenWrt с netshift/podkop: сам находит заблокированные сайты, проверяет опытом и добавляет в Local Domain List

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

21 Commits

Folders and files

Repository files navigation

blockwatch

Наблюдатель за блокировками для роутеров на OpenWrt с netshift или podkop.

Он сам находит сайты, которые у провайдера не открываются напрямую, но открываются через туннель, проверяет каждый опытом и добавляет подтверждённые в список netshift/podkop. Списки, которые вы ведёте вручную, остаются как были: blockwatch дополняет их тем, чего в них не хватает. Соединения при добавлении не рвутся — sing-box перечитывает список на лету.

Как это работает

Находит. Своя таблица nftables только считает признаки, ничего не блокирует и не перенаправляет:

признак что видно
сброс сервер присылает RST сразу после приветствия TLS
нет ответа SYN уходит, SYN-ACK не приходит
молчит наши пакеты с данными уходят, обратно — ни одного
обрыв соединение установлено и замерло: сервер не ответил даже на TLS; или передача встала на 12–24 КБ сразу в нескольких соединениях к адресу; или браузер переспрашивает, а ответа нет
замер одно соединение: запросы ушли, ответ встал на 2–24 КБ (слабый признак, в очередь последним)
обход медленный обход сайтов, которые в доме уже открывали

Учитывается только трафик мимо туннеля: то, что уже идёт через netshift/podkop, blockwatch не касается. Кандидатов на загруженной сети бывает сотня, поэтому первыми проверяются находки «1 из 2», затем свежие обрывы — то, во что люди упираются прямо сейчас.

Проверяет. Подозрение — ещё не блокировка. Для каждого кандидата blockwatch сам делает три запроса: к сайту напрямую, к конкретному адресу напрямую и к тому же адресу через туннель. Блокировкой считается только случай, когда напрямую не отвечают ни сайт, ни адрес, а через туннель страница приходит целиком. Передача, оборванная на середине, считается отказом, даже если заголовки успели прийти с кодом 200 — именно так выглядит самая незаметная блокировка. Обрыв случается после ~16 КБ от сервера, поэтому маленький ответ (корень CDN, редирект) blockwatch запрашивает ещё раз подряд в том же соединении, пока не наберётся больше: оборванное соединение на этом замрёт. Если соединение установилось и замерло, решает тот адрес, в который упирается браузер: проверка «сайта целиком» заново спрашивает DNS и может попасть на соседний, рабочий узел CDN. Добавляется находка только после двух совпадений в разных проверках: второе — не раньше чем через confirm_minutes (по умолчанию минута). Сразу после подтверждения адреса сайта на полчаса отправляются в sing-box: он по SNI пускает в туннель только этот домен, поэтому сайт открывается, даже если браузер или система закэшировали его настоящий адрес. На практике хватает открыть сайт, подождать минуту-две и обновить страницу.

Имя сайта берётся из журнала запросов dnsmasq — то, которое спросил браузер, даже если ответ пришёл через цепочку CNAME (у сайтов на Vercel, Cloudflare и CDN адрес приходит на служебное имя хостинга). Вердикт хранится на пару «адрес + имя»: за одним адресом хостинга живут сотни сайтов. Если на подтверждении не ответил и туннель, набранное совпадение не сбрасывается (один раз) — вдруг туннель сбоил сам.

Добавляет. Подтверждённые домены дописываются в /etc/blockwatch/domains.txt (Local Domain List netshift/podkop), а адреса — без имени или общие, где живут сотни сайтов (Cloudflare, Vercel, CDN), — в /etc/blockwatch/subnets.txt (Local Subnet List). blockwatch вписывает их ещё и в уже собранные списки sing-box и в nft-множество бэкенда, поэтому сайт начинает открываться через пару секунд, без перезапуска.

Убирает. Домены из списка раз в recheck_hours открываются напрямую; открылся целиком remove_after раз подряд — домен уходит из списка. Адрес так не перепроверить (трафик к нему уже в туннеле), поэтому у адреса срок ip_ttl_days. Вручную — кнопкой «Убрать» на вкладке или blockwatch remove.

Что не делает

  • Не видит геоблоки — «сервис недоступен в вашей стране». Для роутера такой сайт выглядит исправным: соединение и TLS проходят, отказ приходит внутри шифрованного ответа.
  • Не добавляет видеоузлы Google, имена ваших собственных серверов из конфига sing-box и, как правило, российские домены (.ru, .su, .рф): через зарубежный выход они часто отказывают. Исключение — российский домен на зарубежном хостинге, который провайдер режет обрывом (так бывает с Vercel и Cloudflare): если соединения к нему обрываются на середине, blockwatch его проверяет и добавляет, когда напрямую сайт не открывается, а через туннель открывается (zones_on_cut).
  • Не добавляет адреса Google и YouTube (ни по именам, ни по сетям самого Google), частные адреса и адреса ваших прокси-серверов.
  • Не трогает домены и адреса, которые уже есть в каком-либо списке netshift/podkop, — ни в туннеле, ни в исключениях. Если YouTube у вас нарочно идёт мимо туннеля, так и останется.
  • Не видит сайтов, если браузер спрашивает DNS мимо роутера (Secure DNS / DoH в браузере): тогда и netshift направляет их только по адресам.
  • Не меняет настройки netshift/podkop и не перезапускает их сам — кроме команды blockwatch hook, которую вы запускаете явно, и самовосстановления auto_rehook, если вы его включите.
  • Смотрит только IPv4.

Требования

  • OpenWrt 24.10 или новее (apk и opkg поддерживаются оба)
  • netshift или podkop. Чтобы проверять, открывается ли сайт через туннель, blockwatch берёт служебный socks-вход sing-box (он есть при включённой загрузке списков через прокси), а если его нет — интерфейс секции типа vpn (например AWG2): так netshift ставит и Zapret-Manager. Можно задать и вручную: socks или tunnel_interface в «Настройках».
  • Zapret-Manager (Forkozz) удаляет локальные файлы-списки при каждом сохранении секции, поэтому там blockwatch hook подключает списки как внешние по ссылке: http://127.0.0.1/blockwatch/domains.txt и subnets.txt отдаёт веб-сервер роутера (uhttpd), и Forkozz их сохраняет. Новые домены и адреса blockwatch сразу дописывает в живые наборы sing-box, а при каждом заходе сверяет их со своими файлами — так ничего не теряется, даже если список не скачался. Режим выбирается сам (hook_mode: auto, local, remote).
  • dnsmasq как DNS-сервер роутера (у netshift и podkop так по умолчанию)

Установка

sh -c "$(curl -fsSL https://raw.githubusercontent.com/xDarkOne/blockwatch/main/install.sh)"

Установщик сам поставит недостающие jq и curl, разложит файлы и в конце покажет результат blockwatch doctor.

Затем подключите списки к нужной секции netshift/podkop:

blockwatch hook main

Команда подключает оба списка — доменов и адресов — и один раз перезапускает netshift/podkop, чтобы он их собрал. Если подключён только список доменов (установка до версии с адресами), повторный hook докинет список адресов. Вручную: секция → Local Domain Lists → /etc/blockwatch/domains.txt и Local Subnet Lists → /etc/blockwatch/subnets.txt → сохранить.

Смотреть, что происходит: LuCI → Службы → Blockwatch.

Ссылки и файлы списков для ручного подключения (например, в Forkozz) показывают вкладка «Обзор» и blockwatch doctor: http://127.0.0.1/blockwatch/domains.txt и http://127.0.0.1/blockwatch/subnets.txt.

Что меняется в системе

что зачем при удалении
журнал запросов dnsmasq включается узнать имя сайта по адресу возвращается как было
буфер системного журнала — не меньше 512 КБ (в ОЗУ) чтобы имена не вытеснялись раньше, чем их прочитают возвращается как было
учёт трафика conntrack (если был выключен) распознавать обрывы возвращается как было
задание cron раз в 2 минуты заходы наблюдателя удаляется
таблица nftables inet blockwatch только счётчики удаляется

Рабочее состояние хранится в /tmp, чтобы не изнашивать флеш. На флеш пишутся списки доменов и адресов, журнал находок (последние 500 записей) и вердикты — раз в час или сразу после находки.

Команды

blockwatch doctor          проверить установку: бэкенд, socks-вход, туннель, проблемы
blockwatch report [all]    найденные блокировки (all — вместе с живыми и лежащими)
blockwatch hook [секция]   подключить списки доменов и адресов к netshift/podkop
blockwatch unhook          отключить оба
blockwatch export          перенести подтверждённое прямо сейчас
blockwatch remove <x>      убрать домен или адрес из списка
blockwatch status          состояние в JSON (для вкладки LuCI)

Журнал находок: /etc/blockwatch/blockwatch.log.

Настройки

/etc/config/blockwatch:

параметр по умолчанию
enabled 1 выключить заходы
backend auto netshift, podkop или автоопределение
auto_export 1 0 — только находить, ничего не добавлять
confirm_minutes 1 второе подтверждение находки — не раньше чем через столько минут
max_per_day 30 предел добавлений в сутки
max_domains 500 предел всего списка: дальше новые не добавляются, на вкладке предупреждение
auto_remove 1 убирать из списка то, что снова открывается напрямую
recheck_hours 24 как часто перепроверять каждый домен списка (после удачной проверки — через 6 часов)
remove_after 3 сколько удачных прямых проверок подряд нужно, чтобы убрать домен

| auto_rehook | 0 | для подключения локальными файлами: вернуть списки, если они пропали из настроек бэкенда, и перезапустить его (не чаще трёх раз в час) | | max_subnets | 200 | предел списка адресов | | ip_ttl_days | 30 | срок адреса в туннеле | | never_ip_suffix | Google, YouTube | адреса с такими именами не добавляются никогда |

Всё это меняется и на вкладке LuCI → Службы → Blockwatch, во вкладке «Настройки». Там же сводка, поиск по спискам, журнал и кнопка «Убрать» у каждого домена и адреса (blockwatch remove <домен|адрес> в консоли).

Адреса. На одном адресе Cloudflare или CDN живут сотни сайтов, а в соединении имени сайта нет — только адрес, и имя из журнала DNS бывает чужим. Поэтому, если адрес без имени или общий, а блокировка подтверждена по самому адресу, в туннель уходит адрес: он дописывается в /etc/blockwatch/subnets.txt (подключается как Local Subnet List), в набор sing-box и в nft-множество netshift/podkop — на лету. Проверить адрес напрямую после этого нельзя, поэтому у него срок ip_ttl_days; потом он возвращается на прямую и, если его всё ещё режут, находится заново. Адреса Google и YouTube, частные, свои прокси-серверы и адреса с именами из стоп-списка не добавляются никогда.

Перепроверка списка. Блокировки снимают так же, как ставят, поэтому blockwatch время от времени открывает каждый домен из своего списка напрямую — по настоящему адресу, мимо туннеля. Открылся целиком remove_after раз подряд — домен уходит из списка и из sing-box на лету; вернётся блокировка — найдётся заново. Домены, чей адрес уже есть в IP-списках netshift/podkop, так не проверить: трафик к ним уходит в туннель и с самого роутера. Они остаются в списке и помечены на вкладке.

Сколько места занимает: рабочее состояние в ОЗУ (/tmp/blockwatch) — около 300 КБ и больше не растёт; на флеше — список доменов (~40 байт на домен), журнал находок (последние 500 записей) и вердикты, которые сохраняются раз в час. | never_suffix | ru su xn--p1ai googlevideo.com gvt1.com | что не добавлять никогда | | zones_on_cut | 1 | записи без точки (ru, su, xn--p1ai) — целые зоны: домен из них всё же проверяется, если к нему видны обрывы | | socks, tunnel_interface, dns, fakeip_range, fakeip_mark | из настроек бэкенда | ручная настройка, если автоопределение не справилось |

Всё, чем netshift и podkop отличаются друг от друга, — имена таблиц, метки, адреса — blockwatch читает из их собственного constants.sh и конфига sing-box.

Удаление

sh -c "$(curl -fsSL https://raw.githubusercontent.com/xDarkOne/blockwatch/main/install.sh)" -- uninstall

Список доменов и журнал останутся в /etc/blockwatch. Чтобы убрать всё, включая подключение к netshift/podkop, добавьте --purge.

Проверка

tests/run-rootfs.sh 24.10 и tests/run-rootfs.sh 25.12 прогоняют установку, распознавание netshift и podkop, подключение и удаление в корневой ФС OpenWrt соответствующей версии. То же самое выполняется в CI при каждом изменении.

Лицензия

GPL-2.0, как у netshift и podkop.

About

Наблюдатель за блокировками для OpenWrt с netshift/podkop: сам находит заблокированные сайты, проверяет опытом и добавляет в Local Domain List

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages