---
date: 2026-02-17
tags:
  - zapret
  - zapret2
  - nfqws2
  - lua
  - lua-desync
  - antidpi
  - tcp
  - fakedsplit
  - fake
  - seqovl
aliases:
  - fakedsplit
---

# `fakedsplit` — TCP-сегментация с замешиванием фейков (zapret2 / nfqws2)

**Файл:** `lua/zapret-antidpi.lua:826`
**nfqws1 эквивалент:** `--dpi-desync=fakedsplit`
**Сигнатура:** `function fakedsplit(ctx, desync)`

`fakedsplit` разрезает TCP payload на **две** части по одной позиции и отправляет их вперемешку с **фейковыми** сегментами того же размера. Фейки содержат мусор (pattern), но имеют те же TCP sequence и размеры, что и оригиналы. Для DPI это выглядит как серия ретрансмиссий — он не может понять, какой сегмент настоящий, а какой — подделка. Для сервера фейки отбрасываются благодаря fooling (badseq, md5sig, badsum и т.д.).

Родственные функции: [[multisplit]] (простая сегментация), [[multidisorder]] (обратный порядок), [[fakeddisorder]] (фейки + обратный порядок), [[hostfakesplit]] (по hostname), [[tcpseg]] (диапазон), [[oob]] (urgent byte).

Общий для всех техник дурения порядок работы — восемь стадий от отсева чужого транспорта до вердикта — разобран в [[жизненный цикл desync-функции]]; здесь описано только то, чем `fakedsplit` от этого скелета отличается.

---

## Оглавление

