Содержание
Наглядный гайд · nfqws2 · для тех, кто настраивает, но хочет понимать
DPI читает первый пакет. Вся хитрость — в том, что в нём лежит.
Когда телевизор открывает YouTube, он отправляет один короткий пакет, где открытым текстом написано имя сайта. ТСПУ читает это имя и решает, замедлить соединение или нет. zapret2 вклинивается ровно здесь: он не шифрует трафик и не гонит его через сервер, а аккуратно портит этот первый пакет — так, чтобы ТСПУ обманулся, а сервер понял всё правильно. Ниже — как именно, по шагам и со схемами.
01Что видит ТСПУ — и за что цепляется
HTTPS шифрует переписку с сайтом, но самый первый пакет — TLS ClientHello — уходит ещё до того, как шифрование установлено. Внутри него есть поле SNI (Server Name Indication): имя сайта открытым текстом. Оно нужно, чтобы сервер, обслуживающий много доменов, понял, чей сертификат прислать. Его же читает и ТСПУ.
Почему обман вообще возможен? ТСПУ стоит на линии между вами и сервером и пропускает через себя гигантский поток. Разбирать каждое соединение так же дотошно, как это делает сервер, ему дорого. Поэтому у DPI есть срезки, на которых и держатся все техники zapret2:
Смотрит начало, а не весь поток
Решение принимается по первым пакетам. Если ClientHello разрезать на TCP-сегменты, DPI, не собирающий поток целиком, не увидит имя хоста. Сервер соберёт — для него это штатная ситуация.
Не всегда следит за sequence
TCP-сегменты нумерованы. Если DPI не сверяет номера так же строго, как сервер, ему можно подсунуть «лишние» байты в начале (seqovl), которые сервер отрежет как вышедшие за окно.
Верит первому, что увидел
Часто хватает подсунуть перед настоящим ClientHello поддельный — с невинным SNI. Если DPI решает по первому и не перепроверяет, дальше он теряет к соединению интерес.
Не проверяет то, что проверит сервер
Контрольную сумму, номер подтверждения, TCP-подпись MD5 сервер сверяет и битый пакет выбрасывает, а DPI — обычно нет. На этом строятся фейки: DPI их «съедает», сервер игнорирует.
02Путь пакета: из телевизора в сеть
Прежде чем разбирать стратегии, полезно увидеть, где именно они срабатывают. nfqws2 — это не драйвер и не файрвол; это обычная программа, которой ядро Linux по правилу nftables отдаёт первые пакеты соединения. Пройдите по шагам — от пакета из локальной сети до отправки в интернет.
0x40000000 и потому
не перехватываются повторно — иначе вышла бы бесконечная петля. Той же меткой пользуется ZeroBlock: трафик,
который он забрал себе, zapret2 не трогает. Это стоит помнить при отладке.
03Анатомия одной строки стратегии
Стратегия для nfqws2 — это не набор галочек, а маленькая программа. Она собрана из вызовов --lua-desync:
каждый вызывает Lua-функцию (атаку) с параметрами. Вот из чего состоит один такой вызов:
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=681 — туда помещается целый поддельный ClientHello.
06Фулинг: почему фейк не долетает до сервера
Прямой фейк (fake) — это отдельный пакет с ложным содержимым. Он должен обмануть DPI, но не дойти до
сервера: если сервер примет фейковый ClientHello, он решит, что клиент прислал чепуху, и оборвёт соединение. Фейк
«убивают» по дороге фулингом. Способы:
| Фулинг | Что делает | Почему сервер отбросит, а 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 без фулинга помечается предупреждением.
Скрытые фейки (seqovl, fakedsplit, hostfakesplit) фулинга во многом не требуют или
применяют его только к своим фейковым частям — сервер отсекает их по номерам sequence, а не по битым заголовкам.
07Профили и оркестратор circular
Одна стратегия работает не всегда. Профили позволяют держать разные стратегии для разных условий, а оркестратор
circular — автоматически перебирать их, если текущая перестала работать.
Профили: первый подходящий сверху
Профиль — это фильтр (порты, протокол, hostlist) плюс набор инстансов. Когда приходит новое соединение, nfqws2 проверяет профили по порядку и выбирает первый, чей фильтр совпал; остальные не рассматриваются. Имя хоста известно только из ClientHello, поэтому профиль с hostlist включается именно на этом пакете.
config strategy — это один профиль. Их порядок (в LuCI — перетаскиванием)
определяет приоритет. Имя секции уходит в --name= и видно в логах.
circular: перебор стратегий по кругу
circular — оркестратор: он забирает все следующие инстансы профиля и на каждом соединении выполняет только те,
у кого strategy=N совпадает с текущим активным номером. Он считает неудачи по хосту (входящий RST, отсутствие
ответа, ретрансмиссии) и после fails неудач подряд переключается на следующую стратегию. Нажимайте кнопки и
следите за логикой:
Лог, как в debug-выводе nfqws2:
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_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, чтобы их не перехватывать повторно.