# `syndata` --- payload в TCP SYN (zapret2 / nfqws2)
**Файл:** `lua/zapret-antidpi.lua:385`
**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-сегментация), [[wssize]] (управление размером окна), [[multidisorder]], [[fakedsplit]], [[fakeddisorder]].
---
## Оглавление
- [Зачем нужен syndata](#зачем-нужен-syndata)
- [Быстрый старт](#быстрый-старт)
- [Принцип работы](#принцип-работы)
- [Что такое SYN с payload](#что-такое-syn-с-payload)
- [Нулевая фаза](#нулевая-фаза)
- [Логика обработки пакетов](#логика-обработки-пакетов)
- [Полный список аргументов](#полный-список-аргументов)
- [A) Собственные аргументы syndata](#a-собственные-аргументы-syndata)
- [B) Standard fooling](#b-standard-fooling)
- [C) Standard reconstruct](#c-standard-reconstruct)
- [D) Standard rawsend](#d-standard-rawsend)
- [E) Standard ipfrag](#e-standard-ipfrag)
- [tls_mod --- модификация TLS в syndata](#tls_mod--модификация-tls-в-syndata)
- [Работающие модификации](#работающие-модификации)
- [dupsid и padencap --- молчаливое игнорирование](#dupsid-и-padencap--молчаливое-игнорирование)
- [Почему dupsid и padencap не работают](#почему-dupsid-и-padencap-не-работают)
- [Псевдокод алгоритма](#псевдокод-алгоритма)
- [Отличия от fake](#отличия-от-fake)
- [Работа с хостлистами](#работа-с-хостлистами)
- [Комбинирование с другими функциями](#комбинирование-с-другими-функциями)
- [Нюансы и подводные камни](#нюансы-и-подводные-камни)
- [Миграция с nfqws1](#миграция-с-nfqws1)
- [Практические примеры](#практические-примеры)
---
## Зачем нужен syndata
Некоторые DPI начинают анализировать соединение уже с первого пакета --- с SYN. Они запоминают IP и порт клиента, ждут данные и сопоставляют их с сигнатурами. `syndata` атакует этот механизм на самом раннем этапе:
1. **Ложные данные в SYN:** DPI видит SYN-пакет с payload (например, фейковый TLS ClientHello) и может принять его за начало реального соединения
2. **Сбой трекинга:** если DPI привязывает сессию к содержимому первого пакета, подменный SYN может направить трекинг по ложному пути
3. **Обход до handshake:** воздействие происходит до TCP handshake --- DPI ещё не видел реальных данных приложения
**Важно:** TCP SYN с payload --- это валидная TCP-операция (RFC 793 разрешает данные в SYN, хотя многие стеки их игнорируют до завершения handshake). Сервер примет SYN, но payload из него обычно отбросит --- DPI же может попытаться его проанализировать.
---
## Быстрый старт
Минимально (16 нулевых байт в SYN):
```bash
--lua-desync=syndata
```
С TLS-фейком:
```bash
--lua-desync=syndata:blob=fake_default_tls
```
С TLS-фейком и модификацией SNI:
```bash
--lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,rndsni
```
Типовая комбинация (wssize + syndata + multisplit):
```bash
--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`, [[wssize]] |
| **Фаза 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 нулевых байт (`\x00` x 16)
- **Описание:** Payload, который будет добавлен в SYN-пакет. Должен помещаться в один пакет --- сегментация **невозможна** (используется `rawsend_dissect_ipfrag`, а не `rawsend_payload_segmented`). Если blob не задан, отправляются 16 нулевых байт
- **Примеры:**
- `blob=fake_default_tls` --- стандартный TLS-фейк из zapret
- `blob=fake_default_http` --- стандартный HTTP-фейк
- `blob=0xDEADBEEF` --- inline hex
- `blob=my_custom_payload` --- предзагруженный blob
- без `blob=` --- 16 нулей (дефолт)
#### `tls_mod`
- **Формат:** `tls_mod=<mod1[,mod2,...]>`
- **Тип:** строка со списком модификаций через запятую
- **По умолчанию:** не задан
- **Описание:** Модификации TLS-данных в payload перед отправкой. Применяется **после** `apply_fooling`. Подробности --- в разделе [tls_mod](#tls_mod--модификация-tls-в-syndata)
- **Работающие значения:** `rnd`, `rndsni`, `sni=<str>` (включая `sni=%var`)
- **Молча игнорируемые:** `dupsid`, `padencap`
- **Примеры:**
- `tls_mod=rnd` --- рандомизация TLS-полей
- `tls_mod=rndsni` --- рандомизация SNI
- `tls_mod=sni=google.com` --- замена SNI
- `tls_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`:
```lua
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)`:
```c
// 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".
---
## Псевдокод алгоритма
```lua
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 ложными данными **до** того, как пойдёт реальный трафик
- В комбинации с [[wssize]] и [[multisplit]] для многоуровневой атаки
---
## Работа с хостлистами
На фазе 0 (SYN) zapret **не знает** hostname --- приложение ещё не отправило HTTP-запрос или TLS ClientHello. Поэтому стандартная фильтрация по хостлистам (`--hostlist=...`) не работает с syndata напрямую.
Единственный способ --- `--ipcache-hostname`:
```bash
nfqws2 --ipcache-hostname \
--hostlist=blocked.txt \
--lua-desync=syndata:blob=fake_default_tls
```
Как это работает:
1. Первое соединение к IP-адресу проходит **без** syndata (hostname ещё не известен)
2. Из первого соединения zapret узнаёт hostname (из TLS ClientHello или HTTP Host) и кеширует привязку IP -> hostname
3. Последующие SYN к этому IP уже проходят через syndata, потому что zapret знает hostname из кеша
**Следствие:** syndata с хостлистом не подействует на **первое** соединение к данному IP. Это может быть проблемой для сайтов с уникальными IP или CDN с ротацией адресов.
---
## Комбинирование с другими функциями
`syndata` часто используется в цепочке с другими функциями. **Порядок инстансов важен!**
### Типовая цепочка: wssize + syndata + multisplit
```bash
--lua-desync=wssize:wsize=1:scale=6 \
--lua-desync=syndata \
--lua-desync=multisplit:pos=midsld
```
Что происходит:
1. **SYN-пакет приходит:**
- `wssize` модифицирует TCP Window Size в SYN (wsize=1, scale=6)
- `syndata` добавляет payload в SYN, дропает оригинал, отправляет модифицированный
- `multisplit` ничего не делает (SYN, нет данных для нарезки)
2. **Первый data-пакет (например, TLS ClientHello) приходит:**
- `wssize` --- миссия уже выполнена (cutoff или пропуск)
- `syndata` делает `instance_cutoff` (пакет не SYN)
- `multisplit` нарезает payload по позиции `midsld`
**Почему wssize перед syndata:** [[wssize]] модифицирует TCP Window Size в SYN-пакете. Если поставить после syndata, wssize увидит `VERDICT_DROP` и не получит SYN. Если перед --- wssize модифицирует dissect, затем syndata использует `deepcopy` этого (уже модифицированного) dissect.
### Цепочка: syndata + fake + multisplit
```bash
--lua-desync=syndata:blob=fake_default_tls \
--lua-desync=fake:blob=fake_default_tls:tcp_md5 \
--lua-desync=multisplit:pos=1,midsld
```
Многоуровневая атака:
1. Фаза 0: SYN с фейковым TLS
2. Фаза 1: фейковый пакет с fooling (tcp_md5)
3. Фаза 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 с правильным sequence
- `tcp_ack=N` --- невалидный ack в SYN
- `badsum` --- сервер отбросит пакет с плохой checksum
- `tcp_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) |
### Пример полной миграции
```bash
# 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
```
```bash
# 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
```
```bash
# nfqws1:
nfqws --dpi-desync=syndata \
--dpi-desync-fooling=md5sig
# nfqws2:
nfqws2 \
--lua-desync=syndata:tcp_md5
```
---
## Практические примеры
### Минимальный (дефолт: 16 нулей в SYN)
```bash
--lua-desync=syndata
```
Отправляет SYN с 16 нулевыми байтами вместо обычного SYN. Простейший вариант --- может сбить DPI, не ожидающий payload в SYN.
### С TLS-фейком
```bash
--lua-desync=syndata:blob=fake_default_tls
```
SYN содержит стандартный TLS ClientHello из zapret. DPI может принять это за начало TLS-сессии.
### С кастомным blob из файла
```bash
--blob=mysyndata:@custom_syn_payload.bin \
--lua-desync=syndata:blob=mysyndata
```
Загружает произвольный payload из файла и вставляет в SYN.
### С inline hex blob
```bash
--lua-desync=syndata:blob=0x160301000100
```
6 байт inline hex --- минимальный TLS record header.
### С рандомизацией TLS
```bash
--lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,rndsni
```
TLS-фейк с рандомизированными полями и SNI. Каждый SYN будет содержать уникальные random/session_id/SNI.
### С заменой SNI
```bash
--lua-desync=syndata:blob=fake_default_tls:tls_mod=sni=google.com
```
SYN содержит TLS ClientHello с SNI `google.com`. DPI может записать в трекер "это соединение к google.com" и не блокировать.
### С TCP MD5
```bash
--lua-desync=syndata:tcp_md5
```
SYN с 16 нулями и TCP MD5 option. Сервер без MD5 проигнорирует опцию, DPI может быть сбит нестандартным TCP-заголовком.
### С TTL fooling (осторожно!)
```bash
--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-фрагментацией
```bash
--lua-desync=syndata:blob=fake_default_tls:ipfrag:ipfrag_disorder
```
SYN с TLS-фейком, фрагментированный на IP-уровне в обратном порядке. DPI, не собирающий IP-фрагменты, не увидит полный пакет.
### С IP-фрагментацией (кастомная позиция)
```bash
--lua-desync=syndata:blob=fake_default_tls:ipfrag:ipfrag_pos_tcp=24
```
Фрагментация по позиции 24 байта (кратно 8). Первый фрагмент содержит TCP-заголовок, второй --- payload.
### Типовая боевая комбинация: wssize + syndata + multisplit
```bash
--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
```bash
--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.
### Отладка: повторы отправки
```bash
--lua-desync=syndata:blob=fake_default_tls:repeats=3
```
Каждый SYN с payload отправляется 3 раза. Полезно для отладки или если DPI обрабатывает только N-й пакет.
### IPv6: extension headers
```bash
--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.