todo/Zapret2/desync.md
loop-uh 08b4491545
Some checks failed
Published content check / validate (push) Failing after 3s
Завершить переезд базы знаний на Forgejo
Обновить правила репозитория и подписи исходников в 99 заметках, не затрагивая пользовательские незакоммиченные файлы. Сделать Forgejo Actions содержательным: проверять опубликованный commit, а не пустое рабочее дерево после checkout.
2026-08-07 08:27:28 +03:00

54 KiB
Raw Permalink Blame History

date tags link aliases img
2026-07-17
zapret
zapret2
nfqws2
lua
lua-desync
desync
antidpi
https://github.com/bol-van/zapret2/blob/master/docs/manual.md
lua-desync
Десинхронизация
Механизм --lua-desync

🧨 Десинхронизация: флаг --lua-desync

[!info] О чём заметка Обзор --lua-desync — главного механизма обхода DPI в Zapret2/Zapret2: что это за флаг, как он вызывается для каждого пакета и какие бывают функции-стратегии. Это заметка-хаб: здесь общая картина и каталог функций со ссылками, а детальные аргументы каждой функции — в её собственной заметке (multisplit, fake и т. д.). Устройство входных данных функции (ctx, desync, диссект, track) вынесено в структура desync и диссекта. Где --lua-desync стоит среди других полей — см. profile и preset, а где вызов происходит в общем конвейере — схема обработки трафика.

Что такое --lua-desync

DPI (Deep Packet Inspection) блокирует соединения, распознавая в трафике сигнатуры — домен в SNI у TLS, Host: у HTTP. Чтобы обойти блокировку, пакеты нужно так изменить или дополнить, чтобы DPI не собрал корректную картину, а сервер-получатель — собрал. В Zapret 2 вся эта логика вынесена из C-ядра в Lua-функции (почему так — структура проекта), и подключаются они флагом --lua-desync.

--lua-desync вызывает одну Lua-функцию для каждого пакета, прошедшего через filter profile. Синтаксис:

--lua-desync=<функция>[:параметр1=значение1[:параметр2=значение2]]

Флаг можно указать несколько раз — каждый вызов называется инстансом, и инстансы выполняются строго по порядку задания (порядок важен: сначала фейк, потом нарезка — не то же самое, что наоборот; см. последовательность аргументов). Параметры пишутся через двоеточие: param=valueсо значением, param без значения = true.

[!note] Как это работает по шагам Пакет проходит через фильтры profile (--filter-tcp, --filter-l7, [[hostlist|--hostlist]]) → если соответствует, вызывается Lua-функция инстанса → функция выполняет действие (отправляет fake, разбивает пакет, модифицирует заголовки) → возвращает вердикт (VERDICT_PASS, VERDICT_MODIFY, VERDICT_DROP), который агрегируется по всей цепочке инстансов.


🔗 Что функция получает, что отдаёт и как связана с C-ядром

Это раздел про контракт desync-функции: где она живёт, кто её вызывает, что подаётся ей на вход, что она возвращает и как это стыкуется с C-ядром nfqws2. Понимание этого контракта — ключ ко всем отдельным техникам (fake, multisplit, multidisorder и др.): все они устроены по одной схеме.

Где desync-функция стоит в структуре проекта

Zapret 2 состоит из двух половин (подробно — в структура проекта): быстрое C-ядро nfqws2 и Lua-код с логикой обхода. desync-функции — это как раз Lua: они лежат в файле zapret-antidpi.lua (плюс базовые в zapret-lib.lua). Само C-ядро обхода не делает — оно только перехватывает, разбирает и отправляет пакеты, а решение, что с пакетом сделать, отдаёт в Lua.

Момент вызова — предпоследняя стадия схема обработки трафика. К этому времени C-ядро уже перехватило пакет из ядра ОС, разобрало его (диссекция), привязало к потоку (conntrack), определило тип пейлоада и выбрало profile. Дальше ядро идёт по инстансам профиля (каждый --lua-desync=... — один инстанс) строго по порядку и для каждого вызывает Lua-функцию.

[!note] Инстанс — это один вызов Инстанс = один экземпляр вызова Lua-функции из профиля, заданный одним флагом --lua-desync. Одна и та же функция может быть вызвана несколько раз с разными параметрами — это разные инстансы. Порядок инстансов принципиален (см. последовательность аргументов).

Сигнатура: два параметра на входе

Каждая desync-функция объявляется с двумя аргументами:

function fake(ctx, desync)   -- пример: функция fake
  • ctx — «контекст», непрозрачный мост к C-коду. Сам по себе он ничего не значит для чтения; его передают обратно в C-функции (отправка пакетов, cutoff), чтобы те знали, к какому пакету/очереди относится вызов. Грубо говоря, ctx — это «телефонная линия обратно в ядро».
  • desync — большая Lua-таблица со всеми данными обрабатываемого пакета и его потока. Это главный вход: из неё функция читает всё, что ей нужно. Полный разбор всех полей (arg, dis, track, reasm/replay и пр.) — в отдельной заметке структура desync и диссекта.

