Skip to content

Repository files navigation

Blockcheck Wrapper

CI GitHub Release License: MIT Downloads

Быстрая обёртка над blockcheck2 для параллельного поиска стратегий(и ещё кое-что)

Зачем

blockcheck2.sh blockcheckw
Скорость ~90 мин (TLS 1.2) ~2 мин (1024 воркера)
Пропускная способность ~1 стратегия/сек ~150 стратегий/сек
Язык Bash + curl Rust (compiled binary)
TLS fingerprint curl/OpenSSL rustls
Установка часть zapret2 отдельный бинарь, install.sh

Ключевые возможности

Параллельный подбор стратегий — один процесс nfqws2 держит до 1024 стратегий одновременно как профили (--filter-mark), а не как отдельные процессы. Диспетчеризация — два статических правила nftables на весь прогон, независимо от числа воркеров.

Дифференциация блокировокstatus автоматически определяет тип блокировки для каждого домена: SNI blocked (DPI, zapret может обойти) vs IP blocked (нужен VPN). 1000+ доменов за 30 секунд.

  youtube.com       ✓  812 Kbps
  rutracker.org     ✗  SNI blocked
  discord.com       ✗  IP blocked

16KB DPI detection — некоторые DPI пропускают TLS handshake, но обрывают соединение после ~16KB данных. check ловит это автоматически — стратегия, которая грузит страницу но ломает видео, не пройдёт верификацию.

Pipe между командамиuniversal → check в одну строку. JSON-отчёты совместимы между командами.

blockcheckw -w 512 universal --domain-list blocked.txt | blockcheckw check -d rutracker.org --take 10

9 архитектур — x86_64, x86, arm64, arm, mips, mipsel, mips64, ppc, riscv64. Работает на роутерах с 256MB RAM.

Команды

Команда Что делает
scan Параллельный поиск рабочих стратегий для одного домена
universal Поиск стратегий, работающих на нескольких доменах
check Верификация с data transfer (32KB+, 16KB DPI detection)
status Проверка доступности + дифференциация SNI/IP блокировок
benchmark Подбор оптимального числа воркеров
--version Текущая версия + проверка обновлений на GitHub
--upgrade Обновление до последнего релиза

У каждой команды свои флаги — таймауты, DNS-режим, число проходов:

blockcheckw <command> --help

Quickstart — таблицы всех флагов по командам, установка, решение проблем.

Классификация блокировки (block_type)

scan и status сообщают тип блокировки в JSON-поле block_type — это сетевой вердикт, по которому потребитель решает, что делать, не перепроверяя:

block_type Что произошло Помогает ли десинк
not_blocked доступно без обхода
throttled HEAD проходит, но загрузка режется в ~16-19КБ (DPI-cap) возможно
sni_blocked TCP/TLS-рукопожатие прошло, данные режутся (DPI по SNI) да
ip_blocked прямой SYN не прошёл, причина не уточнялась нет (нет рукопожатия)
syn_blocked SYN дропнут на этой линии, но хост жив через прокси нет (нужна смена egress)
host_dead недостижим и напрямую, и через прокси нет
dns_failed резолв не удался

Рядом — отдельное булево поле dns_spoofed (ортогонально block_type): system-DNS отравлен (расходится с DoH на блокируемом домене). При auto-режиме скан сам откатывается на чистые DoH-IP, поэтому block_type меряется по ним — домен может быть dns_spoofed: true И not_blocked одновременно. Сигнал «не доверяй system-DNS, бери DoH».

Флаг --alive-via <endpoint> (только scan)

