Zapret: what's new

В tpws реализованы фильтры протоколов для disorder и oob.
Параметр oob претерпел несовместимое изменение. Теперь наравне с disorder он берет название протокола http или tls. Если без параметра - применяется дурение ко всем протоколам. Если с параметром - только к этому протоколу.
Может быть несколько --disorder или --oob. Например, можно сказать ему сделать oob для tls и http, но не делать для остальных, при условии что задано --split-any-protocol.
Байт OOB перенесен в параметр --oob-data. Это нужно, потому что в tpws стали появляться стратегии, которые нужны для одних протоколов, но могут ломать другие.
Для http есть отдельный split --split-http-req. Он имеет приоритет над --split-pos.
Если это не http, то применяется --split-pos. Получается, можно двумя этими параметрами задать разный сплит для http и tls.
Но вот disorder может сломать http на ТСПУ. В скриптах запуска можно было этот вопрос решить как с nfqws - сделать несколько параметров для http,https,http6,https6.
Но tpws еще ценен наличием режима socks, а там такое сделать не выйдет, потому что в прогах нет 4 поля socks для разных вариантов. Потому принято решение идти по пути обьединения стратегий в 1 процесс.
Кстати, это еще один пример, что вот так просто взять копипастнуть как на картинке может не получиться. Если вы захотите пойти путем tpws, то там только 1 поле, а стратегии выдал blockcheck две разные. И все, вы тут встряли, если вы - копипастер. А на самом деле это сделано потому, что все можно запихать в 1 стратегию, если их обьеденить, но это не для копипастеров. И, конечно, чтобы не ломать достоинство socks.
tpws в текущих реалиях в России работает, но ограниченно.
Как правило он может пробить http, а https только на tls 1.3.
Не поддерживающие tls 1.3 заблокированные сайты пробить не получится.

Худой, но как-то работающий способ пробить TLS1.2 на tpws. Не везде, но много где. Не особо качественно. Но лучше, чем ничего.

–mss устанавливает опцию сокета TCP_MAXSEG. Клиент выдает это значение в tcp опциях SYN пакета.
Сервер в ответ в SYN,ACK выдает свой MSS. На практике сервера обычно снижают размеры отсылаемых ими пакетов, но они все равно не вписываются в низкий MSS, указанный клиентом. Обычно чем больше указал клиент, тем больше шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет, это может обмануть DPI, секущий ответ сервера.
Схема может значительно снизить скорость и сработать не на всех сайтах.
Несовместимо с фильтром по hostlist. Невозможен фильтр по версии TLS.
Взамен имеется фильтр по портам --mss-pf. --mss-pf=443 применяет дурение только к https.
Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже.
Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в
3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который может привести к реакции DPI.
Использовать только когда нет ничего лучше или для отдельных ресурсов.
Работает только на linux, не работает на BSD и MacOS.

В tpws ликвидировано узкое место, связанное с ресолвером хостов.
У socks proxy есть режим переадресации по IP адресу и по хосту.
В curl за выбор режима отвечают параметр --socks5 или --socks5-hostname. Можно использовать параметр --proxy socks5://… и --proxy socks5h://… . socks5h - это как раз ресолвинг через прокси.

tpws основан на однопоточном обслуживании всех соединений с использованием неблокирующих сокетов и событийной модели. Тормоза в каком-то соединении не вешают остальные соединения. Но раньше ресолвинг ломал эту модель, поскольку использовался блокирующий вызов getaddrinfo. На время ресолвинга все замирало.

Сейчас это больше не так. Задача по ресолвингу решается в отдельных потоках, организованных в виде thread pool. Есть очередь запросов, а потоки их по мере возможности разгребают. На время ресолвинга соединение ставится на паузу, не прерывая процессинг всего остального.

Количество потоков ресолвера выбирается по умолчанию как 5+max_conn/50. По умолчанию max_conn=512, следовательно потоков 15. Можно переопределить в параметре --resolver-threads.

Да, можно было использовать какую-то отдельную библиотеку для асинхронных ресолвингов, ведь libc в общем случае такой возможности не имеет. Имеет только glibc, а musl и другие - нет. Но это зависимости, это тяжесть процесса, которую хочется избежать.

Помимо прямого назначения, это нововведение несет в себе и другую цель. Использование tpws в socks режиме с удаленным ресолвингом хостов дает tpws возможность узнать hostname еще до подключения к серверу. Следовательно, задействуется механизм, ограничивающий дурение по MSS через hostlist. В любом другом режиме MSS будет применяться неограниченно ко всем соединениям.