[!note] Проще говоря desync — это «что за пакет и что мы про него знаем» (данные, которые C передал в Lua). ctx — это «как достучаться обратно до C, чтобы что-то отправить или отключиться». Первое читают, второе используют как ручку для команд.

Что функция делает в середине

Получив desync, инстанс может:

  • читать поля пакета и потока (диссект, тип пейлоада, счётчики conntrack, собранный reasm);
  • создавать копии текущего диссекта, менять в них поля (sequence number, TTL, флаги, payload) и генерировать собственные диссекты (например, фейковый ClientHello);
  • отправлять эти диссекты сырыми пакетами прямо в сеть — через C-функции вроде rawsend_* (именно тут используется ctx). Это происходит немедленно, ещё до того как функция вернёт вердикт;
  • хранить состояние: в самой таблице desync — для передачи данных следующим инстансам этого же пакета; в desync.track.lua_state — для данных, живущих между пакетами одного потока (эту таблицу C выдаёт одну и ту же на каждый пакет потока).

Что функция отдаёт: два вида выхода

У desync-функции, как и у multisplit, два «выхода», и их важно различать.

1. Побочный эффект — уже отправленные пакеты. Основную работу fake или multisplit функция делает не через return, а вызовами отправки (rawsend_*) прямо посреди тела. К моменту return фейковые/нарезанные пакеты уже улетели в сеть.

2. Возвращаемое значение — вердикт оригинальному пакету. Перехваченный пакет всё ещё ждёт решения. Функция возвращает одно из:

Вердикт Что значит
VERDICT_PASS не делать с оригиналом ничего (пропустить как есть)
VERDICT_MODIFY в конце всей цепочки отправить изменённое содержимое диссекта
VERDICT_DROP выбросить оригинал (например, потому что данные уже ушли нарезанными)
nil (без return) бездействие — функция решила не вмешиваться

Агрегация по цепочке. Вердикты всех инстансов профиля объединяются по приоритету: MODIFY перебивает PASS, а DROP перебивает и PASS, и MODIFY. Достаточно одному инстансу вернуть DROP — оригинал будет выброшен, что бы ни вернули соседи (иначе, например, при нарезке сервер получил бы данные дважды).

Управляющий «выход» — cutoff. Кроме вердикта функция может управлять своим будущим: instance_cutoff отключает этот инстанс от дальнейших пакетов потока по направлению, lua_cutoff отключает направление потока от всей Lua-обработки, а инстанс-оркестратор может вовсе взять управление остальной цепочкой на себя. Это способ сэкономить CPU и строить динамические сценарии (подробнее — схема обработки трафика, стадия про cutoff).

Связь C ↔ Lua одной картинкой

  • Из C в Lua передаётся desync — данные: диссект, conntrack, тип пейлоада, аргументы инстанса, replay-инфо. C уже сделал всю «тяжёлую» работу (перехват, разбор, отслеживание потока) и сложил результат в таблицу.
  • Из Lua в C идут команды — через ctx: отправить сырой пакет, испортить checksum, поставить cutoff. Плюс вердикт через return — что C сделать с оригиналом в конце.

Такое разделение и есть главная идея Zapret 2: медленную логику обхода можно править в текстовых Lua-файлах без перекомпиляции C-ядра.


📦 Доступные функции из zapret-antidpi.lua

Аргументы

Категория Аргумент Описание
Direction dir in | out | any
Fooling ip_ttl=N TTL для IPv4
ip6_ttl=N TTL для IPv6
ip_autottl=delta,min-max Авто-определение TTL
ip6_autottl=delta,min-max Авто-определение TTL для IPv6
ip6_hopbyhop[=hex] Добавить hop-by-hop заголовок
ip6_hopbyhop2[=hex] Второй hop-by-hop
ip6_destopt[=hex] Destopt заголовок
ip6_destopt2[=hex] Второй destopt
ip6_routing[=hex] Routing заголовок
ip6_ah[=hex] Authentication заголовок
tcp_seq=N Добавить N к tcp.th_seq
tcp_ack=N Добавить N к tcp.th_ack
tcp_ts=N Добавить N к timestamp
tcp_md5[=hex] Добавить MD5 опцию
tcp_flags_set= Установить TCP флаги
tcp_flags_unset= Снять TCP флаги
tcp_ts_up Переместить timestamp наверх
fool= Кастомная функция fooling
Reconstruct badsum Невалидная L4 checksum
Rawsend repeats Сколько раз отправить пакет
ifout Override исходящего интерфейса
fwmark Override fwmark
Payload payload Список разрешённых типов payload
IP_ID ip_id seq|rnd|zero|none
ip_id_conn Сохранять ip_id между пакетами
IPfrag ipfrag[=func] Функция фрагментации (default: ipfrag2)
ipfrag_disorder Отправить фрагменты в обратном порядке
ipfrag_pos_udp Позиция UDP фрагмента (default: 8)
ipfrag_pos_tcp Позиция TCP фрагмента (default: 32)
ipfrag_next Next protocol для второго фрагмента IPv6