- [Зачем нужен fakedsplit](#зачем-нужен-fakedsplit)
- [Быстрый старт](#быстрый-старт)
- [Откуда берутся данные для нарезки](#откуда-берутся-данные-для-нарезки)
- [Маркер позиции (pos)](#маркер-позиции-pos)
  - [Типы маркеров](#типы-маркеров)
  - [Относительные маркеры](#относительные-маркеры)
  - [Арифметика маркеров](#арифметика-маркеров)
  - [Как маркер разрешается в коде](#как-маркер-разрешается-в-коде)
  - [Важные нюансы pos](#важные-нюансы-pos)
- [Последовательность отправки (6 пакетов)](#последовательность-отправки-6-пакетов)
  - [ASCII-диаграмма](#ascii-диаграмма)
  - [Что видит DPI](#что-видит-dpi)
  - [Что видит сервер](#что-видит-сервер)
- [Два набора опций: opts_orig vs opts_fake](#два-набора-опций-opts_orig-vs-opts_fake)
- [seqovl — скрытый фейк внутри сегмента](#seqovl--скрытый-фейк-внутри-сегмента)
  - [Принцип работы seqovl](#принцип-работы-seqovl)
  - [seqovl_pattern](#seqovl_pattern)
- [pattern — заполнение фейков](#pattern--заполнение-фейков)
- [nofake1..nofake4 — отключение отдельных фейков](#nofake1nofake4--отключение-отдельных-фейков)
- [Полный список аргументов](#полный-список-аргументов)
  - [A) Собственные аргументы fakedsplit](#a-собственные-аргументы-fakedsplit)
  - [B) Standard direction](#b-standard-direction)
  - [C) Standard payload](#c-standard-payload)
  - [D) Standard fooling](#d-standard-fooling)
  - [E) Standard ipid](#e-standard-ipid)
  - [F) Standard reconstruct](#f-standard-reconstruct)
  - [G) Standard rawsend](#g-standard-rawsend)
- [Порядок отправки — подробно с seqovl](#порядок-отправки--подробно-с-seqovl)
- [Поведение при replay / reasm](#поведение-при-replay--reasm)
- [Автосегментация по MSS](#автосегментация-по-mss)
- [Место в общем скелете](#место-в-общем-скелете)
- [Псевдокод алгоритма](#псевдокод-алгоритма)
- [Нюансы и подводные камни](#нюансы-и-подводные-камни)
- [Отличия от других функций сегментации](#отличия-от-других-функций-сегментации)
- [Миграция с nfqws1](#миграция-с-nfqws1)
- [Практические примеры](#практические-примеры)

---

## Зачем нужен fakedsplit

Обычная сегментация ([[multisplit]]) разрезает payload, но DPI может просто реассемблировать поток. Отдельная отправка фейка ([[fake]]) работает, но DPI может отбросить фейк по эвристикам (слишком другой TTL, плохой sequence).

`fakedsplit` комбинирует оба подхода: он **одновременно** разрезает и замешивает фейки. При этом фейки:

1. **Совпадают по размеру** с реальными частями
2. **Имеют те же TCP sequence numbers** — выглядят как ретрансмиссии
3. **Окружают** каждую реальную часть с двух сторон (до и после)

Для DPI поток выглядит так: 6 TCP-сегментов, из которых по 3 пары — "ретрансмиссии" одного и того же. Какой из трёх сегментов каждой пары настоящий? DPI не знает. Сервер знает — потому что фейки имеют невалидные заголовки (fooling), и TCP-стек их молча отбросит.

---

## Быстрый старт

Минимально (разрез по позиции 2, payload=known, dir=out):

```bash
--lua-desync=fakedsplit:tcp_ack=-66000
```

Типовой TLS-разрез с badseq:

```bash
--payload=tls_client_hello --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up
```

HTTP с разрезом по методу:

```bash
--payload=http_req --lua-desync=fakedsplit:pos=method+2:tcp_ack=-66000:tcp_ts_up
```

С seqovl для дополнительной маскировки:

```bash
--payload=tls_client_hello --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up:seqovl=5:seqovl_pattern=0x1603030000
```

---

## Откуда берутся данные для нарезки

Внутри `fakedsplit` данные (`data`) выбираются в следующем порядке приоритетов:

```
1. blob_or_def(desync, desync.arg.blob)    — если задан blob= и он существует
2. desync.reasm_data                        — если есть реассемблированные данные (multi-packet payload)
3. desync.dis.payload                       — текущий пакет (fallback)
```

**Следствие:** все маркеры `pos`, `seqovl` и прочие аргументы применяются именно к тем данным, которые реально выбраны. Если вы задали `blob=myblob`, маркеры вроде `midsld` будут работать только если `myblob` содержит валидный TLS/HTTP payload, который zapret может распознать.

---

## Маркер позиции (pos)

`pos` — главный аргумент `fakedsplit`. Определяет **где** внутри payload будет произведён разрез. В отличие от [[multisplit]], `pos` — это **один маркер**, а не список. Payload всегда делится ровно на **две части**.

### Типы маркеров

| Тип | Описание | Пример |
|:----|:---------|:-------|
| **Абсолютный положительный** | Смещение от начала payload, считая с 0. `pos=N` → первые N байт становятся отдельным сегментом | `2`, `5`, `100` |
| **Абсолютный отрицательный** | Смещение от конца payload. `-1` = последний байт | `-1`, `-10`, `-50` |
| **Относительный** | Логическая позиция внутри распознанного payload. Привязана к структуре протокола | `midsld`, `host`, `sniext` |

### Относительные маркеры

| Маркер | Описание | Для каких payload |
|:-------|:---------|:------------------|
| `method` | Начало HTTP-метода (`GET`, `POST`, `HEAD`, `PUT` и т.д.). Обычно позиция 0, но может стать 1-2 при использовании `http_methodeol` | `http_req` |
| `host` | Первый байт имени хоста (`Host:` в HTTP, SNI в TLS) | `http_req`, `tls_client_hello` |
| `endhost` | Байт, **следующий** за последним байтом имени хоста. Т.е. `host..endhost-1` = полный hostname | `http_req`, `tls_client_hello` |
| `sld` | Первый байт домена второго уровня (SLD). Для `www.example.com` — это `e` в `example` | `http_req`, `tls_client_hello` |
| `endsld` | Байт, следующий за последним байтом SLD. Для `example.com` — это `.` после `example` | `http_req`, `tls_client_hello` |
| `midsld` | Середина SLD (самый популярный маркер). Для `example` (7 символов) — позиция 3-го или 4-го символа | `http_req`, `tls_client_hello` |
| `sniext` | Начало поля данных SNI extension в TLS ClientHello. Extension состоит из type (2 байта) + length (2 байта) + **данные** — sniext указывает на начало данных | `tls_client_hello` |
| `extlen` | Поле длины всех TLS extensions | `tls_client_hello` |

### Арифметика маркеров

К любому маркеру можно прибавить (+) или вычесть (-) целое число:

```
midsld+1      — один байт ПОСЛЕ середины SLD
midsld-1      — один байт ДО середины SLD
endhost-2     — два байта до конца hostname
method+2      — два байта после начала метода (разрежет "GET " после "GE")
sniext+1      — один байт после начала SNI extension data
host+3        — три байта после начала hostname
-1            — последний байт payload (абсолютный, не относительный)
```

### Как маркер разрешается в коде

В отличие от [[multisplit]], который вызывает `resolve_multi_pos` (парсит список через запятую), `fakedsplit` вызывает **`resolve_pos`** напрямую — для одного маркера:

```lua
local pos = resolve_pos(data, desync.l7payload, spos)
```

Функция `resolve_pos`:

1. Разбирает маркер (имя + арифметика)
2. Если маркер не может быть разрешён (например, `midsld` для `unknown` payload) — возвращает `nil`
3. При успехе возвращает абсолютную позицию (1-based, как в Lua)

Далее проверяется:

```lua
if pos == 1 then
    DLOG("fakedsplit: split pos resolved to 0. cannot split.")
    -- ничего не делает
end
```

### Важные нюансы pos

- **Только ОДИН маркер.** `pos=midsld,endhost` НЕ работает. Запятая не парсится — это не список. Если нужно несколько точек разреза с фейками — используйте цепочку нескольких `fakedsplit`
- **Разрез в самом начале данных отбрасывается.** Если маркер разрешается в Lua-позицию 1 — а это маркер `0`, поскольку в командной строке смещения считаются с нуля, — функция логирует "split pos resolved to 0. cannot split." и ничего не делает. Под запрет попадает `pos=0`, а не `pos=1`; частая жертва правила — `pos=method` для HTTP, где метод лежит на смещении 0
- **Неразрешимый маркер => ничего не делается.** Если `resolve_pos` вернул `nil` (маркер не разрешился), fakedsplit логирует "cannot resolve pos" и пропускает
- **По умолчанию `pos=2`.** Если `pos` не задан, payload делится на 2 части: первые 2 байта отдельным сегментом, весь остаток — вторым

---

## Последовательность отправки (6 пакетов)

`fakedsplit` отправляет **до 6 пакетов** (при включённых всех фейках):

| # | Что | Тип | Отключение | Опции |
|:--|:----|:----|:-----------|:------|
| 1 | Фейк 1-й части | fake | `nofake1` | `opts_fake` (полный fooling + reconstruct + repeats) |
| 2 | Реальная 1-я часть (+seqovl) | orig | -- | `opts_orig` (только tcp_ts_up, без repeats) |
| 3 | Фейк 1-й части (повтор) | fake | `nofake2` | `opts_fake` |
| 4 | Фейк 2-й части | fake | `nofake3` | `opts_fake` |
| 5 | Реальная 2-я часть | orig | -- | `opts_orig` |
| 6 | Фейк 2-й части (повтор) | fake | `nofake4` | `opts_fake` |

**Ключевой момент:** каждая реальная часть **окружена** фейками того же размера и с тем же TCP sequence. DPI видит "тройки ретрансмиссий" и не может определить, какая из трёх — настоящая.

### ASCII-диаграмма

```
Payload: [=======ЧАСТЬ 1=======|=======ЧАСТЬ 2=======]
                               ^pos

Время отправки (сверху вниз):

  #1  FAKE1  [XXXXXXXXXXXXXXXXXXXXX]  seq=0       len=pos-1      opts_fake
  #2  REAL1  [=====================]  seq=-seqovl len=pos-1+sovl  opts_orig
  #3  FAKE1  [XXXXXXXXXXXXXXXXXXXXX]  seq=0       len=pos-1      opts_fake
  #4  FAKE2  [XXXXXXXXXXXXXXXXXXXXX]  seq=pos-1   len=#data-pos+1 opts_fake
  #5  REAL2  [=====================]  seq=pos-1   len=#data-pos+1 opts_orig
  #6  FAKE2  [XXXXXXXXXXXXXXXXXXXXX]  seq=pos-1   len=#data-pos+1 opts_fake

  X = мусор (pattern)
  = = реальные данные
```

### Что видит DPI

```
Поток TCP-сегментов на проводе:

  seq=0      [XXXXXXX]  ← fake 1  (мусор)
  seq=-sovl  [PPP|REAL1] ← real 1  (seqovl pattern + данные)
  seq=0      [XXXXXXX]  ← fake 1  (мусор, "ретрансмиссия")
  seq=pos    [XXXXXXX]  ← fake 2  (мусор)
  seq=pos    [==REAL2=]  ← real 2  (данные)
  seq=pos    [XXXXXXX]  ← fake 2  (мусор, "ретрансмиссия")

DPI видит: "3 сегмента с seq=0, 3 сегмента с seq=pos — похоже на ретрансмиссии.
           Какой из каждой тройки настоящий? Непонятно."
```

### Что видит сервер

```
Сервер (TCP-стек):

  seq=0,     данные=мусор   → fooling (badseq/md5/badsum) → ОТБРОШЕН
  seq=-sovl, данные=PPP+R1  → seqovl-часть за window → отброшена; R1 → ПРИНЯТ
  seq=0,     данные=мусор   → fooling → ОТБРОШЕН
  seq=pos,   данные=мусор   → fooling → ОТБРОШЕН
  seq=pos,   данные=REAL2   → нормальный пакет → ПРИНЯТ
  seq=pos,   данные=мусор   → fooling → ОТБРОШЕН

Результат: сервер собрал [REAL1][REAL2] = полный оригинальный payload
```

---

## Два набора опций: opts_orig vs opts_fake

Это ключевое отличие `fakedsplit` от [[multisplit]]. Внутри функции создаются **два набора** опций:

```lua
-- Для оригинальных частей:
local opts_orig = {
    rawsend    = rawsend_opts_base(desync),  -- БЕЗ repeats!
    reconstruct = {},                         -- пустой (без badsum)
    ipfrag     = {},                          -- пустой (без IP-фрагментации)
    ipid       = desync.arg,                  -- ip_id применяется
    fooling    = {tcp_ts_up = desync.arg.tcp_ts_up}  -- ТОЛЬКО tcp_ts_up
}

-- Для фейковых частей:
local opts_fake = {
    rawsend    = rawsend_opts(desync),        -- С repeats!
    reconstruct = reconstruct_opts(desync),    -- badsum если задан
    ipfrag     = {},                          -- пустой (без IP-фрагментации)
    ipid       = desync.arg,                  -- ip_id применяется
    fooling    = desync.arg                    -- ВСЁ fooling целиком
}
```

**Сводная таблица:**

| Что | opts_orig (оригиналы) | opts_fake (фейки) |
|:----|:----------------------|:-------------------|
| **fooling** | Только `tcp_ts_up` | Всё (tcp_ack, tcp_seq, tcp_md5, ip_ttl, badseq, ...) |
| **reconstruct** | Нет (пустой `{}`) | Да (`badsum` если задан) |
| **rawsend.repeats** | Нет (`rawsend_opts_base`) | Да (`rawsend_opts`) |
| **rawsend.ifout** | Да | Да |
| **rawsend.fwmark** | Да | Да |
| **ipid** | Да | Да |
| **ipfrag** | Нет (пустой `{}`) | Нет (пустой `{}`) |

**Почему так:**
- Оригиналы **должны** быть приняты сервером => никакого fooling (кроме безвредного tcp_ts_up), никакого badsum
- Фейки **должны** быть отброшены сервером => полный fooling + badsum
- `repeats` — множественная отправка имеет смысл только для фейков (больше шума для DPI)
- `ipfrag` **не используется** ни для чего — fakedsplit работает исключительно на уровне TCP-сегментов
- `ipid` и базовый `rawsend` (ifout, fwmark) нужны обоим — это уровень IP/маршрутизации

---

## seqovl — скрытый фейк внутри сегмента

**seqovl** (Sequence Overlap) — техника скрытого замешивания фейковых данных в реальный TCP-сегмент через манипуляцию TCP sequence number. В `fakedsplit` seqovl применяется **только к первому реальному сегменту** (пакет #2).

### Принцип работы seqovl

```
Без seqovl:
  TCP seq: 0
  Данные:  [РЕАЛЬНАЯ_ЧАСТЬ_1]
  Сервер:  принимает [РЕАЛЬНАЯ_ЧАСТЬ_1] целиком

С seqovl=10:
  TCP seq: -10            (уменьшен на 10)
  Данные:  [PATTERN_10_БАЙТ][РЕАЛЬНАЯ_ЧАСТЬ_1]

  Что видит DPI:
    Единый TCP-сегмент начиная с seq -10.
    DPI анализирует весь блок, включая PATTERN.
    Если PATTERN содержит ложный SNI — DPI может принять его за настоящий.

  Что видит сервер (TCP-стек):
    TCP window начинается с seq 0.
    Байты -10..-1 выходят за левую границу window => отбрасываются.
    Байты с 0 (РЕАЛЬНАЯ_ЧАСТЬ_1) => принимаются.
```

**Визуализация:**

```
           TCP window boundary
                 |
  |  ОТБРОСИТЬ  | ПРИНЯТЬ          |
  | PATTERN(10) | РЕАЛЬНАЯ_ЧАСТЬ_1 |
  ^seq=-10       ^seq=0
```

**seqovl в fakedsplit — дополнительный уровень защиты** поверх фейков. Даже если DPI научился отбрасывать фейковые сегменты, seqovl-данные внутри реального сегмента он может не распознать.

**Важно:** в `fakedsplit` `seqovl` — только **число** (не маркер). Маркеры поддерживаются в [[fakeddisorder]] и [[multidisorder]], но не здесь.

### seqovl_pattern

Паттерн, которым заполняется seqovl-область (N байт слева от реальных данных). По умолчанию — `0x00` (нули).

В `fakedsplit` `seqovl_pattern` — это **имя blob**. Паттерн повторяется до нужной длины `seqovl`.

```bash
# Inline hex blob (маскировка под начало TLS record)
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:seqovl=5:seqovl_pattern=0x1603030000

# Предзагруженный blob
--blob=tlspat:0x1603030100 \
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:seqovl=8:seqovl_pattern=tlspat
```

Если `optional` задан и blob `seqovl_pattern` отсутствует — используется нулевой паттерн (seqovl не отменяется).

---

## pattern — заполнение фейков

Аргумент `pattern` задаёт содержимое фейковых сегментов. Это имя blob, из которого генерируется паттерн для заполнения фейков.

```lua
fakepat = desync.arg.pattern and blob(desync, desync.arg.pattern) or "\x00"
```

- По умолчанию: `\x00` (нулевые байты)
- Фейк первой части: `pattern(fakepat, 1, pos-1)` — паттерн со смещением 1, длиной pos-1
- Фейк второй части: `pattern(fakepat, pos, #data-pos+1)` — паттерн со смещением pos, длиной остатка

Смещение паттерна (`pos`) соответствует смещению TCP sequence отсылаемой части. Это значит, что если DPI сравнивает байты фейка и оригинала побайтово — он увидит разные данные в одних и тех же позициях. Но если он просто реассемблирует поток — паттерн не сможет "обмануть" конкретную сигнатуру (для этого нужен осмысленный blob).

```bash
# Фейки заполнены случайными данными из blob
--blob=rndpat:0xDEADBEEFCAFEBABE \
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:pattern=rndpat

# Фейки заполнены нулями (по умолчанию)
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000
```

---

## nofake1..nofake4 — отключение отдельных фейков

Каждый из 4 фейковых пакетов можно отключить индивидуально:

| Флаг | Отключает | Позиция в потоке |
|:-----|:----------|:-----------------|
| `nofake1` | Фейк 1-й части (до реальной 1-й) | #1 |
| `nofake2` | Фейк 1-й части (после реальной 1-й) | #3 |
| `nofake3` | Фейк 2-й части (до реальной 2-й) | #4 |
| `nofake4` | Фейк 2-й части (после реальной 2-й) | #6 |

Минимально необходимые пакеты — только два реальных (#2, #5). Все 4 фейка можно отключить:

```bash
# Без фейков вообще (по сути = multisplit с одной позицией)
--lua-desync=fakedsplit:pos=midsld:nofake1:nofake2:nofake3:nofake4
```

Типичные комбинации:

```bash
# Только "передние" фейки (до реальных частей)
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:nofake2:nofake4

# Только "задние" фейки (после реальных частей)
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:nofake1:nofake3

# Фейки только для 1-й части
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:nofake3:nofake4
```

---

## Полный список аргументов

Формат вызова:

```
--lua-desync=fakedsplit[:arg1[=val1][:arg2[=val2]]...]
```

Все `val` приходят в Lua как строки. Если `=val` не указан, значение = пустая строка `""` (в Lua это truthy), поэтому флаги пишутся просто как `:optional`, `:nodrop`, `:tcp_ts_up`.

### A) Собственные аргументы fakedsplit

#### `pos`

- **Формат:** `pos=<marker>`
- **Тип:** строка — **один** маркер (НЕ список!)
- **По умолчанию:** `"2"`
- **Описание:** Точка разреза. Payload делится на 2 части: `data[1..pos-1]` и `data[pos..#data]`
- **Примеры:**
  - `pos=2` — разрез после 2-го байта (дефолт)
  - `pos=1` — первый байт уходит отдельным сегментом
  - `pos=midsld` — разрез посередине SLD
  - `pos=method+2` — после первых 2 символов HTTP-метода
  - `pos=host` — перед началом hostname
  - `pos=sniext+1` — после начала SNI extension data

#### `pattern`

- **Формат:** `pattern=<blobName>`
- **Тип:** имя blob-переменной
- **По умолчанию:** `\x00` (нулевой байт)
- **Описание:** Данные для заполнения фейковых сегментов. Blob повторяется функцией `pattern()` до нужного размера
- **Примеры:**
  - `pattern=0xDEADBEEF` — inline hex
  - `pattern=my_fake_pattern` — предзагруженный blob

#### `seqovl`

- **Формат:** `seqovl=N` (где N > 0)
- **Тип:** только число (маркеры **не поддерживаются** — в отличие от [[fakeddisorder]])
- **По умолчанию:** не задан (нет seqovl)
- **Описание:** Применяется **только к первому реальному сегменту** (пакет #2). К данным первого сегмента слева добавляется N байт `seqovl_pattern`, а TCP `th_seq` уменьшается на N. Сервер отбросит левую часть, DPI — может не отбросить
- **Примеры:**
  - `seqovl=5` — 5 байт фейка слева
  - `seqovl=13` — 13 байт фейка слева

#### `seqovl_pattern`

- **Формат:** `seqovl_pattern=<blobName>`
- **Тип:** имя blob-переменной
- **По умолчанию:** один байт `0x00`, повторяемый до длины `seqovl`
- **Описание:** Данные для заполнения seqovl-области. Blob повторяется функцией `pattern()` до нужного размера
- **Поведение с `optional`:** если `optional` задан и blob отсутствует — используется нулевой паттерн, seqovl не отменяется
- **Примеры:**
  - `seqovl_pattern=0x1603030000` — inline hex (маскировка под TLS)
  - `seqovl_pattern=my_pattern_blob` — предзагруженный blob

#### `blob`

- **Формат:** `blob=<blobName>`
- **Тип:** имя blob-переменной
- **По умолчанию:** не задан
- **Описание:** Заменить текущий payload/reasm на указанный blob и резать/слать его. Используется для отправки произвольных данных (фейковых payload, модифицированных ClientHello и т.д.)
- **Примеры:**
  - `blob=fake_default_tls` — стандартный TLS-фейк
  - `blob=0xDEADBEEF` — inline hex
  - `blob=my_custom_ch` — предзагруженный blob

#### `optional`

- **Формат:** `optional` (флаг, без значения)
- **Описание:** Мягкий режим:
  - Если задан `blob=...` и blob отсутствует => fakedsplit **ничего не делает** (тихий skip, без ошибок)
  - Если задан `seqovl_pattern=...` и blob отсутствует => используется нулевой паттерн (seqovl не отменяется)
- **Использование:** защита от ошибок при использовании blob, которые могут отсутствовать

#### `nodrop`

- **Формат:** `nodrop` (флаг, без значения)
- **Описание:** После успешной отправки сегментов **не выносить** `VERDICT_DROP` (вместо этого вернуть `VERDICT_PASS`). Это означает, что оригинальный пакет тоже будет отправлен (наряду с нарезанными сегментами и фейками)
- **Использование:** для отладки
- **Предупреждение:** в боевых профилях `nodrop` обычно нежелателен

#### `nofake1`

- **Формат:** `nofake1` (флаг, без значения)
- **Описание:** Не отправлять фейк 1-й части **до** реальной 1-й части (пакет #1)

#### `nofake2`

- **Формат:** `nofake2` (флаг, без значения)
- **Описание:** Не отправлять фейк 1-й части **после** реальной 1-й части (пакет #3)

#### `nofake3`

- **Формат:** `nofake3` (флаг, без значения)
- **Описание:** Не отправлять фейк 2-й части **до** реальной 2-й части (пакет #4)

#### `nofake4`

- **Формат:** `nofake4` (флаг, без значения)
- **Описание:** Не отправлять фейк 2-й части **после** реальной 2-й части (пакет #6)

---

### B) Standard direction

| Параметр | Значения | По умолчанию |
|:---------|:---------|:-------------|
| `dir` | `in`, `out`, `any` | `out` |

Фильтр по направлению пакета. `fakedsplit` по умолчанию работает только с исходящими (`out`).

- `dir=out` — только исходящие (от клиента к серверу)
- `dir=in` — только входящие (от сервера к клиенту)
- `dir=any` — оба направления

При первом вызове с указанным `dir` функция делает `direction_cutoff_opposite` — отсекает себя от противоположного направления.

---

### C) Standard payload

| Параметр | Значения | По умолчанию |
|:---------|:---------|:-------------|
| `payload` | список типов через запятую | `known` |

Фильтр по типу payload на уровне Lua. Это **дополнительный** фильтр к `--payload=...` на уровне профиля.

- `payload=known` — только распознанные протоколы (`http_req`, `tls_client_hello`, `quic_initial` и т.д.)
- `payload=all` — любой payload, включая `unknown`
- `payload=tls_client_hello,http_req` — конкретные типы
- `payload=~unknown` — инверсия: всё кроме unknown

**Важно:** лучше ставить `--payload=...` на уровне профиля (C-код, быстрее), а не полагаться только на Lua-фильтр.

---

### D) Standard fooling

Модификации L3/L4 заголовков. В `fakedsplit` применяются **только к фейкам** (opts_fake). К оригиналам из всего fooling идёт **только tcp_ts_up**.

| Параметр | Описание | Пример |
|:---------|:---------|:-------|
| `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` |

**Важно для fakedsplit:** `tcp_ts_up` — единственный параметр fooling, который применяется и к оригиналам. Все остальные — только к фейкам. Это значит, что `tcp_ack=-66000` безопасен — оригиналы будут иметь валидный ACK, а фейки — невалидный.

**Заметка про tcp_ts_up:** На Linux-серверах пакеты с инвалидным ACK стабильно отбрасываются **только если** TCP timestamp option идёт первой в заголовке. `tcp_ts_up` перемещает её в начало, обеспечивая корректную работу badseq-fooling. Поскольку `tcp_ts_up` безвреден (не портит данные, просто переупорядочивает опции), он применяется и к оригиналам.

---

### E) Standard ipid

| Параметр | Описание | По умолчанию |
|:---------|:---------|:-------------|
| `ip_id=seq` | Последовательные IP ID | `seq` |
| `ip_id=rnd` | Случайные IP ID | -- |
| `ip_id=zero` | Нулевые IP ID | -- |
| `ip_id=none` | Не менять IP ID | -- |
| `ip_id_conn` | Сквозная нумерация IP ID в рамках соединения (требует tracking) | -- |

`ip_id` применяется **и к фейкам, и к оригиналам** (оба набора опций содержат `ipid = desync.arg`).

---

### F) Standard reconstruct

| Параметр | Описание |
|:---------|:---------|
| `badsum` | Испортить L4 (TCP) checksum при реконструкции raw-пакета. Сервер отбросит такой пакет |

В `fakedsplit` `badsum` применяется **только к фейкам** (`opts_fake`). Оригиналы имеют пустой `reconstruct = {}`.

---

### G) Standard rawsend

| Параметр | Описание |
|:---------|:---------|
| `repeats=N` | Отправить каждый сегмент N раз (идентичные повторы) |
| `ifout=<iface>` | Интерфейс для отправки (по умолчанию определяется автоматически) |
| `fwmark=N` | Firewall mark (только Linux, nftables/iptables) |

**Важная деталь:** `repeats` применяется **только к фейкам**. Оригиналы используют `rawsend_opts_base`, который не включает `repeats`. `ifout` и `fwmark` применяются к обоим.

---

## Порядок отправки — подробно с seqovl

### Без seqovl

```
Payload "ABCDEFGHIJ" (10 байт), pos=4, pattern=0xFF

Пакет #1 (fake1):   seq=0  data=[FF FF FF]     len=3   opts_fake
Пакет #2 (real1):   seq=0  data=[A  B  C ]     len=3   opts_orig
Пакет #3 (fake1'):  seq=0  data=[FF FF FF]     len=3   opts_fake
Пакет #4 (fake2):   seq=3  data=[FF FF FF FF FF FF FF]  len=7  opts_fake
Пакет #5 (real2):   seq=3  data=[D  E  F  G  H  I  J]  len=7  opts_orig
Пакет #6 (fake2'):  seq=3  data=[FF FF FF FF FF FF FF]  len=7  opts_fake
```

### С seqovl=5

```
Payload "ABCDEFGHIJ" (10 байт), pos=4, pattern=0xFF, seqovl=5, seqovl_pattern=0x00

Пакет #1 (fake1):   seq=0   data=[FF FF FF]                  len=3   opts_fake
Пакет #2 (real1):   seq=-5  data=[00 00 00 00 00 A  B  C ]   len=8   opts_orig
Пакет #3 (fake1'):  seq=0   data=[FF FF FF]                  len=3   opts_fake
Пакет #4 (fake2):   seq=3   data=[FF FF FF FF FF FF FF]      len=7   opts_fake
Пакет #5 (real2):   seq=3   data=[D  E  F  G  H  I  J]      len=7   opts_orig
Пакет #6 (fake2'):  seq=3   data=[FF FF FF FF FF FF FF]      len=7   opts_fake

Сервер:
  Пакет #2: seq=-5, байты -5..-1 за window => отброшены; байты 0..2 = [A B C] => приняты
  Пакет #5: seq=3, байты 3..9 = [D E F G H I J] => приняты
  Итого: [A B C D E F G H I J] = полный payload
```

---

## Поведение при replay / reasm

Многопакетный запрос `nfqws2` придерживает, собирает в буфер `reasm_data` и перепроигрывает через desync-функции. `fakedsplit` использует штатную развилку из общего скелета desync-функций ([[жизненный цикл desync-функции]], стадия 6) без изменений: разрезает и отправляет **весь** собранный буфер вместе с фейками на первой части, а остальные части дропает. Если отправка сорвалась, флаг «реасм уже отправлен» не ставится и оставшиеся части проходят как есть.

Специфика функции здесь одна, зато существенная: фейковые сегменты строятся по размерам реальных частей **всего реасма**, а не отдельного пакета. Поэтому при многопакетном ClientHello фейки получаются крупными — ровно такими же, как реальные куски.

---

## Автосегментация по MSS

О размерах TCP-сегментов думать **не нужно**. Функция `rawsend_payload_segmented` из `zapret-lib.lua` автоматически:

1. Отслеживает MSS для каждого TCP-соединения
2. Если часть payload превышает MSS — дополнительно режет по MSS
3. Каждый под-сегмент отправляется с корректным TCP sequence

Это относится и к фейкам, и к оригиналам.

---

## Место в общем скелете

Тело `fakedsplit` построено по тому же шаблону, что и все остальные функции дурения: восемь стадий от отсева чужого транспорта до вердикта. Разобраны они один раз в [[жизненный цикл desync-функции]] — здесь только отклонения:

| Стадия общего скелета | Что делает `fakedsplit` |
|:----------------------|:----------------|
| 1. Отсев транспорта | только TCP; на не-TCP делает `instance_cutoff` (кроме связанного ICMP) |
| 2. Направление | `dir=out` по умолчанию, отключается от входящего |
| 3. Аргументы | обязательных нет; `optional` + отсутствующий `blob` → тихий выход |
| 4. Данные | штатная цепочка `blob → reasm → payload` |
| 5. Гварды | штатные `#data>0`, `direction_check`, `payload_check` (по умолчанию `known`) |
| 6. replay | штатная развилка: работа на первой части, дроп остальных |
| 7. **Своя техника** | одна позиция разреза (`resolve_pos`, не список), два реальных сегмента и до четырёх фейков между ними — этому посвящена вся заметка |
| 8. Вердикт | `VERDICT_DROP` после успешной отправки, `VERDICT_PASS` при `nodrop` или сбое `rawsend` |

Отдельно стоит запомнить, как `fakedsplit` обращается с опциями. В отличие от [[multisplit]], он собирает **два разных набора**: фейкам достаются fooling и reconstruct в полном объёме (фейк обязан быть отвергнут сервером), а реальным частям — только `tcp_ts_up` и политика `ip_id`. Повторы `repeats` тоже уходят лишь на фейки. Общий разбор наборов опций — в [[жизненный цикл desync-функции]].

---

## Псевдокод алгоритма

Тело функции целиком, включая общие для всех техник стадии — они пронумерованы так же, как в [[жизненный цикл desync-функции]]:

```lua
function fakedsplit(ctx, desync)
    -- 1. Проверка: только TCP
    if not desync.dis.tcp then
        if not desync.dis.icmp then instance_cutoff_shim() end
        return
    end

    -- 2. Cutoff противоположного направления
    direction_cutoff_opposite(ctx, desync)

    -- 3. Проверка optional blob
    if optional and blob specified and blob not exists then
        DLOG("blob not found. skipped")
        return
    end

    -- 4. Выбор данных
    data = blob_or_def(blob) or reasm_data or dis.payload

    -- 5. Проверки: данные не пусты, направление OK, payload OK
    if #data > 0 and direction_check() and payload_check() then

        -- 6. Только первый replay
        if replay_first() then

            -- 7. Разрешение ОДНОГО маркера
            pos = resolve_pos(data, l7payload, pos_arg or "2")

            if pos == nil then
                DLOG("cannot resolve pos")
            elseif pos == 1 then
                DLOG("split pos resolved to 0. cannot split.")
            else
                -- 8. Создание двух наборов опций
                opts_orig = {rawsend=base, reconstruct={}, ipfrag={},
                             ipid=arg, fooling={tcp_ts_up=arg.tcp_ts_up}}
                opts_fake = {rawsend=full, reconstruct=reconstruct_opts,
                             ipfrag={}, ipid=arg, fooling=arg}

                -- 9. Паттерн для фейков
                fakepat = arg.pattern blob or "\x00"

                -- 10. ФЕЙК 1-й части
                fake = pattern(fakepat, 1, pos-1)
                if not nofake1 then
                    rawsend_payload_segmented(fake, 0, opts_fake)
                end

                -- 11. РЕАЛЬНАЯ 1-я часть (+seqovl)
                part = data:sub(1, pos-1)
                seqovl = 0
                if arg.seqovl and tonumber(arg.seqovl) > 0 then
                    seqovl = tonumber(arg.seqovl)
                    pat = "\x00"
                    if arg.seqovl_pattern then
                        if optional and blob not exists then
                            pat = "\x00"  -- fallback
                        else
                            pat = blob(seqovl_pattern)
                        end
                    end
                    part = pattern(pat, 1, seqovl) .. part
                end
                rawsend_payload_segmented(part, -seqovl, opts_orig)

                -- 12. ФЕЙК 1-й части (повтор)
                if not nofake2 then
                    rawsend_payload_segmented(fake, 0, opts_fake)
                end

                -- 13. ФЕЙК 2-й части
                fake = pattern(fakepat, pos, #data-pos+1)
                if not nofake3 then
                    rawsend_payload_segmented(fake, pos-1, opts_fake)
                end

                -- 14. РЕАЛЬНАЯ 2-я часть
                part = data:sub(pos)
                rawsend_payload_segmented(part, pos-1, opts_orig)

                -- 15. ФЕЙК 2-й части (повтор)
                if not nofake4 then
                    rawsend_payload_segmented(fake, pos-1, opts_fake)
                end

                -- 16. Пометить как отправленное
                replay_drop_set()
                return nodrop and VERDICT_PASS or VERDICT_DROP
            end
        else
            -- 17. Не первый replay
            DLOG("not acting on further replay pieces")
        end

        -- 18. Drop replayed packets если ранее успешно отправлено
        if replay_drop() then
            return nodrop and VERDICT_PASS or VERDICT_DROP
        end
    end
end
```

---

## Нюансы и подводные камни

### 1. Работает только с TCP

Если текущий пакет не TCP (UDP, ICMP и т.д.), `fakedsplit` делает `instance_cutoff_shim` — отключает себя для этого потока навсегда. Исключение: ICMP-пакеты (связанные с TCP) не вызывают cutoff.

### 2. Только ОДНА позиция разреза

В отличие от [[multisplit]], `fakedsplit` принимает **один** маркер, не список. `pos=midsld,endhost` не будет работать как два разреза — строка целиком передастся в `resolve_pos`, который не умеет парсить запятые. Если нужно несколько точек разреза с фейками — используйте цепочку инстансов или [[fakeddisorder]].

### 3. Позиция 1 не работает

Если `resolve_pos` возвращает Lua-позицию 1, fakedsplit логирует "split pos resolved to 0. cannot split." и ничего не делает. Это соответствует маркеру `0` (смещения в командной строке считаются с нуля), а не `pos=1`.

### 4. Fooling ОБЯЗАТЕЛЕН для фейков

Без fooling фейки будут приняты сервером как валидные данные, что сломает TCP-поток. Всегда указывайте хотя бы один метод fooling:

```bash
# НЕПРАВИЛЬНО — фейки будут приняты сервером!
--lua-desync=fakedsplit:pos=midsld

# ПРАВИЛЬНО — фейки отброшены по невалидному ACK
--lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up
```

### 5. tcp_ts_up рекомендуется вместе с tcp_ack/tcp_seq

На Linux-серверах `tcp_ack=-66000` надёжно отбрасывает пакеты только если TCP timestamp option идёт первой. `tcp_ts_up` обеспечивает это. Всегда комбинируйте:

```bash
:tcp_ack=-66000:tcp_ts_up
```

### 6. repeats применяются ТОЛЬКО к фейкам

Если задать `repeats=5`, каждый фейк отправится 5 раз, а каждый оригинал — 1 раз. Это сделано специально: больше фейков => больше шума для DPI, но данные не дублируются.

### 7. ipfrag НЕ используется

В отличие от [[multisplit]] и [[multidisorder]], `fakedsplit` не поддерживает IP-фрагментацию. Оба набора опций имеют пустой `ipfrag = {}`. Если нужна IP-фрагментация поверх фейков — это не поддерживается напрямую.

### 8. badsum идёт только на фейки

`badsum` — часть `reconstruct`, который применяется только к фейкам. Оригиналы всегда имеют валидный checksum. Это безопасно и является ещё одним методом fooling.

### 9. nodrop создаёт сильное дублирование

С `nodrop` fakedsplit отправляет до 6 сегментов (фейки + оригиналы) И пропускает оригинальный пакет. Сервер получит данные как минимум дважды. Используйте `nodrop` только для отладки.

### 10. Порядок инстансов важен

Если перед `fakedsplit` стоит `pktmod` с модификацией — pktmod изменит payload, и fakedsplit порежет уже изменённые данные. Если после fakedsplit стоит ещё один инстанс — он увидит VERDICT_DROP и не получит оригинальный payload.

### 11. Неразрешённый маркер != ошибка

Если `resolve_pos` не смог разрешить маркер (например, `midsld` для `unknown` payload), fakedsplit логирует "cannot resolve pos" и **ничего не делает** — ни фейков, ни разреза. Оригинальный пакет проходит как есть.

---

## Отличия от других функций сегментации

| Аспект | `multisplit` | `multidisorder` | `fakedsplit` | `fakeddisorder` |
|:-------|:-------------|:----------------|:-------------|:----------------|
| Количество позиций | Список (любое кол-во) | Список (любое кол-во) | **Одна** | **Одна** |
| Резолвер позиций | `resolve_multi_pos` | `resolve_multi_pos` | **`resolve_pos`** | **`resolve_pos`** |
| Порядок отправки | Прямой (1->2->3) | Обратный (3->2->1) | Прямой (с фейками) | Обратный (с фейками) |
| Фейковые сегменты | **Нет** | **Нет** | Да (до 4 шт.) | Да (до 4 шт.) |
| Пакетов на выходе | N+1 (N позиций) | N+1 (N позиций) | До 6 (2 реальных + 4 фейка) | До 6 (2 реальных + 4 фейка) |
| seqovl тип | Только число | **Маркер** | Только число | **Маркер** |
| seqovl к какому сегменту | 1-й | 2-й (предпоследний) | 1-й реальный | 2-й реальный |
| Fooling к | Всем сегментам | Всем сегментам | **Только к фейкам** | **Только к фейкам** |
| reconstruct к | Всем сегментам | Всем сегментам | **Только к фейкам** | **Только к фейкам** |
| repeats к | Всем сегментам | Всем сегментам | **Только к фейкам** | **Только к фейкам** |
| ipfrag | Да | Да | **Нет** | **Нет** |
| ipid к | Всем сегментам | Всем сегментам | И фейкам, и оригиналам | И фейкам, и оригиналам |
| tcp_ts_up к оригиналам | Да (как часть fooling) | Да (как часть fooling) | **Да (единственный fooling)** | **Да (единственный fooling)** |

---

## Миграция с nfqws1

### Соответствие параметров

| nfqws1 | nfqws2 |
|:-------|:-------|
| `--dpi-desync=fakedsplit` | `--lua-desync=fakedsplit` |
| `--dpi-desync-split-pos=midsld` | `:pos=midsld` |
| `--dpi-desync-split-pos=method+2` | `:pos=method+2` |
| `--dpi-desync-fooling=badseq` | `:tcp_ack=-66000:tcp_ts_up` (или другой fooling) |
| `--dpi-desync-badseq-increment=0` | `:tcp_seq=0` (если нужен нулевой seq инкремент) |
| `--dpi-desync-split-seqovl=5` | `:seqovl=5` |
| `--dpi-desync-split-seqovl-pattern=0x1603030000` | `:seqovl_pattern=0x1603030000` |
| `--dpi-desync-any-protocol` | Не нужно; или `payload=all` в инстансе |

### Пример полной миграции

```bash
# nfqws1:
nfqws --dpi-desync=fakedsplit \
  --dpi-desync-fooling=badseq \
  --dpi-desync-badseq-increment=0 \
  --dpi-desync-split-pos=method+2

# nfqws2 (эквивалент):
nfqws2 \
  --payload=http_req \
    --lua-desync=fakedsplit:pos=method+2:tcp_ack=-66000:tcp_ts_up
```

```bash
# nfqws1:
nfqws --dpi-desync=fakedsplit \
  --dpi-desync-fooling=md5sig \
  --dpi-desync-split-pos=midsld \
  --dpi-desync-split-seqovl=5 \
  --dpi-desync-split-seqovl-pattern=0x1603030000

# nfqws2 (эквивалент):
nfqws2 \
  --payload=tls_client_hello \
    --lua-desync=fakedsplit:pos=midsld:tcp_md5:tcp_ts_up:seqovl=5:seqovl_pattern=0x1603030000
```

```bash
# nfqws1 с несколькими protocol:
nfqws --dpi-desync=fakedsplit \
  --dpi-desync-fooling=badseq \
  --dpi-desync-split-pos=2

# nfqws2 (разделяем по payload):
nfqws2 \
  --payload=tls_client_hello,http_req \
    --lua-desync=fakedsplit:pos=2:tcp_ack=-66000:tcp_ts_up
```

---

## Практические примеры

### 1. Минимальный (дефолт: pos=2, fooling=badseq)

```bash
--lua-desync=fakedsplit:tcp_ack=-66000:tcp_ts_up
```

Разрезает payload после 2-го байта => 2 реальных + 4 фейка = 6 пакетов. Фейки отбрасываются по невалидному ACK.

### 2. TLS: разрез посередине SNI

```bash
--payload=tls_client_hello --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up
```

SNI разрезан пополам. В каждом фейке — нули вместо реальных данных. DPI не может собрать hostname ни из одного отдельного сегмента.

### 3. HTTP: разрез после метода

```bash
--payload=http_req --lua-desync=fakedsplit:pos=method+2:tcp_ack=-66000:tcp_ts_up
```

Для `GET /path...` разрежет после `GE`. DPI видит 6 сегментов — 3 "ретрансмиссии" для `GE*` и 3 для `T /path...`.

### 4. С seqovl (двойная защита)

```bash
--payload=tls_client_hello \
  --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up:seqovl=5:seqovl_pattern=0x1603030000
```

Фейки + seqovl в первом реальном сегменте. Даже если DPI отбросит фейки, seqovl-данные (выглядящие как начало TLS record) могут его сбить.

### 5. С кастомным паттерном для фейков

```bash
--blob=fakepat:0x474554202F HTTP --payload=http_req \
  --lua-desync=fakedsplit:pos=host:tcp_ack=-66000:tcp_ts_up:pattern=fakepat
```

Фейки заполнены данными, похожими на HTTP-запрос. DPI ещё больше запутывается.

### 6. С badsum вместо badseq

```bash
--payload=tls_client_hello --lua-desync=fakedsplit:pos=midsld:badsum:tcp_ts_up
```

Фейки отбрасываются сервером из-за невалидного TCP checksum. Не все DPI проверяют checksum, поэтому для многих этого достаточно.

### 7. С TCP MD5 signature

```bash
--payload=tls_client_hello --lua-desync=fakedsplit:pos=midsld:tcp_md5:tcp_ts_up
```

Фейки содержат TCP MD5 option. Сервер без настроенного MD5 отбросит такие пакеты.

### 8. Без "задних" фейков (оптимизация трафика)

```bash
--payload=tls_client_hello \
  --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up:nofake2:nofake4
```

Только 4 пакета вместо 6. Фейки идут только **до** реальных частей. Для многих DPI этого достаточно.

### 9. С повторами фейков (максимальный шум)

```bash
--payload=tls_client_hello \
  --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up:repeats=3
```

Каждый фейк отправляется 3 раза => 4*3 + 2 = 14 пакетов. Оригиналы — по 1 разу. Максимальное замусоривание потока для DPI.

### 10. С TTL-fooling (вместо badseq)

```bash
--payload=tls_client_hello \
  --lua-desync=fakedsplit:pos=midsld:ip_ttl=4:tcp_ts_up
```

Фейки имеют TTL=4 — не доживут до сервера, но DPI на пути их увидит. Менее надёжно, чем badseq (зависит от числа хопов).

### 11. Цепочка: fake + fakedsplit

```bash
--payload=tls_client_hello \
  --lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,rndsni,dupsid \
  --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up
```

Сначала отправляется полноценный TLS-фейк (поддельный ClientHello), затем реальный payload нарезается с замешиванием фейков. Двойной удар по DPI.

### 12. Комбинация с wssize и syndata

```bash
--lua-desync=wssize:wsize=1:scale=6 \
--lua-desync=syndata \
--payload=tls_client_hello \
  --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up:seqovl=5
```

Window size manipulation + SYN data + fakedsplit с seqovl. Многоуровневая защита.

### 13. Защита от отсутствующего blob

```bash
--lua-desync=fakedsplit:blob=maybe_missing:optional:pos=midsld:tcp_ack=-66000:tcp_ts_up
```

Если blob не существует — тихий пропуск, без ошибок и без VERDICT_DROP.

### 14. Отладка: не блокировать оригинал

```bash
--payload=http_req --lua-desync=fakedsplit:pos=method+2:tcp_ack=-66000:tcp_ts_up:nodrop
```

Отправляет нарезанные сегменты с фейками И пропускает оригинальный пакет (для экспериментов).

### 15. Боевой пример для YouTube (TLS)

```bash
--filter-tcp=443 --hostlist=youtube.txt \
  --payload=tls_client_hello \
    --lua-desync=fakedsplit:pos=midsld:tcp_ack=-66000:tcp_ts_up:seqovl=5:seqovl_pattern=0x1603030000
```

Разрез SNI пополам + seqovl маскировка + badseq fooling. Оптимальная комбинация для TLS-трафика.

### 16. Боевой пример для HTTP

```bash
--filter-tcp=80 --hostlist=blocked.txt \
  --payload=http_req \
    --lua-desync=fakedsplit:pos=host:tcp_ack=-66000:tcp_ts_up
```

Разрез перед hostname в HTTP Host header. Ни один сегмент не содержит полный `Host: blocked.example.com`.

---

> **Источники:** `lua/zapret-antidpi.lua:803-906`, `lua/zapret-lib.lua:385-422`, `docs/manual.md:4122-4164` из репозитория zapret2.
