Исправлены ссылки с лишним префиксом Privacy/ (Hysteria/00-overview, Zapret/download), несуществующие цели заменены: fooling → ts-and-fooling, wssize и маркеры → обзор desync, genhost и instance_cutoff → инлайн-код. Проверка obsidian unresolved: было 28 неразрешённых ссылок, осталась одна в Zapret/home.md (отсутствующая картинка, файл владельца не трогаем). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
40 KiB
| date | tags | aliases | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-02-17 |
|
|
syndata --- payload в TCP SYN (zapret2 / nfqws2)
Файл: lua/zapret-antidpi.lua:395
nfqws1 эквивалент: --dpi-desync=syndata
Сигнатура: function syndata(ctx, desync)
syndata --- стратегия "нулевой фазы" в zapret2. Она добавляет произвольный payload в TCP SYN-пакет, применяет модификации (fooling, tls_mod) и отправляет его вместо оригинального SYN. Оригинальный пакет дропается (VERDICT_DROP). Работает до установления TCP-соединения --- на этапе, когда клиент ещё только отправляет SYN.
Родственные/сопутствующие функции: fake (фейковый пакет после SYN), multisplit (TCP-сегментация), Zapret2/desync (управление размером окна), multidisorder, fakedsplit, fakeddisorder.
Общий для всех техник дурения порядок работы — восемь стадий от отсева чужого транспорта до вердикта — разобран в жизненный цикл desync-функции; здесь описано только то, чем syndata от этого скелета отличается.
Оглавление
- Зачем нужен syndata
- Быстрый старт
- Принцип работы
- Полный список аргументов
- tls_mod --- модификация TLS в syndata
- Место в общем скелете
- Псевдокод алгоритма
- Отличия от fake
- Работа с хостлистами
- Комбинирование с другими функциями
- Нюансы и подводные камни
- Миграция с nfqws1
- Практические примеры
Зачем нужен syndata
Некоторые DPI начинают анализировать соединение уже с первого пакета --- с SYN. Они запоминают IP и порт клиента, ждут данные и сопоставляют их с сигнатурами. syndata атакует этот механизм на самом раннем этапе:
- Ложные данные в SYN: DPI видит SYN-пакет с payload (например, фейковый TLS ClientHello) и может принять его за начало реального соединения
- Сбой трекинга: если DPI привязывает сессию к содержимому первого пакета, подменный SYN может направить трекинг по ложному пути
- Обход до handshake: воздействие происходит до TCP handshake --- DPI ещё не видел реальных данных приложения
Важно: TCP SYN с payload --- это валидная TCP-операция (RFC 793 разрешает данные в SYN, хотя многие стеки их игнорируют до завершения handshake). Сервер примет SYN, но payload из него обычно отбросит --- DPI же может попытаться его проанализировать.
Быстрый старт
Минимально (16 нулевых байт в SYN):
--lua-desync=syndata
С TLS-фейком:
--lua-desync=syndata:blob=fake_default_tls
С TLS-фейком и модификацией SNI:
--lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,rndsni
Типовая комбинация (wssize + syndata + multisplit):
--lua-desync=wssize:wsize=1:scale=6 \
--lua-desync=syndata \
--lua-desync=multisplit:pos=midsld
Принцип работы
Что такое SYN с payload
Обычный TCP SYN-пакет не содержит данных --- только заголовки с флагом SYN. syndata берёт этот пакет, добавляет в него payload (указанный в blob или 16 нулевых байт по умолчанию), применяет модификации и отправляет через raw socket вместо оригинала.
Обычный SYN:
[IP Header][TCP Header (SYN)]
SYN после syndata:
[IP Header][TCP Header (SYN)][PAYLOAD (blob или 16x 0x00)]
Сервер получит SYN с данными. Большинство TCP-стеков:
- Завершат handshake (SYN-ACK), проигнорировав payload в SYN
- Payload будет отброшен, потому что соединение ещё не установлено
DPI же может:
- Проанализировать payload из SYN как начало потока данных
- Записать ложную информацию о соединении (фейковый SNI, фейковый HTTP Host)
- Пропустить реальные данные, которые пойдут позже
Нулевая фаза
syndata --- стратегия нулевой фазы. В терминологии zapret это означает:
| Фаза | Когда | Что доступно | Примеры функций |
|---|---|---|---|
| Фаза 0 (SYN) | До TCP handshake | Только SYN-пакет. Нет payload от приложения | syndata, [[Zapret2/desync |
| Фаза 1 (данные) | После handshake, первые данные | Реальный payload (TLS ClientHello, HTTP request и т.д.) | fake, multisplit, fakedsplit |
Следствия нулевой фазы:
- Нет реального payload: приложение ещё ничего не отправило, поэтому syndata работает только с blob-данными или нулями
- Нет hostname: на этом этапе zapret не знает, к какому домену обращается клиент --- хостлисты работают только через
--ipcache-hostname - Нет payload filter: параметры
--payload=...иpayload=...не применимы --- SYN-пакет не содержит данных приложения - Воздействие на все ретрансмиссии SYN: если TCP-стек ретранслирует SYN (timeout), syndata обработает и его
Логика обработки пакетов
Пакет пришёл в syndata
|
+-- Не TCP? --> instance_cutoff (кроме ICMP)
|
+-- TCP:
|
+-- Флаг SYN (не SYN+ACK)? --> deepcopy dis, добавить payload,
| apply_fooling, tls_mod,
| rawsend + VERDICT_DROP
|
+-- Не SYN? --> instance_cutoff (миссия завершена)
Ключевые моменты:
- Проверяется именно
TH_SYNбезTH_ACK--- то есть только исходящий SYN от клиента, не SYN+ACK от сервера deepcopy--- работа ведётся с копией dissect, оригинал не модифицируется- Если пакет не SYN (например, ACK, PSH+ACK) --- это значит, что handshake уже прошёл, и syndata отключает себя (
instance_cutoff) - Для ICMP cutoff не выполняется --- ICMP может быть связан с SYN (например, ICMP Destination Unreachable)
Полный список аргументов
Формат вызова:
--lua-desync=syndata[:arg1[=val1][:arg2[=val2]]...]
Все val приходят в Lua как строки. Если =val не указан, значение = пустая строка "" (в Lua это truthy), поэтому флаги пишутся просто как :tcp_md5, :badsum, :ipfrag.
Важно: syndata не поддерживает стандартные аргументы direction, payload (фильтр) и ipid. Это связано с тем, что syndata работает на фазе 0 (SYN), где нет данных приложения, нет понятия "payload type", и apply_ip_id не вызывается.
A) Собственные аргументы syndata
blob
- Формат:
blob=<blobName> - Тип: имя blob-переменной
- По умолчанию: 16 нулевых байт (
\x00x 16) - Описание: Payload, который будет добавлен в SYN-пакет. Должен помещаться в один пакет --- сегментация невозможна (используется
rawsend_dissect_ipfrag, а неrawsend_payload_segmented). Если blob не задан, отправляются 16 нулевых байт - Примеры:
blob=fake_default_tls--- стандартный TLS-фейк из zapretblob=fake_default_http--- стандартный HTTP-фейкblob=0xDEADBEEF--- inline hexblob=my_custom_payload--- предзагруженный blob- без
blob=--- 16 нулей (дефолт)
tls_mod
- Формат:
tls_mod=<mod1[,mod2,...]> - Тип: строка со списком модификаций через запятую
- По умолчанию: не задан
- Описание: Модификации TLS-данных в payload перед отправкой. Применяется после
apply_fooling. Подробности --- в разделе tls_mod - Работающие значения:
rnd,rndsni,sni=<str>(включаяsni=%var) - Молча игнорируемые:
dupsid,padencap - Примеры:
tls_mod=rnd--- рандомизация TLS-полейtls_mod=rndsni--- рандомизация SNItls_mod=sni=google.com--- замена SNItls_mod=rnd,rndsni,sni=google.com--- комбинацияtls_mod=dupsid--- не даст ошибки, но молча проигнорируется
B) Standard fooling
Модификации L3/L4 заголовков. В syndata применяются к копии dissect (через apply_fooling после deepcopy). Оригинальный пакет не модифицируется --- он дропается.
| Параметр | Описание | Пример |
|---|---|---|
ip_ttl=N |
Установить IPv4 TTL | ip_ttl=6 |
ip6_ttl=N |
Установить IPv6 Hop Limit | ip6_ttl=6 |
ip_autottl=delta,min-max |
Автоматический TTL (delta от серверного TTL) | ip_autottl=-2,40-64 |
ip6_autottl=delta,min-max |
Аналогично для IPv6 | ip6_autottl=-2,40-64 |
ip6_hopbyhop[=HEX] |
Вставить extension header hop-by-hop (по умолчанию 6 нулей) | ip6_hopbyhop |
ip6_hopbyhop2[=HEX] |
Второй hop-by-hop header | ip6_hopbyhop2 |
ip6_destopt[=HEX] |
Destination options header | ip6_destopt |
ip6_destopt2[=HEX] |
Второй destination options | ip6_destopt2 |
ip6_routing[=HEX] |
Routing header | ip6_routing |
ip6_ah[=HEX] |
Authentication header | ip6_ah |
tcp_seq=N |
Сместить TCP sequence (+ или -) | tcp_seq=-10000 |
tcp_ack=N |
Сместить TCP ack (+ или -) | tcp_ack=-66000 |
tcp_ts=N |
Сместить TCP timestamp | tcp_ts=-100 |
tcp_md5[=HEX] |
Добавить TCP MD5 option (16 байт; по умолчанию случайные) | tcp_md5 |
tcp_flags_set=LIST |
Установить TCP-флаги | tcp_flags_set=FIN,PUSH |
tcp_flags_unset=LIST |
Снять TCP-флаги | tcp_flags_unset=ACK |
tcp_ts_up |
Поднять TCP timestamp option в начало заголовка | tcp_ts_up |
tcp_nop_del |
Удалить все TCP NOP опции | tcp_nop_del |
fool=<func> |
Кастомная Lua-функция fooling | fool=my_fooler |
Заметка: fooling в syndata имеет иной смысл, чем в fake или fakedsplit. В fake fooling нужен, чтобы сервер отбросил фейк. В syndata fooling модифицирует сам SYN-пакет, который сервер должен принять для установления соединения. Поэтому деструктивные fooling-параметры (tcp_seq, tcp_ack, badsum) сломают handshake --- сервер не получит валидный SYN. Безопасные варианты: ip_ttl/ip6_ttl (если TTL хватит до DPI, но не до сервера --- спорно для SYN), tcp_md5 (сервер без MD5 проигнорирует опцию), IPv6 extension headers.
C) Standard reconstruct
| Параметр | Описание |
|---|---|
badsum |
Испортить L4 (TCP) checksum при реконструкции raw-пакета. Сервер отбросит такой пакет |
Предупреждение: badsum в syndata означает, что сервер не получит SYN вообще --- TCP handshake не состоится. Используйте только если хотите отправить "мусорный" SYN, за которым пойдёт ретрансмиссия.
D) Standard rawsend
| Параметр | Описание |
|---|---|
repeats=N |
Отправить пакет N раз (идентичные повторы) |
ifout=<iface> |
Интерфейс для отправки (по умолчанию определяется автоматически) |
fwmark=N |
Firewall mark (только Linux, nftables/iptables) |
E) Standard ipfrag
IP-фрагментация SYN-пакета. Каждый отправляемый SYN+payload фрагментируется на уровне IP.
| Параметр | Описание | По умолчанию |
|---|---|---|
ipfrag[=func] |
Включить IP-фрагментацию. Если без значения --- ipfrag2 |
--- |
ipfrag_disorder |
Отправить IP-фрагменты в обратном порядке | --- |
ipfrag_pos_tcp=N |
Позиция фрагментации TCP (кратно 8) | 32 |
ipfrag_pos_udp=N |
Позиция фрагментации UDP (кратно 8). Для syndata бесполезно --- он только TCP | 8 |
ipfrag_next=N |
IPv6: next protocol во 2-м фрагменте (penetration атака на фаерволы) | --- |
tls_mod --- модификация TLS в syndata
tls_mod позволяет модифицировать TLS-данные внутри payload перед отправкой. Вызывается после apply_fooling:
if desync.arg.tls_mod then
dis.payload = tls_mod_shim(desync, dis.payload, desync.arg.tls_mod, nil)
end
Четвёртый аргумент --- nil (реальный payload от приложения). Это ключевой момент, определяющий какие модификации работают, а какие --- нет.
Работающие модификации
| Мод | Описание | Работает? | Причина |
|---|---|---|---|
rnd |
Рандомизация TLS-полей (session_id, random) | Да | Код находится вне блока if(payload) |
rndsni |
Рандомизация SNI (замена на случайные символы) | Да | Код находится вне блока if(payload) |
sni=<str> |
Замена SNI на указанную строку. Поддерживает sni=%var |
Да | Код находится вне блока if(payload) |
Пример: если blob содержит TLS ClientHello с SNI www.example.com, а вы указали tls_mod=sni=google.com, в отправленном SYN-пакете SNI будет заменён на google.com.
dupsid и padencap --- молчаливое игнорирование
| Мод | Описание | Работает? | Причина |
|---|---|---|---|
dupsid |
Дублирование session_id из реального ClientHello | Молча игнорируется | Требует реальный payload (4-й аргумент != NULL) |
padencap |
Упаковка в padding extension | Молча игнорируется | Требует реальный payload (4-й аргумент != NULL) |
Поведение при использовании dupsid/padencap:
| Аспект | Результат |
|---|---|
| Вызывают ошибку? | НЕТ |
| Выводят warning в лог? | НЕТ |
| Возвращают false? | НЕТ (возвращают true = "успех") |
| Применяются? | НЕТ --- код просто пропускается |
Почему dupsid и padencap не работают
В C-коде (protocol.c) логика dupsid и padencap находится внутри блока if (payload):
// protocol.c
if (payload) // <-- syndata передаёт NULL сюда
{
if (tls_mod->mod & FAKE_TLS_MOD_DUP_SID)
// ... копирование session_id из реального ClientHello
// этот код НЕ выполнится
if (tls_mod->mod & FAKE_TLS_MOD_PADENCAP)
// ... упаковка реального payload в padding
// и этот тоже
}
return bRes; // возвращает true --- "всё ОК"
Причина: dupsid копирует session_id из реального ClientHello клиента в фейк. На фазе SYN реального ClientHello ещё не существует (клиент его не отправлял). Аналогично padencap упаковывает реальный payload в padding extension --- на фазе SYN упаковывать нечего.
Это дизайн-решение, а не баг. Но отсутствие warning в логе может ввести в заблуждение --- конфигурация с tls_mod=dupsid будет молча работать "без dupsid".
Место в общем скелете
Тело syndata построено по тому же шаблону, что и все остальные функции дурения: восемь стадий от отсева чужого транспорта до вердикта. Разобраны они один раз в жизненный цикл desync-функции — здесь только отклонения:
| Стадия общего скелета | Что делает syndata |
|---|---|
| 1. Отсев транспорта | нужен TCP и именно SYN без ACK; после прохождения фазы рукопожатия делает instance_cutoff с пометкой «mission complete» |
| 2. Направление | отклонение: аргумента dir нет вообще — SYN по определению исходящий |
| 3. Аргументы | обязательных нет: без blob подставляются 16 нулевых байт |
| 4. Данные | отклонение: цепочка blob → reasm → payload не используется, берётся только blob |
| 5. Гварды | отклонение: штатных гвардов нет, единственный фильтр — флаги TCP |
| 6. replay | не используется: SYN всегда одиночный пакет |
| 7. Своя техника | подставить payload в SYN, применить fooling и tls_mod, отправить rawsend_dissect_ipfrag |
| 8. Вердикт | VERDICT_DROP при успешной отправке — оригинальный SYN заменяется подделанным |
Отклонений здесь много именно потому, что syndata работает до появления прикладных данных. Отсюда же ограничение, о котором легко забыть: payload должен помещаться в один пакет — сегментации на этапе SYN не существует.
Псевдокод алгоритма
Тело функции целиком, включая общие для всех техник стадии — они пронумерованы так же, как в жизненный цикл desync-функции:
function syndata(ctx, desync)
-- 1. Проверка: только TCP
if not desync.dis.tcp then
-- ICMP пропускаем (не делаем cutoff), остальное --- cutoff
if not desync.dis.icmp then instance_cutoff(ctx, desync) end
return
end
-- 2. Проверка: только SYN (не SYN+ACK)
if bitand(th_flags, TH_SYN + TH_ACK) == TH_SYN then
-- 3. Глубокая копия dissect (оригинал не трогаем)
dis = deepcopy(desync.dis)
-- 4. Установка payload: blob или 16 нулей
dis.payload = blob(desync, arg.blob, "\x00" * 16)
-- 5. Применение fooling к копии
apply_fooling(desync, dis)
-- 6. tls_mod (если задан)
if arg.tls_mod then
dis.payload = tls_mod_shim(desync, dis.payload, arg.tls_mod, nil)
-- ^^^ payload от приложения = nil
end
-- 7. Отправка и фрагментация
if rawsend_dissect_ipfrag(dis, desync_opts(desync)) then
return VERDICT_DROP -- оригинальный SYN дропается
end
else
-- 8. Не SYN --- миссия завершена
instance_cutoff(ctx, desync)
end
end
Ключевые отличия от функций сегментации (multisplit, fakedsplit и т.д.):
- Нет цикла по позициям --- payload отправляется одним пакетом целиком
rawsend_dissect_ipfragвместоrawsend_payload_segmented--- нет TCP-сегментации, только IP-фрагментацияdeepcopy--- полная копия dissect, а не создание нового пакета- Нет replay/reasm логики --- на фазе SYN нет многопакетных данных
Отличия от fake
| Аспект | syndata |
fake |
|---|---|---|
| Фаза | 0 (SYN, до handshake) | 1 (после handshake, есть реальные данные) |
| Что отправляет | SYN-пакет с payload | Отдельный data-пакет (не SYN) |
| Дефолтный blob | 16 нулевых байт | Обязательный --- без blob ничего не отправится |
| Сегментация | Невозможна (один пакет) | Невозможна (один пакет) |
| Заменяет оригинал | Да (VERDICT_DROP на SYN) | Нет (оригинал проходит дальше) |
| Fooling | Модифицирует сам SYN --- осторожно! | Модифицирует фейк --- сервер должен его отбросить |
| tls_mod=dupsid | Молча игнорируется | Работает (есть реальный ClientHello) |
| tls_mod=padencap | Молча игнорируется | Работает (есть реальный payload) |
| Хостлисты | Только --ipcache-hostname |
Работают напрямую (payload уже содержит hostname) |
| Воздействие на ретрансмиссии | Да --- каждый SYN обрабатывается | Нет --- работает с конкретным data-пакетом |
| direction | Не поддерживается | Поддерживается |
| payload filter | Не поддерживается | Поддерживается |
| ipid | Не поддерживается | Поддерживается |
Когда использовать syndata вместо fake:
- DPI начинает трекинг с SYN и не реагирует на фейки после handshake
- Нужно "отравить" DPI ложными данными до того, как пойдёт реальный трафик
- В комбинации с Zapret2/desync и multisplit для многоуровневой атаки
Работа с хостлистами
На фазе 0 (SYN) zapret не знает hostname --- приложение ещё не отправило HTTP-запрос или TLS ClientHello. Поэтому стандартная фильтрация по хостлистам (--hostlist=...) не работает с syndata напрямую.
Единственный способ --- --ipcache-hostname:
nfqws2 --ipcache-hostname \
--hostlist=blocked.txt \
--lua-desync=syndata:blob=fake_default_tls
Как это работает:
- Первое соединение к IP-адресу проходит без syndata (hostname ещё не известен)
- Из первого соединения zapret узнаёт hostname (из TLS ClientHello или HTTP Host) и кеширует привязку IP -> hostname
- Последующие SYN к этому IP уже проходят через syndata, потому что zapret знает hostname из кеша
Следствие: syndata с хостлистом не подействует на первое соединение к данному IP. Это может быть проблемой для сайтов с уникальными IP или CDN с ротацией адресов.
Комбинирование с другими функциями
syndata часто используется в цепочке с другими функциями. Порядок инстансов важен!
Типовая цепочка: wssize + syndata + multisplit
--lua-desync=wssize:wsize=1:scale=6 \
--lua-desync=syndata \
--lua-desync=multisplit:pos=midsld
Что происходит:
-
SYN-пакет приходит:
wssizeмодифицирует TCP Window Size в SYN (wsize=1, scale=6)syndataдобавляет payload в SYN, дропает оригинал, отправляет модифицированныйmultisplitничего не делает (SYN, нет данных для нарезки)
-
Первый data-пакет (например, TLS ClientHello) приходит:
wssize--- миссия уже выполнена (cutoff или пропуск)syndataделаетinstance_cutoff(пакет не SYN)multisplitнарезает payload по позицииmidsld
Почему wssize перед syndata: Zapret2/desync модифицирует TCP Window Size в SYN-пакете. Если поставить после syndata, wssize увидит VERDICT_DROP и не получит SYN. Если перед --- wssize модифицирует dissect, затем syndata использует deepcopy этого (уже модифицированного) dissect.
Цепочка: syndata + fake + multisplit
--lua-desync=syndata:blob=fake_default_tls \
--lua-desync=fake:blob=fake_default_tls:tcp_md5 \
--lua-desync=multisplit:pos=1,midsld
Многоуровневая атака:
- Фаза 0: SYN с фейковым TLS
- Фаза 1: фейковый пакет с fooling (tcp_md5)
- Фаза 1: реальный payload нарезан на сегменты
Нюансы и подводные камни
1. Payload должен помещаться в один пакет
syndata использует rawsend_dissect_ipfrag, а не rawsend_payload_segmented. Это означает, что TCP-сегментация невозможна. Если blob слишком большой и не влезает в один Ethernet frame (с учётом MTU), пакет может быть отброшен сетевым стеком или фрагментирован на IP-уровне (если включён ipfrag).
2. Fooling может сломать handshake
В отличие от fake, где fooling должен заставить сервер отбросить пакет, в syndata fooling применяется к пакету, который сервер должен принять. Деструктивные параметры:
tcp_seq=N--- сервер не увидит SYN с правильным sequencetcp_ack=N--- невалидный ack в SYNbadsum--- сервер отбросит пакет с плохой checksumtcp_flags_unset=SYN--- пакет перестанет быть SYN
Безопасные параметры:
tcp_md5--- сервер без MD5 проигнорирует опцию (RFC 2385)tcp_ts_up--- перестановка timestamp option (не влияет на валидность)tcp_nop_del--- удаление NOP (не влияет на валидность)- IPv6 extension headers --- для обхода DPI/фаерволов на пути
3. Нет direction, payload filter, ipid
syndata не вызывает direction_cutoff_opposite, direction_check, payload_check или apply_ip_id. Эти стандартные блоки просто отсутствуют в коде функции:
- direction --- SYN всегда исходящий, фильтрация по направлению бессмысленна
- payload filter --- в SYN нет данных приложения, фильтровать нечего
- ipid ---
apply_ip_idне вызывается, IP ID не контролируется
4. Все ретрансмиссии SYN обрабатываются
Если первый SYN не дошёл (или SYN+ACK потерялся), TCP-стек отправит ретрансмиссию SYN. syndata обработает каждую ретрансмиссию --- добавит payload, применит модификации, дропнет оригинал. Это полезно: DPI может обрабатывать только первый SYN, а ретрансмиссия с payload "перезапишет" данные в трекере.
5. deepcopy защищает оригинал
syndata делает deepcopy(desync.dis) и работает с копией. Это значит, что apply_fooling и замена payload не затрагивают оригинальный dissect. Если после syndata стоят другие инстансы и SYN не дропнут (rawsend failed), они увидят немодифицированный пакет.
6. instance_cutoff на не-SYN
Как только syndata видит пакет без флага SYN (ACK, PSH+ACK и т.д.), он делает instance_cutoff --- отключает себя для этого потока навсегда. Это правильно: миссия syndata --- только SYN-пакеты. Последующие данные должны обрабатываться другими функциями (multisplit, fake и т.д.).
7. ICMP не вызывает cutoff
Если в цепочке инстансов через syndata проходит ICMP-пакет (например, ICMP Destination Unreachable в ответ на SYN), syndata не делает instance_cutoff. Это защита от преждевременного отключения --- ICMP может быть связан с SYN и не означает конец потока.
8. Дефолтный blob --- 16 нулей, а не обязательный параметр
В отличие от fake, где blob обязателен, syndata имеет fallback --- 16 нулевых байт. --lua-desync=syndata без blob= отправит SYN с 16 байтами 0x00. Это может быть достаточно, чтобы сбить DPI, который не ожидает payload в SYN.
9. tls_mod без blob бессмыслен
Если вы указали tls_mod=rnd,rndsni без blob=, tls_mod попытается модифицировать 16 нулевых байт как TLS --- результат будет непредсказуемым. Всегда используйте tls_mod вместе с blob, содержащим валидный TLS ClientHello.
Миграция с nfqws1
Соответствие параметров
| nfqws1 | nfqws2 |
|---|---|
--dpi-desync=syndata |
--lua-desync=syndata |
--dpi-desync-fake-tls=<file> |
--blob=name:@file + :blob=name |
--dpi-desync-fake-tls-mod=rnd,rndsni |
:tls_mod=rnd,rndsni |
--dpi-desync-fooling=md5sig |
:tcp_md5 |
--wssize 1:6 |
--lua-desync=wssize:wsize=1:scale=6 (отдельный инстанс, перед syndata) |
Пример полной миграции
# nfqws1:
nfqws --dpi-desync=syndata,multisplit \
--dpi-desync-split-pos=midsld \
--wssize 1:6
# nfqws2 (порядок инстансов важен!):
nfqws2 \
--lua-desync=wssize:wsize=1:scale=6 \
--lua-desync=syndata \
--lua-desync=multisplit:pos=midsld
# nfqws1:
nfqws --dpi-desync=syndata \
--dpi-desync-fake-tls-mod=rnd,rndsni
# nfqws2:
nfqws2 \
--lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,rndsni
# nfqws1:
nfqws --dpi-desync=syndata \
--dpi-desync-fooling=md5sig
# nfqws2:
nfqws2 \
--lua-desync=syndata:tcp_md5
Практические примеры
Минимальный (дефолт: 16 нулей в SYN)
--lua-desync=syndata
Отправляет SYN с 16 нулевыми байтами вместо обычного SYN. Простейший вариант --- может сбить DPI, не ожидающий payload в SYN.
С TLS-фейком
--lua-desync=syndata:blob=fake_default_tls
SYN содержит стандартный TLS ClientHello из zapret. DPI может принять это за начало TLS-сессии.
С кастомным blob из файла
--blob=mysyndata:@custom_syn_payload.bin \
--lua-desync=syndata:blob=mysyndata
Загружает произвольный payload из файла и вставляет в SYN.
С inline hex blob
--lua-desync=syndata:blob=0x160301000100
6 байт inline hex --- минимальный TLS record header.
С рандомизацией TLS
--lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,rndsni
TLS-фейк с рандомизированными полями и SNI. Каждый SYN будет содержать уникальные random/session_id/SNI.
С заменой SNI
--lua-desync=syndata:blob=fake_default_tls:tls_mod=sni=google.com
SYN содержит TLS ClientHello с SNI google.com. DPI может записать в трекер "это соединение к google.com" и не блокировать.
С TCP MD5
--lua-desync=syndata:tcp_md5
SYN с 16 нулями и TCP MD5 option. Сервер без MD5 проигнорирует опцию, DPI может быть сбит нестандартным TCP-заголовком.
С TTL fooling (осторожно!)
--lua-desync=syndata:blob=fake_default_tls:ip_ttl=5:ip6_ttl=5
SYN с TTL=5. Если DPI ближе 5 хопов --- увидит фейк. Если сервер дальше 5 хопов --- SYN не дойдёт, handshake не состоится. Ретрансмиссия SYN тоже получит TTL=5 и тоже не дойдёт. Используйте только если точно знаете расстояние до DPI и сервера.
С IP-фрагментацией
--lua-desync=syndata:blob=fake_default_tls:ipfrag:ipfrag_disorder
SYN с TLS-фейком, фрагментированный на IP-уровне в обратном порядке. DPI, не собирающий IP-фрагменты, не увидит полный пакет.
С IP-фрагментацией (кастомная позиция)
--lua-desync=syndata:blob=fake_default_tls:ipfrag:ipfrag_pos_tcp=24
Фрагментация по позиции 24 байта (кратно 8). Первый фрагмент содержит TCP-заголовок, второй --- payload.
Типовая боевая комбинация: wssize + syndata + multisplit
--filter-tcp=443 \
--lua-desync=wssize:wsize=1:scale=6 \
--lua-desync=syndata \
--lua-desync=multisplit:pos=midsld
Трёхуровневая атака на DPI: маленькое окно (заставляет сервер слать маленькие сегменты) + payload в SYN + нарезка реального ClientHello.
Боевая комбинация: syndata + fake + multisplit
--filter-tcp=443 --hostlist=blocked.txt --ipcache-hostname \
--lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,rndsni \
--lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,rndsni,dupsid \
--lua-desync=multisplit:pos=1,midsld
Максимальная комбинация: фейк в SYN, фейк после handshake (с dupsid --- здесь он работает, потому что это fake, а не syndata), нарезка реального payload.
Отладка: повторы отправки
--lua-desync=syndata:blob=fake_default_tls:repeats=3
Каждый SYN с payload отправляется 3 раза. Полезно для отладки или если DPI обрабатывает только N-й пакет.
IPv6: extension headers
--lua-desync=syndata:blob=fake_default_tls:ip6_hopbyhop:ip6_destopt
SYN с hop-by-hop и destination options extension headers. Некоторые DPI/фаерволы не умеют парсить IPv6 extension headers и пропускают пакет.
Источники:
lua/zapret-antidpi.lua:385,lua/zapret-lib.lua,docs/manual.md:3944-3961из репозитория zapret2.