Базовые:

Функция Описание
drop Отбросить пакет
send Отправить пакет как есть (с возможной модификацией заголовков)
pktmod Модифицировать заголовки пакета (fooling)
Функция Std args Специфичные args
drop direction, payload -
send direction, fooling, ip_id, ipfrag, rawsend, reconstruct -
pktmod direction, fooling, ip_id -

HTTP модификации:

Функция Описание
http_domcase Изменить регистр домена (HoSt)
http_hostcase Изменить регистр заголовка Host
http_methodeol Модифицировать конец строки метода

TCP сплит и disorder:

Функция Описание
multisplit Разбить пакет на несколько TCP сегментов
multidisorder Разбить + отправить в обратном порядке
tcpseg TCP сегментация
Функция Std args Специфичные args
multisplit direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag pos= (default: "2"), seqovl=N, seqovl_pattern=, blob=, nodrop
multidisorder direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag pos= (default: "2"), seqovl=N, seqovl_pattern=, blob=, nodrop
tcpseg direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag pos= (обязательный, 2 позиции), seqovl=N, seqovl_pattern=, blob=

Fake-атаки:

Функция Описание
fake Отправить fake пакет
fakedsplit Fake + сплит оригинала
fakeddisorder Fake + disorder оригинала
hostfakesplit Fake только для хоста + сплит
Функция Std args Специфичные args
fake direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag blob= (обязательный), tls_mod= (rnd,rndsni,sni=,dupsid,padencap)
fakedsplit direction, payload, fooling, ip_id, rawsend, reconstruct pos= (default: "2"), nofake1, nofake2, nofake3, nofake4, pattern=, seqovl=N, seqovl_pattern=, blob=, nodrop
fakeddisorder direction, payload, fooling, ip_id, rawsend, reconstruct pos= (default: "2"), nofake1-4, pattern=, seqovl=N, seqovl_pattern=, blob=, nodrop
hostfakesplit direction, payload, fooling, ip_id, rawsend, reconstruct host= (шаблон хоста), midhost=, nofake1, nofake2, disorder_after=, blob=, nodrop

SYN-атаки:

Функция Описание
syndata Отправить SYN с данными
synack Работа с SYN/ACK
synack_split Сплит по SYN/ACK

Window size:

Функция Описание
wsize Изменить window size на SYN-ACK
wssize Изменить window size на всех пакетах

Прочее:

Функция Описание
rst Отправить RST
udplen Изменить длину UDP
dht_dn DHT domain name injection

Из zapret-lib.lua:

Функция Описание
pass Ничего не делать (для отладки)
pktdebug Вывести содержимое desync в лог
argdebug Вывести аргументы в лог
posdebug Вывести позиции conntrack
luaexec Выполнить произвольный Lua код

💡 Примеры использования

Простой fake:

--lua-desync=fake:blob=fake_default_tls

Fake с параметрами:

--lua-desync=fake:blob=fake_default_tls:tcp_md5:ip_ttl=3:repeats=5

Multisplit:

--lua-desync=multisplit:pos=1,midsld

Комбинация функций:

--lua-desync=fake:blob=fake_default_tls:tcp_md5 \
--lua-desync=multisplit:pos=1,midsld

С фильтром payload:

--payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls \
--payload=http_req --lua-desync=fake:blob=fake_default_http

📊 Структура параметров

--lua-desync=функция:param1=val1:param2=val2:param3
            ─────────┬─────────────────────────────
                     │
         параметры через двоеточие

Типы параметров:

  • param=value — параметр со значением
  • param — булевый параметр (без значения = true)

🔍 Что получает функция — кратко

Второй параметр — таблица desync — это весь вход функции. Коротко её ключевые части:

  • desync.arg — аргументы этого инстанса (всё после двоеточий в --lua-desync); значения приходят строками, флаг без значения = "" (в Lua истинно).
  • desync.dis — диссект: разобранный на поля текущий пакет (ip/ip6, tcp/udp, payload).
  • desync.l7payload / desync.outgoing — тип содержимого пакета и направление.
  • desync.track — данные потока из conntrack (может отсутствовать!); внутри track.lua_state — память, живущая между пакетами потока.
  • desync.reasm_data / decrypt_data + поля replay* — собранные из нескольких пакетов пейлоады.

Увидеть полное содержимое desync на конкретном пакете можно инстансом pktdebug.

[!tip] Полный справочник по всем полям — в отдельной заметке Прототип функции, все вердикты (включая VERDICT_PRESERVE_NEXT), полная структура desync, диссекта (ip/ip6/tcp/udp/icmp, exthdr, tcp options), track со счётчиками, механика reasm/replay, работа с 32-битными sequence и обработка ICMP/raw IP — всё это подробно разобрано в структура desync и диссекта.


🎯 Полный пример

winws2 ^
  --wf-tcp-out=80,443 ^
  --lua-init=@zapret-lib.lua --lua-init=@zapret-antidpi.lua ^
  --filter-tcp=80 --filter-l7=http ^
  --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 ^
  --lua-desync=multisplit:pos=method+2 ^
  --new ^
  --filter-tcp=443 --filter-l7=tls ^
  --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,rndsni ^
  --lua-desync=multidisorder:pos=1,midsld

Итог

--lua-desync — это сердце nfqws2:

  • 🔹 Вызывает Lua функцию для каждого пакета
  • 🔹 Передаёт параметры через двоеточие
  • 🔹 Можно указывать несколько раз (выполняются последовательно)
  • 🔹 Работает с фильтрами [[payload|--payload]], [[out-range|--out-range]], --in-range
  • 🔹 Можно писать свои функции

📋 Полная таблица функций --lua-desync

🔹 Базовые функции (zapret-lib.lua)

Функция Описание Параметры
pass Ничего не делает (для отладки)
pktdebug Выводит содержимое desync в лог
argdebug Выводит аргументы функции в лог
posdebug Выводит позиции conntrack в лог
luaexec Выполняет произвольный Lua код code=<lua_code>

🔹 Функции из zapret-antidpi.lua

Базовые действия

Функция Аналог nfqws1 Описание Параметры
drop Отбросить пакет dir, payload
send --dup Отправить копию пакета dir, fooling, ip_id, ipfrag, rawsend, reconstruct
pktmod --orig Модифицировать текущий пакет dir, fooling, ip_id

HTTP модификации

Функция Аналог nfqws1 Описание Параметры
http_domcase --domcase Изменить регистр домена (HoSt) dir
http_hostcase --hostcase Изменить регистр заголовка Host dir, spell=<str> (4 символа)
http_methodeol --methodeol Модифицировать EOL метода dir, method=cr|lf|crlf|lfcr, no_space

SYN-атаки

Функция Аналог nfqws1 Описание Параметры
syndata --dpi-desync=syndata Отправить SYN с данными blob=<blob>, tls_mod=<list>, fooling, rawsend, reconstruct, ipfrag
synack Отправить SYN-ACK fooling, rawsend, reconstruct, ipfrag
synack_split Сплит по SYN-ACK pos=<posmarker>, seqovl=N, seqovl_pattern=<blob>

Window size

Функция Аналог nfqws1 Описание Параметры
wsize --wssize Изменить window size на SYN-ACK wsize=N, scale=N
wssize --wssize Изменить window size на всех пакетах wsize=N, scale=N

RST

Функция Аналог nfqws1 Описание Параметры
rst --dpi-desync=rst Отправить RST dir, payload, fooling, ip_id, rawsend, reconstruct, ipfrag, rstack

Fake-атаки

Функция Аналог nfqws1 Описание Параметры
fake --dpi-desync=fake Отправить fake пакет blob=<blob> (обязательный), tls_mod=<list>, dir, payload, fooling, ip_id, rawsend, reconstruct, ipfrag

Сплит и disorder

Функция Аналог nfqws1 Описание Параметры
multisplit --dpi-desync=multisplit Разбить на TCP сегменты pos=<posmarker_list>, seqovl=N, seqovl_pattern=<blob>, blob=<blob>, nodrop
multidisorder --dpi-desync=multidisorder Разбить + обратный порядок pos=<posmarker_list>, seqovl=<posmarker>, seqovl_pattern=<blob>, blob=<blob>, nodrop
tcpseg TCP сегментация по диапазону pos=<range> (обязательный), seqovl=N, seqovl_pattern=<blob>, blob=<blob>

Fake + сплит комбинации

Функция Аналог nfqws1 Описание Параметры
hostfakesplit --dpi-desync=hostfakesplit Fake только для хоста + сплит host=<template>, midhost=<posmarker>, nofake1, nofake2, disorder_after=<posmarker>, blob=<blob>, nodrop
fakedsplit --dpi-desync=fakedsplit Fake + сплит оригинала pos=<posmarker>, nofake1, nofake2, nofake3, nofake4, pattern=<blob>, seqovl=N, seqovl_pattern=<blob>, blob=<blob>, nodrop
fakeddisorder --dpi-desync=fakeddisorder Fake + disorder оригинала pos=<posmarker>, nofake1, nofake2, nofake3, nofake4, pattern=<blob>, seqovl=<posmarker>, seqovl_pattern=<blob>, blob=<blob>, nodrop

UDP

Функция Аналог nfqws1 Описание Параметры
udplen --dpi-desync=udplen Изменить длину UDP пакета dir, payload, min=N, max=N, increment=N (по умолч. 2), pattern=<blob>, pattern_offset=N
dht_dn --dpi-desync=tamper (dht) DHT domain name injection dir, dn=N (по умолч. 2)

🔧 Стандартные параметры (применимы ко многим функциям)

Direction (направление)

Параметр Описание
dir=in Только входящие пакеты
dir=out Только исходящие (по умолчанию)
dir=any Оба направления

Payload фильтр

Параметр Описание
payload=<type_list> Фильтр по типу payload

Fooling (обманки)

Параметр Описание
ip_ttl=N Установить TTL IPv4
ip6_ttl=N Установить Hop Limit IPv6
ip_autottl=delta,min-max Автоматический TTL
ip6_autottl=delta,min-max Автоматический Hop Limit
ip6_hopbyhop[=hex] Добавить Hop-by-Hop заголовок
ip6_hopbyhop2[=hex] Второй Hop-by-Hop
ip6_destopt[=hex] Добавить Destination Options
ip6_destopt2[=hex] Второй Destination Options
ip6_routing[=hex] Добавить Routing заголовок
ip6_ah[=hex] Добавить Authentication Header
tcp_seq=N Добавить к TCP sequence
tcp_ack=N Добавить к TCP ack
tcp_ts=N Добавить к timestamp
tcp_md5[=hex] Добавить TCP MD5 опцию
tcp_flags_set=<list> Установить TCP флаги
tcp_flags_unset=<list> Снять TCP флаги
tcp_ts_up Переместить timestamp наверх
fool=<function> Пользовательская функция обманки

Reconstruct

Параметр Описание
badsum Невалидная контрольная сумма L4

Rawsend

Параметр Описание
repeats=N Количество повторов
ifout=<iface> Интерфейс отправки
fwmark=N fwmark пакета

IP ID

Параметр Описание
ip_id=seq|rnd|zero|none Политика IP ID
ip_id_conn Сохранять IP ID между пакетами

IP фрагментация

Параметр Описание
ipfrag[=function] Включить IP фрагментацию
ipfrag_disorder Отправить фрагменты в обратном порядке
ipfrag_pos_tcp=N Позиция фрагментации TCP (кратно 8)
ipfrag_pos_udp=N Позиция фрагментации UDP (кратно 8)
ipfrag_next=N Next proto для второго фрагмента

TLS модификации

Параметр Описание
tls_mod=rnd Рандомизировать поле random
tls_mod=rndsni Случайный SNI
tls_mod=sni=<domain> Установить конкретный SNI
tls_mod=dupsid Копировать Session ID
tls_mod=padencap Padding encapsulation

📍 Position markers (маркеры позиций)

Маркер Описание
N Абсолютная позиция (число)
-N Позиция с конца
host Начало хоста
endhost Конец хоста
sld Second-level domain
midsld Середина SLD
endsld Конец SLD
method HTTP метод
extlen TLS extensions length
sniext TLS SNI extension
marker+N Маркер + смещение
marker-N Маркер - смещение

💡 Примеры

# Простой fake
--lua-desync=fake:blob=fake_default_tls:tcp_md5

# Fake с TTL и повторами
--lua-desync=fake:blob=fake_default_tls:ip_ttl=3:repeats=5:tls_mod=rnd,rndsni

# Multisplit с seqovl
--lua-desync=multisplit:pos=1,midsld:seqovl=10

# Fakedsplit
--lua-desync=fakedsplit:pos=midsld:nofake1:tcp_md5

# Комбинация fake + multidisorder
--lua-desync=fake:blob=fake_default_tls:tcp_md5 --lua-desync=multidisorder:pos=1,midsld

# UDP length
--lua-desync=udplen:increment=4:min=50

Соответствие флагов nfqws1 → nfqws2

В nfqws1 были готовые флаги --dpi-desync-fooling=. В nfqws2 их нет — вместо этого используются отдельные параметры для каждого действия.


📋 Таблица соответствия

nfqws1 флаг nfqws2 параметр Описание
md5sig tcp_md5 Добавить TCP MD5 signature опцию
badsum badsum Невалидная контрольная сумма L4
badseq tcp_seq=-10000 Сдвинуть TCP sequence (для SYN)
badseq tcp_ack=-66000 Сдвинуть TCP ack (для данных)
datanoack tcp_flags_unset=ack Снять флаг ACK
badack tcp_ack=-66000 Сдвинуть TCP ack
hopbyhop ip6_hopbyhop IPv6 Hop-by-Hop header
hopbyhop2 ip6_hopbyhop2 Второй Hop-by-Hop header
destopt ip6_destopt IPv6 Destination Options
destopt2 ip6_destopt2 Второй Destination Options
ipfrag1 ipfrag IP фрагментация

🔧 Детали каждого флага

md5sigtcp_md5

Добавляет TCP опцию MD5 signature (RFC 2385). DPI не может проверить подпись.

# nfqws1
--dpi-desync-fooling=md5sig

# nfqws2
--lua-desync=fake:blob=fake_default_tls:tcp_md5

badsumbadsum

Делает контрольную сумму TCP/UDP невалидной. Сервер отбросит пакет.

# nfqws1
--dpi-desync-fooling=badsum

# nfqws2
--lua-desync=fake:blob=fake_default_tls:badsum

badseqtcp_seq / tcp_ack

В nfqws1 badseq применял разные значения для SYN и обычных пакетов:

  • SYN пакеты: tcp_seq=-10000
  • Обычные пакеты: tcp_ack=-66000
# nfqws1
--dpi-desync-fooling=badseq

# nfqws2 (для обычных пакетов)
--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000

# nfqws2 (для SYN)
--lua-desync=fake:blob=fake_default_tls:tcp_seq=-10000

badacktcp_ack

Сдвигает TCP acknowledgment number.

# nfqws1
--dpi-desync-fooling=badack

# nfqws2
--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000

Важно! Для Linux нужен tcp_ts_up чтобы работало без badseq:

--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000:tcp_ts_up

datanoacktcp_flags_unset=ack

Снимает флаг ACK с пакета.

# nfqws1
--dpi-desync-fooling=datanoack

# nfqws2
--lua-desync=fake:blob=fake_default_tls:tcp_flags_unset=ack

hopbyhopip6_hopbyhop

Добавляет IPv6 Hop-by-Hop extension header.

# nfqws1
--dpi-desync-fooling=hopbyhop

# nfqws2
--lua-desync=fake:blob=fake_default_tls:ip6_hopbyhop

hopbyhop2ip6_hopbyhop2

Добавляет второй Hop-by-Hop header (нестандартно, ломает обработку).

# nfqws1
--dpi-desync-fooling=hopbyhop2

# nfqws2
--lua-desync=fake:blob=fake_default_tls:ip6_hopbyhop2

destoptip6_destopt

Добавляет IPv6 Destination Options header.

# nfqws1
--dpi-desync-fooling=destopt

# nfqws2
--lua-desync=fake:blob=fake_default_tls:ip6_destopt

ipfrag1ipfrag

IP фрагментация пакета.

# nfqws1
--dpi-desync-fooling=ipfrag1

# nfqws2
--lua-desync=send:ipfrag

💡 Примеры комбинаций

Классический fake с md5sig:

# nfqws1
--dpi-desync=fake --dpi-desync-fooling=md5sig

# nfqws2
--lua-desync=fake:blob=fake_default_tls:tcp_md5

Fake с badseq + md5sig:

# nfqws1
--dpi-desync=fake --dpi-desync-fooling=badseq,md5sig

# nfqws2
--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000:tcp_md5

Fake с TTL:

# nfqws1
--dpi-desync=fake --dpi-desync-ttl=3

# nfqws2
--lua-desync=fake:blob=fake_default_tls:ip_ttl=3

Fake с autottl:

# nfqws1
--dpi-desync=fake --dpi-desync-autottl=-1,3-20

# nfqws2
--lua-desync=fake:blob=fake_default_tls:ip_autottl=-1,3-20:ip6_autottl=-1,3-20

Fakedsplit с badseq + md5sig:

# nfqws1
--dpi-desync=fakedsplit --dpi-desync-fooling=badseq,md5sig --dpi-desync-split-pos=2

# nfqws2
--lua-desync=fakedsplit:pos=2:tcp_ack=-66000:tcp_md5

IPv6 hopbyhop + destopt:

# nfqws1
--dpi-desync=fake --dpi-desync-fooling=hopbyhop,destopt

# nfqws2
--lua-desync=fake:blob=fake_default_tls:ip6_hopbyhop:ip6_destopt

📝 Полный список fooling параметров nfqws2

Параметр Значение Описание
tcp_md5 [=hex] TCP MD5 signature (16 байт)
tcp_seq =N Сдвиг TCP sequence
tcp_ack =N Сдвиг TCP ack
tcp_ts =N Сдвиг TCP timestamp
tcp_flags_set =list Установить TCP флаги
tcp_flags_unset =list Снять TCP флаги
tcp_ts_up Переместить timestamp наверх
badsum Невалидная контрольная сумма
ip_ttl =N Установить TTL
ip6_ttl =N Установить Hop Limit
ip_autottl =delta,min-max Авто TTL
ip6_autottl =delta,min-max Авто Hop Limit
ip6_hopbyhop [=hex] Hop-by-Hop header
ip6_hopbyhop2 [=hex] Второй Hop-by-Hop
ip6_destopt [=hex] Destination Options
ip6_destopt2 [=hex] Второй Destination Options
ip6_routing [=hex] Routing header
ip6_ah [=hex] Authentication header

Быстрая шпаргалка

# md5sig
:tcp_md5

# badsum
:badsum

# badseq (для данных)
:tcp_ack=-66000

# badseq (для SYN)
:tcp_seq=-10000

# badack
:tcp_ack=-66000:tcp_ts_up

# datanoack
:tcp_flags_unset=ack

# TTL
:ip_ttl=3:ip6_ttl=3

# autottl
:ip_autottl=-1,3-20:ip6_autottl=-1,3-20

# IPv6 headers
:ip6_hopbyhop:ip6_destopt

Нет, badseq и badack — это разные вещи!


📊 Разница

Флаг Что меняет Поле TCP Типичное значение
badseq Sequence number tcp.th_seq -10000
badack Acknowledgment number tcp.th_ack -66000

🔬 Как работают

badseq (tcp_seq)

Сдвигает номер последовательности (sequence number) пакета.

Оригинальный пакет:  seq=1000, ack=5000
С badseq (-10000):   seq=-9000 (990), ack=5000
  • Сервер видит пакет с "неправильным" seq
  • Пакет не попадает в окно приёма → отбрасывается
  • DPI может обработать пакет, но сервер его игнорирует

badack (tcp_ack)

Сдвигает номер подтверждения (acknowledgment number) пакета.

Оригинальный пакет:  seq=1000, ack=5000
С badack (-66000):   seq=1000, ack=-61000
  • Сервер видит пакет с "неправильным" ack
  • Пакет может быть отброшен или обработан (зависит от ОС)
  • На Linux с опцией timestamp пакет может быть принят!

⚠️ Важный нюанс для Linux

На Linux badack без badseq может не работать, если есть TCP timestamp опция!

Linux отбрасывает пакеты с плохим ack только если timestamp опция идёт первой в списке TCP опций.

Поэтому в nfqws2 есть параметр tcp_ts_up — он перемещает timestamp наверх:

# Чтобы badack работал на Linux:
--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000:tcp_ts_up

📝 В nfqws1

В nfqws1 флаг badseq был универсальным и применял разные значения в зависимости от типа пакета:

Тип пакета Что менялось Значение
SYN tcp_seq -10000
Данные tcp_ack -66000

Поэтому --dpi-desync-fooling=badseq фактически менял либо seq, либо ack в зависимости от контекста.


🎯 В nfqws2

В nfqws2 нет такой "магии" — вы явно указываете что хотите изменить:

# Изменить sequence (для SYN)
:tcp_seq=-10000

# Изменить ack (для данных)
:tcp_ack=-66000

# Изменить оба
:tcp_seq=-10000:tcp_ack=-66000

💡 Рекомендации

Для fake пакетов (данные):

# Вариант 1: badack с tcp_ts_up (надёжнее на Linux)
--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000:tcp_ts_up

# Вариант 2: md5sig (проще, работает везде)
--lua-desync=fake:blob=fake_default_tls:tcp_md5

# Вариант 3: TTL (если известно расстояние до DPI)
--lua-desync=fake:blob=fake_default_tls:ip_ttl=3

Для syndata (SYN пакеты):

--lua-desync=syndata:blob=fake_default_tls:tcp_seq=-10000

Итог

badseq badack
Поле Sequence Acknowledgment
nfqws2 параметр tcp_seq=N tcp_ack=N
Типичное значение -10000 -66000
Для SYN Да Нет
Для данных ⚠️ Редко Да
Нужен tcp_ts_up Нет Да (на Linux)

Короткий ответ: badseq меняет seq, badack меняет ack — это разные поля TCP заголовка.

tcp_ts_up — нужен не всегда, но рекомендуется для Linux


🔍 Когда tcp_ts_up НУЖЕН

Только на Linux, и только если:

  1. Вы используете tcp_ack (badack) без tcp_seq (badseq)
  2. В пакете есть TCP timestamp опция

Почему?

Linux проверяет timestamp опцию для валидации пакетов. Но есть баг/особенность:

  • Linux отбрасывает пакеты с плохим ack только если timestamp идёт первой в списке TCP опций
  • Если timestamp не первая — пакет может быть принят несмотря на плохой ack!

tcp_ts_up перемещает timestamp в начало списка опций → Linux корректно отбрасывает пакет.


Когда tcp_ts_up НЕ нужен

  1. Целевой сервер — не Linux (Windows, BSD и др.)
  2. Используете tcp_seq (badseq) — тогда пакет отбрасывается по другой причине
  3. Используете tcp_md5 — md5sig работает независимо
  4. Используете ip_ttl — пакет не дойдёт до сервера
  5. В пакете нет timestamp опции — нечего перемещать