Когда прямой SYN дропается, нельзя отличить «SYN режут на твоей линии, а хост жив» от «хост мёртв». --alive-via даёт прокси, через который scan делает точечную проверку живости IP-blocked хоста (но не маршрутизирует через него сам скан — для этого --via). Результат: ip_blocked уточняется в syn_blocked (жив через прокси) либо host_dead (мёртв везде). Формат эндпоинта — как у --via (socks5://host:1080); должен быть прокси. Если прокси недостижим, разбиение отключается и остаётся ip_blocked. Без флага поведение не меняется.

Архитектура параллелизма

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

Один процесс nfqws2 держит до 1024 стратегий одновременно (--profiles-per-instance, по умолчанию 1024) — каждая стратегия становится профилем движка, а не отдельным процессом. Профиль выбирается по метке пакета (--filter-mark), поэтому очередь NFQUEUE и nft-правила одни на весь прогон, независимо от числа воркеров.

Каждый воркер получает уникальный fwmark (SO_MARK на TCP-сокете), но марка выбирает ПРОФИЛЬ внутри процесса, а не очередь и не процесс:

Worker 1: fwmark=0x20000001 → nfqws2 профиль 1 (--filter-mark=1/0xFFFF)
Worker 2: fwmark=0x20000002 → nfqws2 профиль 2 (--filter-mark=2/0xFFFF)
...
Worker N: fwmark=0x2000_NNNN → nfqws2 профиль N — все на ОДНОЙ очереди, в ОДНОМ процессе

Поток пакетов:

reqwest SYN (mark=0x20000001)
  → postnat: mark & DESYNC == 0, mark & 0x20000000 != 0 → ct mark = mark | DESYNC, queue num Q
    → nfqws2 видит mark, выбирает профиль по --filter-mark, десинхронизирует
      → nfqws2 реинжектит с mark=DESYNC_MARK
        → predefrag: DESYNC_MARK → notrack

SYN/ACK (incoming)
  → prenat: ct mark & 0x20000000 != 0 → meta mark = ct mark & 0x2000FFFF, queue num Q
    → nfqws2 видит восстановленную марку, определяет TTL (autottl) тем же профилем

Планов на прогон столько, сколько нужно, чтобы разложить корпус стратегий по profiles_per_instance: например, на корпусе из 13 943 стратегий и K=1024 это 15 планов (а не 13 943 запуска движка) — независимо от того, 8 воркеров используются или 1024.

Что НЕ делает curl

В отличие от ванильного blockcheck2, blockcheckw не использует curl. HTTP-запросы выполняются in-process через hyper + tokio-rustls + socket2:

  • socket2 — создаёт TCP-сокет, ставит SO_MARK до connect() (SYN уже помечен)
  • tokio-rustls — TLS handshake с контролем версии (TLS 1.2 only / TLS 1.3 only)
  • hyper — HTTP/1.1 запрос поверх TLS-стрима

Это убирает ~600 fork+exec процессов curl за скан, и даёт полный контроль над сокетом.

Сильные стороны

  • Скорость: 100-150x ускорение по сравнению с последовательным blockcheck2

  • Масштабируемость: диспетчеризация — два статических правила nftables на весь прогон, не карта и не цепочка на воркер; 1024 воркера не добавляют nft-правил по сравнению с 8

  • Нет TIME_WAIT проблемы: fwmark-маршрутизация не привязана к фиксированным портам

  • autottl работает: prenat-правило перехватывает SYN/ACK для определения TTL сервера

  • Памяти мало: один процесс nfqws2 держит до 1024 стратегий как профили. Замер на живом ядре (весь корпус 13 943 стратегии, ноль потерь в очереди на всех уровнях):

    воркеров пик Σ PSS старая → новая запусков nfqws2 старая → новая
    8 8 396 → 5 442 КБ 288 → 1
    64 50 190 → 7 723 КБ 2 053 → 3
    1024 373 863 → 5 769 КБ (~365 → ~5,6 МБ) 12 917 → 15

    На восьми воркерах выигрыш скромный — полуторакратный: обе схемы грузят память заранее, и на низком параллелизме старая ещё дёшева. Весь смысл — на высоком: старая схема растёт линейно с числом воркеров, новая грузит фиксированные 1024 профиля один раз, независимо от того, 8 воркеров или 1024

  • Удалённый скан: флаг --via позволяет сканировать через удалённый шлюз

Слабые стороны и ограничения

  • TLS fingerprint отличается от curl: rustls генерирует другой ClientHello, чем curl/OpenSSL
  • Нужен root: SO_MARK, nftables, NFQUEUE требуют привилегий
  • Нужен zapret2 ≥ v1.0.5: nfqws2 из этой версии понимает --filter-mark, без него blockcheckw откажется стартовать (см. Quickstart)
  • Одна очередь NFQUEUE на прогон: до --profiles-per-instance (по умолчанию 1024) стратегий в одном процессе nfqws2; корпус больше этого числа режется на несколько последовательных планов — процесс перезапускается между ними

Благодарности

Проект основан на zapret2 — оригинальном инструменте обхода DPI от bol-van. Все стратегии и логика их генерации взяты из blockcheck2.

Поддержать разработчика. Donations

Если вы считаете проект полезным и желаете поддержать разработку, направляйте пожертвования на криптокошелёк :

If you find this project useful and wish to donate here is a crypto wallet :

BTC bc1qnry3qcl34qhf33469j7aaes4kp9e89v729s2x2

About

`blockcheck2.sh` wrapper for better scanning speed (and more)

Resources

Contributing

Security policy

Stars

180 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages