Содержание
  1. 01 · Что видит ТСПУ
  2. 02 · Путь пакета
  3. 03 · Анатомия стратегии
  4. 04 · Маркеры позиций
  5. 05 · Каталог атак
  6. 06 · Фулинг
  7. 07 · Профили и circular
  8. 08 · Декодер стратегии
  9. 09 · Как это на роутере
  10. 10 · Словарь

Наглядный гайд · nfqws2 · для тех, кто настраивает, но хочет понимать

DPI читает первый пакет. Вся хитрость — в том, что в нём лежит.

Когда телевизор открывает YouTube, он отправляет один короткий пакет, где открытым текстом написано имя сайта. ТСПУ читает это имя и решает, замедлить соединение или нет. zapret2 вклинивается ровно здесь: он не шифрует трафик и не гонит его через сервер, а аккуратно портит этот первый пакет — так, чтобы ТСПУ обманулся, а сервер понял всё правильно. Ниже — как именно, по шагам и со схемами.

↑ упрощённый TLS ClientHello. Зелёным — имя хоста в поле SNI красная линия — разрез, которым его прячут от DPI

01Что видит ТСПУ — и за что цепляется

HTTPS шифрует переписку с сайтом, но самый первый пакет — TLS ClientHello — уходит ещё до того, как шифрование установлено. Внутри него есть поле SNI (Server Name Indication): имя сайта открытым текстом. Оно нужно, чтобы сервер, обслуживающий много доменов, понял, чей сертификат прислать. Его же читает и ТСПУ.

Ключевая мысль Для YouTube ТСПУ не блокирует, а замедляет: распознав трафик Google по SNI и адресам, оно с некоторой вероятностью роняет пакеты, и видео не грузится в высоком качестве. Если трафик перестать распознавать как YouTube — замедление к нему не применяется. (source: zarazaex, habr.com 2026-03-24; лекция по ТСПУ, Lavrushin)

Почему обман вообще возможен? ТСПУ стоит на линии между вами и сервером и пропускает через себя гигантский поток. Разбирать каждое соединение так же дотошно, как это делает сервер, ему дорого. Поэтому у DPI есть срезки, на которых и держатся все техники zapret2:

Смотрит начало, а не весь поток

Решение принимается по первым пакетам. Если ClientHello разрезать на TCP-сегменты, DPI, не собирающий поток целиком, не увидит имя хоста. Сервер соберёт — для него это штатная ситуация.

Не всегда следит за sequence

TCP-сегменты нумерованы. Если DPI не сверяет номера так же строго, как сервер, ему можно подсунуть «лишние» байты в начале (seqovl), которые сервер отрежет как вышедшие за окно.

Верит первому, что увидел

Часто хватает подсунуть перед настоящим ClientHello поддельный — с невинным SNI. Если DPI решает по первому и не перепроверяет, дальше он теряет к соединению интерес.

Не проверяет то, что проверит сервер

Контрольную сумму, номер подтверждения, TCP-подпись MD5 сервер сверяет и битый пакет выбрасывает, а DPI — обычно нет. На этом строятся фейки: DPI их «съедает», сервер игнорирует.

Важная оговорка ТСПУ у разных провайдеров и в разных регионах настроено по-разному, балансировщик раскидывает соединения по фильтрам, а настройки со временем меняются. Поэтому универсальной стратегии нет: то, что работает у соседа, у вас может не сработать, а рабочая связка иногда «ломается» после обновления ТСПУ. Стратегию всегда проверяют на своём канале.

02Путь пакета: из телевизора в сеть

Прежде чем разбирать стратегии, полезно увидеть, где именно они срабатывают. nfqws2 — это не драйвер и не файрвол; это обычная программа, которой ядро Linux по правилу nftables отдаёт первые пакеты соединения. Пройдите по шагам — от пакета из локальной сети до отправки в интернет.

Полоски сверху у карточек: голубая — шаг внутри ядра, лиловая — внутри процесса nfqws2. Значения (порты, счётчики) — из конфигурации Routerich AX3000; у вас могут отличаться.
Зачем метка desync Пакеты, которые nfqws2 отправляет сам (фейки, нарезанные сегменты), помечены fwmark 0x40000000 и потому не перехватываются повторно — иначе вышла бы бесконечная петля. Той же меткой пользуется ZeroBlock: трафик, который он забрал себе, zapret2 не трогает. Это стоит помнить при отладке.

03Анатомия одной строки стратегии

Стратегия для nfqws2 — это не набор галочек, а маленькая программа. Она собрана из вызовов --lua-desync: каждый вызывает Lua-функцию (атаку) с параметрами. Вот из чего состоит один такой вызов:

Читается так: «разрежь пакет по позициям 1 и midsld, к первому сегменту добавь 681 байт слева за границей окна, у отправляемых фейков испорти контрольную сумму».

Три вещи, которые сбивают с толку новичков:

  • Несколько --lua-desync — это не «варианты на выбор». Они выполняются по очереди для каждого пакета, один за другим. Три строки fake + multisplit + fake — это одна стратегия из трёх действий, а не три стратегии.
  • Порядок важен. wssize должен идти раньше syndata, иначе окно не успеет подмениться. Функция-фулинг pktmod меняет пакет для всех следующих инстансов.
  • Фильтры перед инстансами. --payload, --in-range, --out-range — не часть атаки, а условия: на какие пакеты и в каком диапазоне соединения звать следующие инстансы. Действуют до переопределения.
Вердикт каждого инстанса агрегируется: DROP сильнее MODIFY, MODIFY сильнее PASS. Поэтому multisplit, отправив сегменты сам, выносит DROP — чтобы целый оригинал не ушёл следом.

04Маркеры позиций — где резать

Точки разреза почти никогда не задают числом байт: имя хоста лежит в разных местах у разных сайтов. Вместо этого используют маркеры — nfqws2 сам находит нужное место в разобранном пакете. Поиграйте: введите список маркеров (как в параметре pos) и посмотрите, куда попадут разрезы на нашем ClientHello для www.youtube.com.

midsld = середина домена 2-го уровня (в www.youtube.com это «youtube»). Так стратегия остаётся рабочей и для googlevideo.com, и для любого другого домена — резать всегда будет внутри значимой части имени. Отрицательные числа считаются от конца (-1 — последний байт).

05Каталог атак: что происходит с пакетом

Это ядро гайда. Выберите технику — и проиграйте, как пакеты идут от роутера к серверу через ТСПУ. Слева видно, что показывается DPI, справа — что в итоге соберёт сервер в буфере сокета. Настоящие байты — светлые, поддельные — тёмные с красным, seqovl — заштрихованные слева за границей окна.

Загрузка интерактивного блока… (нужен JavaScript)

Заметьте закономерность. Техники делятся на два больших семейства, и почти всё остальное — их сочетания:

Разрезание (split / disorder)

ClientHello режется на TCP-сегменты. DPI, не собирающий поток, не видит SNI целиком. disorder добавляет отправку в обратном порядке, чтобы DPI первым получил хвост без заголовка. Фулинг не нужен — сервер честно склеит всё по seq.

Фейки (fake / hostfakesplit)

Рядом с настоящими данными подсовываются поддельные — с чужим SNI или мусором. DPI на них отвлекается. Обязателен фулинг: фейк должен умереть по дороге к серверу, иначе сломает соединение. Об этом — следующий раздел.

Про seqovl отдельно Откройте вкладку «multisplit + seqovl»: это способ спрятать фейк внутри настоящего сегмента, без отдельного пакета и без фулинга. К началу сегмента приписывают N байт, а его seq уменьшают на N — сервер считает эти байты вышедшими за окно и отрезает, а DPI, не следящий за номерами, читает их как начало сообщения. В реальных стратегиях seqovl=681 — туда помещается целый поддельный ClientHello.

06Фулинг: почему фейк не долетает до сервера

Прямой фейк (fake) — это отдельный пакет с ложным содержимым. Он должен обмануть DPI, но не дойти до сервера: если сервер примет фейковый ClientHello, он решит, что клиент прислал чепуху, и оборвёт соединение. Фейк «убивают» по дороге фулингом. Способы:

Роутер nfqws2 ТСПУ DPI Сервер YouTube фейк · TTL=6 гаснет, не дойдя до сервера настоящий ClientHello · TTL=64
Фейк уходит первым и виден ТСПУ, но с малым TTL «умирает» на полпути. Настоящий пакет доходит до сервера. DPI уже принял решение по фейку.
ФулингЧто делаетПочему сервер отбросит, а DPI — нет
ip_autottlСтавит TTL так, чтобы пакета хватило до ТСПУ, но не до сервераTTL считается на каждом хопе; за ТСПУ пакет «истекает». DPI ближе, чем сервер.
badsumПортит контрольную сумму TCPСервер сверяет сумму и выбрасывает. Многие DPI сумму не проверяют. Минус: битый пакет может отсеять и NAT провайдера.
tcp_md5Добавляет TCP-опцию MD5 signatureБольшинство серверов пакеты с чужой MD5-подписью отбрасывает; DPI на опцию не смотрит.
tcp_ackСдвигает номер подтверждения (badack)Сервер видит неверный ack и игнорирует; для DPI содержимое выглядит валидным.
tcp_tsСдвигает TCP timestamp в прошлоеСервер по правилу PAWS отбрасывает «старый» пакет. Нужна опция timestamp в соединении.
Что будет без фулинга Проверьте на вкладке «fake без фулинга»: фейк — корректный пакет с правильным seq, сервер примет его первым, а настоящий ClientHello отбросит как дубликат. DPI обманут, но толку нет — сломан сам сайт. Поэтому в декодере ниже fake без фулинга помечается предупреждением.

Скрытые фейки (seqovl, fakedsplit, hostfakesplit) фулинга во многом не требуют или применяют его только к своим фейковым частям — сервер отсекает их по номерам sequence, а не по битым заголовкам.

07Профили и оркестратор circular

Одна стратегия работает не всегда. Профили позволяют держать разные стратегии для разных условий, а оркестратор circular — автоматически перебирать их, если текущая перестала работать.

Профили: первый подходящий сверху

Профиль — это фильтр (порты, протокол, hostlist) плюс набор инстансов. Когда приходит новое соединение, nfqws2 проверяет профили по порядку и выбирает первый, чей фильтр совпал; остальные не рассматриваются. Имя хоста известно только из ClientHello, поэтому профиль с hostlist включается именно на этом пакете.

В UCI на роутере каждый включённый config strategy — это один профиль. Их порядок (в LuCI — перетаскиванием) определяет приоритет. Имя секции уходит в --name= и видно в логах.

circular: перебор стратегий по кругу

circular — оркестратор: он забирает все следующие инстансы профиля и на каждом соединении выполняет только те, у кого strategy=N совпадает с текущим активным номером. Он считает неудачи по хосту (входящий RST, отсутствие ответа, ретрансмиссии) и после fails неудач подряд переключается на следующую стратегию. Нажимайте кнопки и следите за логикой:

Лог, как в debug-выводе nfqws2:

«Ждать 90 с» показывает сброс счётчика: если между неудачами прошло больше time секунд (по умолчанию 60), счётчик обнуляется — редкие сбои не считаются за отказ стратегии.
Тонкость, которую легко упустить Детекторам circular нужны входящие пакеты (RST, ответ сервера), а по умолчанию входящие отключены (--in-range=x). Поэтому перед circular ставят --in-range=-s5556, а --payloadпосле circular, иначе фильтр обрежет ему обзор. Декодер ниже ловит обе ошибки.

08Декодер: разберите свою стратегию

Вставьте строку стратегии — из поля script секции config strategy в LuCI или командную строку nfqws2. Декодер разложит её на профили и инстансы, объяснит каждый параметр по-русски и подсветит частые ошибки. Всё считается в браузере — ничего никуда не отправляется.

переносы строк и \/^ в конце строк можно — они склеиваются