Как задействовать socks в броузерах.
В хромиум подобных вызвать chrome так : chrome.exe --proxy-server=“socks5://localhost:1111” . Они сразу начинают задействовать режим remote_dns.
В firefox можно глобально задать в about:flags параметр network.proxy.socks_remote_dns=true. А можно использовать расширение foxyproxy. Оно позволяет оперативно переключать прокси, и можно задать remote_dns для каждого прокси отдельно.

WSL 1. Подсистема linux на win10/11 и windows server.
Эмуляция вызовов ядра linux, позволяющая запускать бинарики linux.
Но, естественно, в реализации есть кривизна.

Проверял на windows server 2022. Оказалось глючат linux pipes.
Делаешь splice в pipe. Возвращает, что записал 8192 байт.
Делаешь splice из pipe в сокет. B хрен вам. EAGAIN. Как будто ничего нет в этом пайпе.
Делаешь read из пайпа - тоже самое. То есть там действительно пусто.
Проблема не в сокете. Если в него слать send-ом, то ошибки нет, уходит.
Получается суешь в пайп, и это куда-то пропадает неизвестно куда.
Логика неблокирующих сокетов приводит к зацикливанию процесса, сьедая целое ядро.

Сколько ни тестировал на linux, такого нет, а в винде воспроизводится на раз два.

Лечение - параметр --nosplice. Обход глюка винды

Исправлен целый ряд проблем, все же имевшихся в схеме postnat.
Десинхронизация на первый пакет (syndata на tcp или первый пакет udp, quic, например) несет в себе проблему. Если дропать в очереди первый пакет, то ломается запись в conntrack. Его нельзя дропать.
Потому было сделано особое уродование первого оригинального пакета, чтобы его пропускать в очереди.
TTL использовать нельзя, поскольку linux сечет expired icmp и ресетает сокет.
Использованы следующие схемы :

ipv4 - портим L3 чексумму ipv4 хедера. с порченой чексуммой пакет будет отброшен первым же роутером
tcp - в SYN пакете сбрасываем все флаги и этим самым так же портим чексумму L4
udp - в первом пакете обрезаем все данные после udp хедера, делаем длину в udp хедере нулевой (минимум 8 требуется - длина самого хедера), портим чексумму L4

эти меры призваны достичь результата, даже если вдруг сетевой адаптер на все делает чексум оффлоад
главная цель - чтобы этот пакет никем по возможности не был воспринят как что-то значимое. ни DPI, ни сервером. но в то же время не испортилась бы запись в коннтрак

Для дурения произвольных протоколов в nfqws добавлен параметр --dpi-desync-start.

Он полностью аналогичен --dpi-desync-cutoff, но работает как начальный ограничитель. cutoff - конечный ограничитель.
Таким образом дублируется функционал connbytes FROM:TO на уровне nfqws. Можно вырезать по номеру пакета (n), смещению позиции данных (s), а так же отсутствующий в connbytes режим - по номеру пакета данных (d). d от n отличается только тем, что считаются пакеты с непустым data payload.
Этот фильтр помогает решить вопрос с отсутствующим connbytes на BSD системах или на прошивочках linux с покоцаным ядром, где нет матча connbytes.
При наличии connbytes лучше это делать средствами iptables/nftables. Тогда не будет лишних редиректов user mode, скорость будет выше в разы.
Если надо ограничить дурение в d режиме, игнорируя непонятное количество пустых ACK, то делаем ограничитель connbytes на максимум возможных пакетов, где нам надо что-то поймать, дальше уточняющий ограничитель в d режиме на nfqws.

В tpws уже реализована пара похожих параметров --tamper-start, --tamper-cutoff

В nfqws теперь обязателен параметр --qnum. Раньше был номер очереди по умолчанию 0.
Сделано во избежание неверного использования, вызванного непониманием как оно работает.
В iptables, кстати, NFQUEUE тоже имеет по умолчанию номер очереди 0. То есть если раньше кто-то писал iptables без queue-num, а nfqws запускал без qnum, то это работало, а теперь перестанет. Вернуть этот вариант можно через nfqws --qnum 0

В nfqws сделана система задержки пакетов.
Начиная с chrome 124 по умолчанию включена пост-квантовая криптография kyber. Это раздувает TLS ClientHello до 2 пакетов, QUIC initial до 2 или 3 пакетов. Может быть и больше при низком MTU.
Ранее nfqws умел реассемблировать TLS ClientHello, но проводил десинхронизацию на тот сегмент TCP, где появилось SNI и все последующие. Допустим, имеется 5 пакетов, в 3-м из которых SNI. Получается, мы имеем : tls1,tls2,fake,tls3,fake,tls4,fake,tls5. Не слишком корректное поведение. QUIC же вообще никак не реассемблировался.
Теперь введена система задержки пакетов. Мы получаем tls1…tls5, но в сеть не шлем, а только запоминаем. По приходу последнего tls5 выполняется десинхронизация tls1 на основании полностью собранного запроса. Выходит так : fake,tls1,tls2,tls3,tls4,tls5. Что куда более корректно, ведь суть фейка - вынудить DPI отстать от запроса. Но как он от него отстанет в предыдущем варианте, если он сначала видит tls1. Он начинает реассемблировать вплоть до tls5. И получает испорченный блок данных где-то посередине. Такое тоже обычно срабатывает для обхода, но все же это не достигает изначальной цели fake.
Для QUIC производится аналогичная процедура, только с дешифровкой каждого куска, конкатенацией расшифрованных данных до тех пор, пока из них не соберется полный ClientHello.
Любая ошибка при сборке вызывает немедленную отмену реассемблирования, отсылку задержанных пакетов и отмену десинхронизации.

Реализован nfqws для windows - winws.
Это фактически замена GoodbyeDPI с up-to-date функциями из nfqws.
Работает практически все.
Из ограничений : нет ipset, не поддерживается проходящий трафик (расшаривание соединения)
Поддерживается blockcheck, но он требует установки cygwin.
Сам winws установки cygwin не требует.

Читайте docs/windows.txt, docs/quick_start_windows.txt

Это дебют, так что welcome тестировать.

Создан bundle для ускоренного и упрощенного запуска blockcheck под windows. Его достаточно для полноценного развертывания winws.

Адаптирована инструкция из основного репозитория docs/quick_start_windows.txt

Сделан запуск в виде windows служб.
См service_*.cmd
Можно запускать и через планировщик, и как службы. Как вам больше нравится.

Устранена гонка при одновременном запуске нескольких инстансов winws.
Она связана с CreateService/StartService драйвера windivert.sys
Это проблема не связана напрямую с winws, а с windivert.dll

Устранено возможное падение при остановке сервиса

Поделюсь своим опытом изучения windows 10 arm64 под qemu-aarch64 на платформе x86.

Известно, что эта платформа имеет встроенный эмулятор кода x86. Бинарная трансляция. Примерно так, как это сделано в android x86 для arm - там используются libhoodini.
Целью было выяснить возможно ли вообще использовать winws на базе x86_64 cygwin с неподписанным драйвером windivert для arm в режиме ядра testsigning.

Попытка установить win11 закончилась провалом. Все мои попытки заканчивались ошибкой установщика уже на этапе после наката install.wim на HDD. Тоже самое получалось и если install.wim накатить вручную через dism, а bcd создать вручную

win10 встала. Но первое, что я заметил, были совершенно невообразимые тупняки.
Конечно, тормоза ожидались, но там все просто ложилось почти намертво.
Как выяснилось, бинарный транслятор кода x86 под qemu-aarch64 при попытке выполнить любой бинарик x86 зацикливается с отьеданием 100% одного ядра.
Неважно что это - хоть простейший cmd. Можно ждать хоть часами - ничего не меняется.
Так что миссия на этом этапе провалилась. Не работает x86 код вообще.

А встроенного кода x86 там хватает. На удивление microsoft сильно схалявил. Целый ряд компонент windows не был перенесен на arm, а выполняется как x86 !!
Начиная с onedrive, который автоматически запускается и добавляет тупняка, и заканчивая powershell, без которого , например, даже нельзя снести все эти ненужные магазинные приложения.

По мере чистки от левака с убиранием из автозапуска всего x86 система стала гораздо более отзывчива и даже почти юзабельна.

Так что пока тестировать не на чем. Требуется реальная подходящая arm железяка

Проверена работа winws на windows 11 arm64 с неподписанным драйвером windivert в режиме testsigning.
Оно работает. Для быстрого наката arm64 версии сделан батник в bundle : arm64/install_arm64.cmd
Все, кроме драйвера, работает в x64 эмуляции.
Windows 10 arm64 не поддерживается по причине отсутствия x64 эмуляции. Поддерживается только x86.