📊 Таблица: когда нужен tcp_ts_up

Fooling Linux Windows/BSD tcp_ts_up нужен?
tcp_ack только ⚠️ Может не работать Работает Да (для Linux)
tcp_seq только Работает Работает Нет
tcp_ack + tcp_seq Работает Работает Нет
tcp_md5 Работает Работает Нет
ip_ttl Работает Работает Нет

💡 Рекомендация

Если не уверены — добавляйте tcp_ts_up. Он не навредит, но гарантирует работу на Linux:

# Безопасный вариант (работает везде)
--lua-desync=fake:blob=fake_default_tls:tcp_ack=-66000:tcp_ts_up

# Или просто используйте md5sig — проще и надёжнее
--lua-desync=fake:blob=fake_default_tls:tcp_md5

🎯 Короткий ответ

Нет, не обязательно, но:

  • На Linux без tcp_ts_up badack может не сработать
  • На Windows/BSD работает и без него
  • Рекомендуется добавлять для универсальности

autottl — формат обязателен, значений по умолчанию нет!


Нельзя использовать без цифр

# ОШИБКА! Так нельзя:
--lua-desync=fake:blob=fake_default_tls:ip_autottl

# ОШИБКА! Так тоже нельзя:
--lua-desync=fake:blob=fake_default_tls:ip_autottl=

Будет ошибка:

parse_autottl: invalid value '...'

Обязательный формат

ip_autottl=delta,min-max
ip6_autottl=delta,min-max
Параметр Описание
delta Сдвиг от вычисленного hop count (может быть отрицательным)
min Минимальное значение TTL
max Максимальное значение TTL

💡 Примеры

# Стандартный вариант: delta=-1, диапазон 3-20
:ip_autottl=-1,3-20:ip6_autottl=-1,3-20

# Более агрессивный: delta=-2
:ip_autottl=-2,3-20:ip6_autottl=-2,3-20

# Осторожный: delta=0 (точно до DPI)
:ip_autottl=0,3-20:ip6_autottl=0,3-20

🔬 Как работает autottl

  1. Получает incoming TTL из ответа сервера (SYN-ACK)
  2. Угадывает начальный TTL сервера (64, 128 или 255)
  3. Вычисляет hop count = начальный TTL - incoming TTL
  4. Применяет формулу: fake_ttl = hop_count + delta
  5. Ограничивает результат диапазоном min-max

Пример расчёта:

Incoming TTL = 52
Угаданный начальный TTL = 64
Hop count = 64 - 52 = 12
delta = -1
Результат = 12 + (-1) = 11

Если min=3, max=20: итоговый TTL = 11 ✓

⚠️ Важно

  • Требует conntrack — нужно видеть входящие пакеты для определения TTL
  • Не работает если incoming TTL не попадает в диапазоны (32-64, 96-128, 223-255)
  • Fallback на ip_ttl — если autottl не сработал, используется ip_ttl если указан
# С fallback на фиксированный TTL:
:ip_ttl=5:ip_autottl=-1,3-20

📝 Типичное использование

# Полный пример с autottl и fallback
--lua-desync=fake:blob=fake_default_tls:tcp_md5:ip_ttl=5:ip_autottl=-1,3-20:ip6_ttl=5:ip6_autottl=-1,3-20

📚 См. также

Где --lua-desync в общей картине:

  • profile — блок, внутри которого живёт --lua-desync; как перебирать стратегии под свой DPI
  • preset — файл стратегии целиком (набор профилей)

Соседние поля профиля:

  • filter — фильтры (--filter-tcp/udp/l7, --hostlist, --ipset): какой трафик попадёт в desync
  • payload — типы содержимого пакета (--payload)
  • out-range — на каких по счёту пакетах срабатывать (--out-range)
  • blob — именованные заготовки пакетов (blob=…), на которые ссылаются fake/syndata

Отдельные техники десинхронизации:

Как это встроено в общую картину:

  • жизненный цикл desync-функции — общий скелет всех техник: восемь стадий от отсева чужого транспорта до вердикта, и чем каждая функция от скелета отличается
  • структура desync и диссекта — полный справочник входных данных функции: ctx/desync, вердикты, диссект, track, reasm/replay, ICMP/raw IP
  • структура проекта — почему логика обхода вынесена в Lua, а C-ядро её только вызывает
  • схема обработки трафика — где именно в конвейере пакета вызываются desync-инстансы
  • multisplit — детальный разбор одной функции: что она получает в desync и что возвращает

[!quote] 🤖 Эти статьи открыты — можно обучать на них ИИ При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны в Forgejo: исходник этой заметки · весь репозиторий.