Справочник параметров собран по коду zapret-antidpi.lua, zapret-auto.lua и zapret-lib.lua из zapret2 v1.0.5.1. Декодер знает стандартные функции библиотеки; свои Lua-функции он честно пометит как незнакомые. Он не запускает стратегию и не гарантирует, что она рабочая, — только объясняет синтаксис и ловит типовые промахи.

09Как это выглядит на роутере

На OpenWrt (например, Routerich AX3000) zapret2 настраивается через LuCI, а под капотом хранит конфигурацию в UCI — файле /etc/config/zapret2. Из абстракций гайда в реальные сущности это ложится так:

В гайдеНа роутере (UCI / LuCI)
ПрофильСекция config strategy '<имя>'. Порядок — перетаскиванием в LuCI. Поле script — те самые --lua-desync после фильтров профиля.
Фильтр профиляПоля секции: port, protocol, filter_l3, filter_l7, hostlist.
Блоб для фейкаСекция config blob 'blob_…'. Грузится в nfqws2, только если enabled='1'; в стратегии — blob=blob_….
Список доменовСекция config list → в стратегии hostlist='list_…'.
Перехват пакетовПравила nftables в таблице inet zapret2, очередь NFQUEUE. Сколько первых пакетов перехватывать — nfqws_tcp_pkt_out/in (по умолчанию 25/5).
Практические мелочи
  • После правки стратегий — /etc/init.d/zapret2 restart. reload только перечитывает списки (SIGHUP).
  • --out-range в стратегии не должен превышать nfqws_tcp_pkt_out: дальше nfqws2 пакеты просто не видит.
  • Debug-лог — /tmp/zapret2/main.log, только при main.debug=1. Без него разбираться в стратегиях тяжело.
  • Подбор стратегий: zapret2-finder и blockcheck2. Оба проверяют через системный curl — у него нет HTTP/3 (QUIC) и, как правило, нет kyber, так что многопакетный ClientHello браузера они не воспроизводят.
QUIC / HTTP-3 YouTube ходит и по TLS (tcp/443), и по QUIC (udp/443). Стратегии в этом гайде — про TCP/TLS. QUIC — отдельный транспорт со своими фейками (quic_initial); блокируют ли его и нужно ли обходить — зависит от провайдера, проверяется на месте. И помните про kyber: в браузере ClientHello из-за постквантового ключа часто занимает несколько пакетов, и стратегия должна это учитывать, а curl-инструменты подбора — нет.

10Короткий словарь

DPI
Deep Packet Inspection — разбор содержимого пакетов на линии. В России реализован в ТСПУ.
ТСПУ
Технические средства противодействия угрозам — оборудование DPI у операторов, управляемое централизованно.
SNI
Поле в TLS ClientHello с именем сайта открытым текстом. Главная зацепка для DPI.
ClientHello
Первый пакет TLS-рукопожатия. Уходит до шифрования, поэтому его и правят.
nfqws2
Основная программа zapret2. Получает пакеты из ядра и применяет к ним стратегии на Lua.
инстанс
Один вызов --lua-desync: функция-атака с конкретными параметрами.
фулинг
Порча пакета (TTL, сумма, MD5, seq/ack, ts), из-за которой его отбрасывает сервер, но не DPI.
seqovl
Sequence overlap — байты, приписанные слева за границу TCP-окна. Сервер их отрезает, DPI может прочитать.
fake
Поддельный пакет, отправленный, чтобы обмануть DPI. Требует фулинга.
split / disorder
Нарезка ClientHello на сегменты; disorder — ещё и отправка в обратном порядке.
hostlist
Список доменов, к которым применяется профиль (для YouTube — googlevideo.com, ytimg.com и др.).
circular
Оркестратор: перебирает стратегии по кругу, когда текущая перестаёт работать.
блоб (blob)
Блок двоичных данных (например, готовый фейковый ClientHello), загружаемый в nfqws2.
desync mark
Метка fwmark на пакетах, сгенерированных nfqws2/ZeroBlock, чтобы их не перехватывать повторно.