Пару недель назад прошла такая тема, что в ОАЭ и СаудиАрабиа перестал работать GoodByeDPI.
Просто начисто. Блокчек от winws так же показал безуспешность всех вариантов.
Думали все очень сложно. Но оказалась банальщина. Они ищут в отдельных пакетах stateless сигнатуру SNI и смотрят там хост.
Помогает сплит на SNI. Но , увы, такой функции нет в zapret. Недавно Валдик дописал это для GDPI.

Сейчас догоняет и zapret. Но там все несколько сложнее. Потому что поддерживаются многосегментные запросы.
В tpws добавлен параметр --split-tls. Там все довольно просто, поскольку мы не имеем дело с отдельными пакетами. Все равно сколько пакетов в итоге будет.
В nfqws добавлены параметры --dpi-desync-split-http-req и --dpi-desync-split-tls.
И в nfqws, и в tpws для tls допустимы значения sni и sniext. sni - значит резать после 1 символа хоста. sniext - резать между байтами 2-байтной длины SNI extension.
В nfqws реализация оказалась сложнее. SNI может попасть на любой пакет в серии. Поэтому сплит-десинхронизация применяется только к тому пакету, в котором оказалась искомая позиция относительно начала всего многопакетного сообщения. Это касается как явно заданной позиции в байтах, так и автоопределения через split-tls. fake и многие другие опции идут при этом только на первый пакет серии.
Это все надо, чтобы в ОАЭ без отключения кибера сразу же заработала обманка на chrome.
GDPI пока что требует отключения кибер.

В tpws добавлена поддержка --tlsrec=sniext.
tlsrec может сочетаться со split-tls. В этом случае они адаптируются , и вычисляется корректная позиция, чтобы сплит попал куда надо, учитывая дописывание дополнительного заголовка TLS record.

В блокчек добавлены новые тесты для описанного функционала.
Сделан кэш mdig.
Изначально curl запускался с именем домена. Он сам его и ресолвил. Но оказывается, что при использования прокси опции -4 и -6 не могут корректно рулить через какую версию ip пойдет запрос. А прокси нужен для tpws. На некоторых платформах прозрачный режим не работает для локального хоста, либо его сложно автоматически задействовать.
Потому curl теперь гоняется с --connect-to , а хост ресолвит mdig. Ранее при каждом запросе запускался mdig. Теперь он запускается 1 раз на хост и ip версию, а результат запоминается в переменных shell. Запоминаются все ответы, и каждый раз выбирается случайный. Точно так же, как это делает стандартная система DNS

github внезапно отключил gzip compression. сломались скрипты ipset/get_reestr*.sh
исправлено
использовать curl --compressed нельзя, потому что на кастрированных системах curl без zlib. потому приходится эту логику реализовывать самому через шелл

Добавлена важная функция в winws.
В --ssid-filter можно через запятую задать неограниченное количество имен wifi сетей (SSID). Если задана хотя бы одна сеть, то winws включается только, если подключен указанный SSID. Если SSID исчезает, winws отключается. Если SSID появляется снова, winws включается. Это нужно, чтобы можно было применять раздельное дурение к каждой отдельной wifi сети.
Названия сетей должны быть написаны в том регистре, в котором их видит система. Сравнение идет с учетом регистра !
При этом нет никаких проверок куда реально идет трафик. Если одновременно подключен, допустим, ethernet, и трафик идет туда, то дурение включается и выключается просто по факту наличия wifi сети, на которую трафик может и не идти. И это может сломать дурение на ethernet. Поэтому полезно так же будет добавить фильтр --wf-iface на индекс интерфейса wifi адаптера, чтобы не трогать другой трафик.

Зачем это надо. Представьте себе, что вы настроили winws на ноуте чайника, который ничего не понимает, никуда не полезет и ничего не будет ни запускать, ни менять. Можно настроить и сделать сервис. Окей, чайник переехал и подключился к другому wifi. Стратегия не работает и ломает сайты. Что делать ? Ограничить дурение только на те сети, в которых вы знаете какая стратегия работает. Если таких несколько, то можно создать несколько инстансов winws с разными стратегиями и разными --ssid-fllter.
Таким образом чайник ничего не делает, и у него либо обходится блокировка, либо хотя бы ничего не ломается.

В blockcheck добавлены тесты открытости порта 80,443 (требуется ncat или netcat openbsd, бизибокс netcat не поддерживается !) и тесты блокировки по IP на DPI.

С портами все понятно. Если нет коннекта, то это сразу ВСЕ.
Домен может ресолвиться в несколько IP. Может не быть конекта на отдельных IP, если какие-то IP зарублены полностью.

Бывает так же и частичный IP блок. Конект идет, но на любые запросы возвращается reset или только на определенные протоколы типа http, tls, вне зависимости от домена.
Суть тестов блокировки по IP - дернуть заблокированный домен на предположительно незаблокированном ip (ip iana.org по умолчанию) и незаблокированный домен (iana.org) на заблокированном IP.
Дополнительно тестируется сам неблокированный домен (iana.org), чтобы быть точно уверенным, что в вашей экзотической стране не зарубили даже его.
Интерпретация результата целиком на пользователе и требует понимания.
Логика примерно такая. Если блок идет только на DPI по домену, то блокированный домен будет давать reset, timeout или redirect на любом IP.
Неблокированный домен на блокированном IP будет давать или available для http (на самом деле http code 409 или что-то такое реально вернет сервер), или ошибка при подключения по TLS сразу без задержек (что-то вроде handshake error).
Эта ситуация говорит об отсутствии блока по IP.
Если reset, timeout, redirect идут на неблокированном домене на блокированном IP, а блокированный домен на неблокированном IP выдает available или TLS error сразу без задержек, значит вероятно имеет место блок только по IP.
Если reset, timeout, redirect идут в обоих тестах, то может иметься блок как по IP, так и по домену.
Тест на блокированные IP проводится на каждый IP блокированного домена, если их несколько, а на неблокированный IP - только 1 раз на любой из IP неблокированного домена.
Собственно, это то, что я часто прошу сделать руками в случае непоняток. Сейчас это автоматизировано, и по логу блокчека можно понять больше.
Если действительно есть блок по IP, значит вероятно все последующие тесты будут безуспешны.
Однако, бывают ситуации, когда и частичный IP блок пробивается.
Например, в СаудиАрабиа оказалось, что добавление destopt хедера в ipv6 запросе пробивает блокировку. DPI не может следовать дополнительным ipv6 хедерам, не воспринимает пакет как tcp и пропускает его.
В этом и суть частичного блока. Блок на IP только определенных протоколов транспортного и прикладного уровня. Если DPI не может опознать протокол, то блокировки нет.

Полезные переменные для blockcheck
CURL_MAX_TIME=sec - сколько секунд до таймаута curl запроса. по умолчанию 2
CURL_MAX_TIME_QUIC=sec - отдельно для quic. по умолчанию совпадает с предыдущим
CURL_CMD=1 - показывать строку запуска curl каждый раз
CURL_VERBOSE=1 - опция -v для curl. в добавок автоматически CURL_CMD=1
SKIP_TPWS=1 - отказаться от TPWS тестов
SKIP_TPWS=0 - не отказываться от TPWS тестов, когда по умолчанию предусмотрен отказ
SKIP_PKTWS=1 - отказаться от nfqws/dvtws/winws тестов
UNBLOCKED_DOM - домен, используемый для ip block тестов. по умолчанию iana.org
DOMAINS=“dom1 dom2 … domN” - какие домены тестировать. по умолчанию rutracker.org

Переменные используются так :
CURL_MAX_TIME=1 SKIP_TPWS=1 CURL_CMD=1 /opt/zapret/blockcheck.sh

ПРИМЕРЫ БЛОКИРОВКИ ТОЛЬКО ПО ДОМЕНУ БЕЗ БЛОКА ПО IP

> testing iana.org on it's original ip
!!!!! AVAILABLE !!!!!
> testing rutracker.org on 192.0.43.8 (iana.org)
curl: (28) Operation timed out after 1002 milliseconds with 0 bytes received
> testing iana.org on 172.67.182.196 (rutracker.org)
HTTP/1.1 409 Conflict
> testing iana.org on 104.21.32.39 (rutracker.org)
HTTP/1.1 409 Conflict

> testing iana.org on it's original ip
!!!!! AVAILABLE !!!!!
> testing rutracker.org on 192.0.43.8 (iana.org)
curl: (28) Connection timed out after 1001 milliseconds
> testing iana.org on 172.67.182.196 (rutracker.org)
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure
> testing iana.org on 104.21.32.39 (rutracker.org)
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure

> testing iana.org on it's original ip
!!!!! AVAILABLE !!!!!
> testing rutracker.org on 192.0.43.8 (iana.org)
HTTP/1.1 307 Temporary Redirect
Location: https://www.gblnet.net/blocked.php
> testing iana.org on 172.67.182.196 (rutracker.org)
HTTP/1.1 409 Conflict
> testing iana.org on 104.21.32.39 (rutracker.org)
HTTP/1.1 409 Conflict

> testing iana.org on it's original ip
!!!!! AVAILABLE !!!!!
> testing rutracker.org on 192.0.43.8 (iana.org)
curl: (35) Recv failure: Connection reset by peer
> testing iana.org on 172.67.182.196 (rutracker.org)
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure
> testing iana.org on 104.21.32.39 (rutracker.org)
curl: (35) OpenSSL/3.2.1: error:0A000410:SSL routines::ssl/tls alert handshake failure

ПРИМЕР ПОЛНОГО IP БЛОКА ИЛИ БЛОКА TCP ПОРТА ПРИ ОТСУТСТВИИ БЛОКА ПО ДОМЕНУ

* port block tests ipv4 startmail.com:80
ncat -z -w 1 145.131.90.136 80
145.131.90.136 does not connect. netcat code 1
ncat -z -w 1 145.131.90.152 80
145.131.90.152 does not connect. netcat code 1

* curl_test_http ipv4 startmail.com
- checking without DPI bypass
curl: (28) Connection timed out after 2002 milliseconds
UNAVAILABLE code=28

- IP block tests (requires manual interpretation)
> testing iana.org on it's original ip
!!!!! AVAILABLE !!!!!
> testing startmail.com on 192.0.43.8 (iana.org)
HTTP/1.1 302 Found
Location: https://www.iana.org/
> testing iana.org on 145.131.90.136 (startmail.com)
curl: (28) Connection timed out after 2002 milliseconds
> testing iana.org on 145.131.90.152 (startmail.com)
curl: (28) Connection timed out after 2002 milliseconds

Новое дополнение к split и disorder. Опция --dpi-desync-split-seqovl.
Это достаточно сложная для понимания концепция, если не представляешь себе хорошо как работает tcp протокол.
Если сказать по-простому, то это замешивание фейковых данных и реальных в разделяемые сегменты tcp. Замешивание идет через игру с sequence numbers таким образом, чтобы сервер воспринял лишь оригинал, а DPI было очень сложно разобраться где оригинал, а где мусор.
Этот вариант может не требовать отдельных фейк пакетов, а следовательно TTL и fooling.

На ТСПУ игра с sequence обычно вызывает зависание http, но работает на https.

Полное описание из readme.

seqovl добавляет в начало первой отсылаемой части оригинального пакета (1 часть для split и 2 часть для disorder) seqovl байт со смещенным в минус sequence number на величину seqovl.
В случае split2 расчет идет на то, что предыдущий отсыл, если он был, уже попал в сокет серверного приложения, поэтому новая пришедшая часть лишь частично находится в пределах текущего окна (in-window). Спереди фейковая часть отбрасывается, а оставшаяся часть содержит оригинал и начинается с начала window, поэтому попадает в сокет. Серверное приложение получает все, что реально отсылает клиент, отбрасывая фейковую out-of-window часть. Но DPI не может этого понять, поэтому у него происходит sequence десинхронизация.

Для disorder2 overlap идет на 2-ю часть пакета. Обязательно, чтобы seqovl был меньше split_pos, иначе все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня. При соблюдении этого условия 2-я часть пакета является полностью in-window, поэтому серверная ОС принимает ее целиком, включая фейк. Но поскольку начальная часть данных из 1 пакета еще не принята, то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение. Как только приходит 1-я часть пакета, она переписывает фейковую часть в памяти ядра. Ядро получает данные из 1 и 2 части, поэтому далее идет отправка в сокет приложения. Таково поведение всех unix ОС - оставлять последние принятые данные.
Для windows серверов может быть наоборот, поэтому не факт, что такой вариант будет на них работать. Метод позволяет обойтись без fooling и TTL. Фейки перемешаны с реальным данными.
split/disorder вместо split2/disorder2 по-прежнему добавляют дополнительные отдельные фейки.

Как показывает практика, на https оно может не работать на TLS1.2, поскольку сечется ответ сервера с сертификатом. Только --wssize 1:6 позволяет это обойти.