--dpi-desync-fwmark=<int|0xHEX> ; бит fwmark для пометки десинхронизирующих пакетов, чтобы они повторно не падали в очередь. default = 0x40000000
--dpi-desync-ttl=<int> ; установить ttl для десинхронизирующих пакетов
--dpi-desync-ttl6=<int> ; установить ipv6 hop limit для десинхронизирующих пакетов. если не указано, используется значение ttl
@ -186,8 +274,10 @@ dvtws, собираемый из тех же исходников (см. [док
--dpi-desync-fooling=<fooling> ; дополнительные методики как сделать, чтобы фейковый пакет не дошел до сервера. none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; посылать каждый генерируемый в nfqws пакет N раз (не влияет на остальные пакеты)
--dpi-desync-skip-nosni=0|1 ; 1(default)=не применять dpi desync для запросов без hostname в SNI, в частности для ESNI
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации в режимах split и disorder
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; единичный маркер, определяющий величину перекрытия sequence в режимах split и disorder. для split поддерживается только положительное число.
--dpi-desync-split-pos=<1..1500> ; (только для split*, disorder*) разбивать пакет на указанной позиции
--dpi-desync-split-http-req=method|host ; разбивка http request на указанном логическом месте
--dpi-desync-split-tls=sni|sniext ; разбивка tls client hello на указанном логическом месте
--dpi-desync-split-seqovl=<int> ; использовать sequence overlap перед первым отсылаемым оригинальным tcp сегментом
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; чем заполнять фейковую часть overlap
--dpi-desync-badseq-increment=<int|0xHEX> ; инкремент sequence number для badseq. по умолчанию -10000
--dpi-desync-badack-increment=<int|0xHEX> ; инкремент ack sequence number для badseq. по умолчанию -66000
@ -225,6 +315,12 @@ dvtws, собираемый из тех же исходников (см. [док
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
```
Параметры манипуляции могут сочетаться в любых комбинациях.
> [!TIP]
> **ЗАМЕЧАНИЕ.** Параметр `--wsize` считается устаревшим и более не поддерживается в скриптах. Функции сплита выполняются в
> рамках атаки десинхронизации. Это быстрее и избавляет от целого ряда недостатков wsize.
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования
опций. `--debug` лучше всего указывать в самом начале. Опции анализируются последовательно. Если ошибка будет при
проверке опции, а до анализа `--debug` еще дело не дошло, то сообщения не будут выведены в файл или syslog. При
@ -236,24 +332,18 @@ dvtws, собираемый из тех же исходников (см. [док
### АТАКА ДЕСИНХРОНИЗАЦИИ DPI
Суть ее в следующем. Берется оригинальный запрос, модифицируется, добавляется поддельная информация (фейки)
таким образом, чтобы ОС сервера передала серверному процессу оригинальный запрос в неизменном виде, а DPI увидел другое.
То, что он блокировать не станет. Сервер видит одно, DPI - другое. DPI не понимает, что передается запрещенный запрос и не блокирует его.
Суть ее в следующем. После выполнения tcp 3-way handshake идет первый пакет с данными от клиента. Там обычно `GET / ...`
или TLS ClientHello. Мы дропаем этот пакет, заменяя чем-то другим. Это может быть поддельная версия с безобидным, но
валидным запросом http или https (вариант `fake`), пакет сброса соединения (варианты `rst`, `rstack`), разбитый на части
оригинальный пакет с перепутанным порядком следования сегментов + обрамление первого сегмента фейками (`disorder`), то
же самое без перепутывания порядка сегментов (`split`). fakeknown отличается от fake тем, что применяется только к
распознанному протоколу. В литературе такие атаки еще называют **TCB desynchronization** и **TCB teardown**. Надо, чтобы
фейковые пакеты дошли до DPI, но не дошли до сервера. На вооружении есть следующие возможности : установить низкий TTL,
посылать пакет с инвалидной чексуммой, добавлять tcp option **MD5 signature**, испортить sequence numbers. Все они не
лишены недостатков.
Есть арсенал возможностей, чтобы достичь такого результата.
Это может быть передача фейк пакетов, чтобы они дошли до DPI, но не дошли до сервера. Может использоваться фрагментация на уровне TCP (сегментация) или на уровне IP.
Есть атаки, основанные на игре с tcp sequence numbers или с перепутыванием порядка следования tcp сегментов.
Методы могут сочетаться в различных вариантах.
### ФЕЙКИ
Фейки - это отдельные сгенерированные nfqws пакеты, несущие ложную информацию для DPI.
Они либо не должны дойти до сервера, либо могут дойти, но должны быть им отброшены.
Иначе получается слом tcp соединения или нарушение целостности передаваемого потока, что гарантированно приводит к поломке ресурса.
Есть ряд методов для решения этой задачи.
* `md5sig` добавляет TCP опцию **MD5 signature**. Работает не на всех серверах. Пакеты с md5 обычно отбрасывают только linux.
* `badsum` портит контрольную сумму TCP. Не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. Наиболее
* `md5sig` работает не на всех серверах. Пакеты с md5 обычно отбрасывают только linux.
* `badsum` не сработает, если ваше устройство за NAT, который не пропускает пакеты с инвалидной суммой. Наиболее
распространенная настройка NAT роутера в Linux их не пропускает. На Linux построено большинство домашних роутеров.
Непропускание обеспечивается так : настройка ядра sysctl по умолчанию
`net.netfilter.nf_conntrack_checksum=1` заставляет conntrack проверять tcp и udp чексуммы входящих пакетов и
@ -269,8 +359,7 @@ dvtws, собираемый из тех же исходников (см. [док
себя ведут некоторые роутеры на базе mediatek. badsum пакеты уходят с клиентской ОС, но роутером не видятся в br-lan
через tcpdump. При этом если nfqws выполняется на самом роутере, обход может работать. badsum нормально уходят с
внешнего интерфейса.
* `badseq` увеличивает TCP sequence number на определенное значение, выводя его тем самым из TCP window.
Такие пакеты будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется на sequence
* Пакеты с`badseq` будут наверняка отброшены принимающим узлом, но так же и DPI, если он ориентируется на sequence
numbers. По умолчанию смещение seq выбирается -10000. Практика показала, что некоторые DPI не пропускают seq вне
определенного окна. Однако, такое небольшое смещение может вызвать проблемы при существенной потоковой передаче и
потере пакетов. Если вы используете `--dpi-desync-any-protocol`, может понадобится установить badseq increment
@ -294,8 +383,7 @@ dvtws, собираемый из тех же исходников (см. [док
может ломать NAT и не всегда работает с iptables, если используется masquerade, даже с локальной системы (почти всегда
на роутерах ipv4). На системах c iptables без masquerade и на nftables работает без ограничений. Экспериментально
выяснено, что многие провайдерские NAT не отбрасывают эти пакеты, потому работает даже с внутренним провайдерским IP.
Но linux NAT оно не пройдет, так что за домашним роутером эта техника скорее всего не сработает, но может сработать с него.
Может сработать и через роутер, если подключение по проводу, и на роутере включено аппаратное ускорение.
Но linux NAT оно не пройдет, так что за домашним роутером эта техника не сработает, но может сработать с него.
* `autottl`. Суть режима в автоматическом определении TTL, чтобы он почти наверняка прошел DPI и немного не дошел до
сервера. Берутся базовые значения TTL 64,128,255, смотрится входящий пакет
(да, требуется направить первый входящий пакет на nfqws !). Вычисляется длина пути, отнимается `delta` (1 по
@ -308,64 +396,44 @@ dvtws, собираемый из тех же исходников (см. [док
Режимы дурения могут сочетаться в любых комбинациях. `--dpi-desync-fooling` берет множество значений через запятую.
### TCP СЕГМЕНТАЦИЯ
Для режимов fake, rst, rstack после фейка отправляем оригинальный пакет.
* `multisplit`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях.
* `multidisorder`. нарезаем запрос на указанных в `--dpi-desync-split-pos` позициях и отправляем в обратном порядке.
* `fakedsplit`. нарезаем запрос на 2 части, обрамляя его фейками : фейк 1-й части, 1 часть, фейк 1-й части, 2 часть
* `fakeddisorder`. нарезаем запрос на 2 части, обрамляя его фейками : 2 часть, фейк 1-й части, 1 часть, фейк 1 части.
Режим disorder делит оригинальный пакет на 2 части и отправляет следующую комбинацию в указанном порядке :
Для определения позиций нарезки используются маркеры.
1. 2-я часть пакета
2. поддельная 1-я часть пакета, поле данных заполнено нулями
3. 1-я часть пакета
4. поддельная 1-я часть пакета, поле данных заполнено нулями. отсылка 2-й раз. Оригинальный пакет дропается всегда.
* **Абсолютный положительный маркер** - числовое смещение внутри пакета или группы пакетов от начала.
* **Абсолютный отрицательный маркер** - числовое смещение внутри пакета или группы пакетов от следующего за концом байта. -1 указывает на последний байт.
* **Относительный маркер** - положительное или отрицательное смещение относительно логической позиции внутри пакета или группы пакетов.
Параметр `--dpi-desync-split-pos` позволяет указать байтовую позицию, на которой происходит разбивка. По умолчанию - 2.
Если позиция больше длины пакета, позиция выбирается 1. Этой последовательностью для DPI максимально усложняется задача
реконструкции начального сообщения, по которому принимается решение о блокировке. Некоторым DPI хватит и tcp сегментов в
неправильном порядке, поддельные части сделаны для дополнительной надежности и более сложных алгоритмов реконструкции.
Режим `disorder2` отключает отправку поддельных частей.
Относительные позиции :
Режим `split` очень похож на disorder, только нет изменения порядка следования сегментов :
* **method** - начало метода HTTP ('GET', 'POST', 'HEAD', ...). Метод обычно всегда находится на позиции 0, но поддерживается и нахождение метода после дурение методом `--methodeol` от tpws. Тогда позиция может стать 1 или 2.
* **host** - начало имени хоста в известном протоколе (http, TLS)
* **endhost** - конец имени хоста
* **sld** - начало домена 2 уровня в имени хоста
* **endsld** - конец домена 2 уровня в имени хоста
* **midsld** - середина домена 2 уровня в имени хоста
* **sniext** - начало поля данных SNI extension в TLS. Любой extension состоит из 2-байтовых полей type и length, за ними идет поле данных.
1. поддельная 1-я часть пакета, поле данных заполнено нулями
2. 1-я часть пакета
3. поддельная 1-я часть пакета, поле данных заполнено нулями. отсылка 2-й раз.
4. 2-я часть пакета Режим split2 отключает отправку поддельных частей. Он может быть использован как более быстрая
альтернатива --wsize.
Пример списка маркеров : `100,midsld,sniext+1,endhost-2,-10`.
`disorder2` и `split2` не предполагают отсылку фейк пакетов, поэтому опции ttl и fooling неактуальны.
При разбиении пакета первым делом происходит ресолвинг маркеров - нахождение всех указанных относительных позиций и применение смещений.
Если относительная позиция отсутствует в текущем протоколе, такие позиции не применяются и отбрасываются.
Дальше происходит нормализация позиций относительно смещения текущего пакета в группе пакетов (многопакетные запросы TLS с kyber, например).
Выкидываются все позиции, выходящие за пределы текущего пакета. Оставшиеся сортируются в порядке возрастания и удаляются дубли.
В вариантах `multisplit` и `multidisorder` если не осталось ни одной позиции, разбиение не происходит.
Варианты `fakedsplit` и `fakeddisorder` применяют только одну позицию сплита. Ее поиск среди списка `--dpi-desync-split-pos` осуществляется особым образом.
Сначала сверяются все относительные маркеры. Если среди них найден подходящий, применяется он. В противном случае сверяются все абсолютные маркеры.
Если и среди них ничего не найдено, применяется позиция 1.
Например, можно написать `--dpi-desync-split-pos=method+2,midsld,5`. Если протокол http, разбиение будет на позиции `method+2`.
Если протокол TLS - на позиции `midsld`. Если протокол неизвестен и включено `--dpi-desync-any-protocol`, разбиение будет на позиции 5.
Чтобы все было однозначнее, можно использовать разные профили для разных протоколов и указывать только одну позицию, которая точно есть в этом протоколе.
### ПЕРЕКРЫТИЕ SEQUENCE NUMBERS
`seqovl` добавляет в начало одного из TCP сегментов `seqovl` байт со смещенным в минус sequence number на величину `seqovl`.
Для `split` - в начало первого сегмента, для `disorder` - в начало предпоследнего отсылаемого сегмента (второго в оригинальном порядке следования).
В случае `split` расчет идет на то, что предыдущий отсыл, если он был, уже попал в сокет серверного приложения, поэтому новая пришедшая часть лишь частично находится в
`seqovl` добавляет в начало первой отсылаемой части оригинального пакета (1 часть для split и 2 часть для disorder)
`seqovl` байт со смещенным в минус sequence number на величину seqovl. В случае `split2` расчет идет на то, что предыдущий
отсыл, если он был, уже попал в сокет серверного приложения, поэтому новая пришедшая часть лишь частично находится в
пределах текущего окна (in-window). Спереди фейковая часть отбрасывается, а оставшаяся часть содержит оригинал и
начинается с начала window, поэтому попадает в сокет. Серверное приложение получает все, что реально отсылает клиент,
отбрасывая фейковую out-of-window часть. Но DPI не может этого понять, поэтому у него происходит sequence десинхронизация.
Обязательно, чтобы первый сегмент вместе с`seqovl` не превысили длину MTU. Эта ситуация распознается автоматически в Linux, и `seqovl` отменяется.
В остальных системах ситуация не распознается, и это приведет к поломке соединения. Поэтому выбирайте первую позицию сплита и `seqovl` таким образом, чтобы MTU не был превышен в любом случае.
Иначе дурение может не работать или работать хаотично.
отбрасывая фейковую out-of-window часть. Но DPI не может этого понять, поэтому у него происходит sequence
десинхронизация.
Для `disorder` overlap идет на предпоследнюю отсылаемую часть пакета.
Для простоты будем считать, что разбиение идет на 2 части, шлются они в порядке "2 1" при оригинальном порядке "1 2".
Обязательно, чтобы `seqovl` был меньше позиции первого сплита, иначе все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня.
Такая ситуация легко обнаруживается программой, и `seqovl` отменяется. Увеличение размера пакета невозможно в принципе.
При соблюдении условия 2-я часть пакета является полностью in-window, поэтому серверная ОС принимает ее целиком, включая фейк.
Но поскольку начальная часть данных из 1 пакета еще не принята, то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение.
Для `disorder2` overlap идет на 2-ю часть пакета. Обязательно, чтобы `seqovl` был меньше `split_pos`, иначе
все отосланное будет передано в сокет сразу же, включая фейк, ломая протокол прикладного уровня.
При соблюдении этого условия 2-я часть пакета является полностью in-window,
поэтому серверная ОС принимает ее целиком, включая фейк. Но поскольку начальная часть данных из 1 пакета
еще не принята, то фейк и реальные данные остаются в памяти ядра, не отправляясь в серверное приложение.
Как только приходит 1-я часть пакета, она переписывает фейковую часть в памяти ядра.
Ядро получает данные из 1 и 2 части, поэтому далее идет отправка в сокет приложения.
Таково поведение всех unix ОС, кроме solaris - оставлять последние принятые данные.
@ -373,13 +441,7 @@ Windows оставляет старые данные, поэтому disorder с
при работе с Windows серверами. Solaris практически мертв, windows серверов очень немного.
Можно использовать листы при необходимости.
Метод позволяет обойтись без fooling и TTL. Фейки перемешаны с реальным данными.
`fakedsplit/fakeddisorder` по-прежнему добавляют дополнительные отдельные фейки.
`seqovl` в варианте `split` может быть только абсолютным положительным значением, поскольку применяется только в первому пакету.
В варианте `disorder` допустимо применение всех вариантов маркеров.
Они автоматически нормализуются к текущему пакету в серии. Можно сплитать на `midsld` и делать seqovl на `midsld-1`.
### СПЕЦИФИЧЕСКИЕ РЕЖИМЫ IPV6
`split/disorder` вместо `split2/disorder2` по-прежнему добавляют дополнительные отдельные фейки.
Режимы десинхронизации `hopbyhop`, `destopt` и `ipfrag1` (не путать с fooling !) относятся только к `ipv6` и заключается
в добавлении хедера `hop-by-hop options`, `destination options` или `fragment` во все пакеты, попадающие под десинхронизацию.
@ -390,22 +452,10 @@ Windows оставляет старые данные, поэтому disorder с
extension хедерам в поисках транспортного хедера. Таким образом не поймет, что это tcp или udp, и пропустит пакет
без анализа. Возможно, какие-то DPI на это купятся.
Может сочетаться с любыми режимами 2-й фазы, кроме варианта `ipfrag1+ipfrag2`.
Например, `hopbyhop,multisplit` означает разбить tcp пакет на несколько сегментов, в каждый из них добавить hop-by-hop.
Например, `hopbyhop,split2` означает разбить tcp пакет на 2 сегмента, в каждый из них добавить hop-by-hop.
При `hopbyhop,ipfrag2` последовательность хедеров будет : `ipv6,hop-by-hop`,`fragment`,`tcp/udp`.
Режим `ipfrag1` может срабатывать не всегда без специальной подготовки. См. раздел `IP фрагментация`.
### КОМБИНИРОВАНИЕ МЕТОДОВ ДЕСИНХРОНИЗАЦИИ
В параметре dpi-desync можно указать до 3 режимов через запятую.
* 0 фаза - предполагает работу на этапе установления соединения : `synack`, `syndata``--wsize`, `--wssize`. На эту фазу не действуют фильтры по [hostlist](((#множественные-стратегии))).
* 1 фаза - отсылка чего-либо до оригинального пакета данных : `fake`, `rst`, `rstack`.
* 2 фаза - отсылка в модифицированном виде оригинального пакета данных (например, `fakedsplit` или `ipfrag2`).
Режимы требуют указания в порядке возрастания номеров фаз.
### РЕАКЦИЯ DPI НАОТВЕТСЕРВЕРА
Есть DPI, которые анализируют ответы от сервера, в частности сертификат из ServerHello, где прописаны домены.
Подтверждением доставки ClientHello является ACK пакет от сервера с номером ACK sequence, соответствующим длине ClientHello+1.
В варианте disorder обычно приходит сперва частичное подтверждение (SACK), потом полный ACK.
@ -420,6 +470,44 @@ DPI может отстать от потока, если ClientHello егоу
Лучшее решение - включить на сервере поддержку TLS 1.3. В нем сертификат сервера передается в зашифрованном виде.
Это рекомендация ко всем админам блокируемых сайтов. Включайте TLS 1.3. Так вы дадите больше возможностей преодолеть DPI.
Хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
6 пакетов берется, чтобы покрыть случаи возможных ретрансмиссий quic initial в случае плохой связи или если сервер плохо себя чувствует, а приложение настаивает именно на quic, не переходя на tcp.
А так же для работы autohostlist по quic. Однако, autohostlist для quic не рекомендуется.
Если ваше устройство поддерживает аппаратное ускорение (flow offloading, hardware nat, hardware acceleration), то
iptables могут не работать. При включенном offloading пакет не проходит по обычному пути netfilter. Необходимо или его
отключить, или выборочно им управлять.
В новых ядрах присутствует software flow offloading (SFO).
Пакеты, проходящие через SFO, так же проходят мимо большей части механизмов iptables. При включенном SFO работает
DNAT/REDIRECT (tpws). Эти соединения исключаются из offloading. Однако, остальные соединения идут через SFO, потому
NFQUEUE будет срабатывать только до помещения соединения в flowtable. Практически это означает, что почти весь функционал nfqws работать не будет.
Offload включается через специальный target в iptables `FLOWOFFLOAD`. Не обязательно пропускать весь трафик через offload. Можно исключить из
offload соединения, которые должны попасть на tpws или nfqws. openwrt не предусматривает выборочного управления offload.
Поэтому скрипты zapret поддерживают свою систему выборочного управления offload в openwrt.
iptables target `FLOWOFFLOAD` - это проприетарное изобретение openwrt.
Управление offload в nftables реализовано в базовом ядре linux без патчей.
## tpws
tpws - это transparent proxy.
@ -812,10 +791,10 @@ tpws - это transparent proxy.
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
--fix-seg ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host
--split-pos=<offset> ; делить все посылы на сегменты в указанной позиции. единственная опция, работающая на не-http. при указании split-http-req он имеет преимущество на http.
--split-any-protocol ; применять split-pos к любым пакетам. по умолчанию - только к http и TLS ClientHello
--disorder[=http|tls] ; путем манипуляций с сокетом вынуждает отправлять первым второй сегмент разделенного запроса
--oob[=http|tls] ; отправить байт out-of-band data (OOB) в конце первой части сплита
--oob-data=<char>|0xHEX ; переопределить байт OOB. по умолчанию 0x00.
@ -829,8 +808,10 @@ tpws - это transparent proxy.
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
--methodeol ; добавить перевод строки перед методом : "GET /" => "\r\nGET /"
--unixeol ; конвертировать 0D0A в 0A и использовать везде 0A
--tlsrec=N|-N|marker+N|marker-N ; разбивка TLS ClientHello на 2 TLS records на указанной позиции. Минимальное смещение - 6.
--tlsrec=sni|sniext ; разбивка TLS ClientHello на 2 TLS records. режем между 1 и 2 символами hostname в SNI или между байтами длины SNI extension. Если SNI нет - отмена.
--tlsrec-pos=<pos> ; разбивка TLS ClientHello на 2 TLS records. режем на указанной позиции, если длина слишком мелкая - на позиции 1.
--mss=<int> ; установить MSS для клиента. может заставить сервер разбивать ответы, но существенно снижает скорость
--mss-pf=[~]port1[-port2] ; применять MSS только к портам назначения, подпадающим под фильтр. ~ означает инверсию
--tamper-start=[n]<pos> ; начинать дурение только с указанной байтовой позиции или номера блока исходяшего потока (считается позиция начала принятого блока)
--tamper-cutoff=[n]<pos> ; закончить дурение на указанной байтовой позиции или номере блока исходящего потока (считается позиция начала принятого блока)
--hostlist=<filename> ; действовать только над доменами, входящими в список из filename. поддомены автоматически учитываются.
@ -853,115 +834,6 @@ tpws - это transparent proxy.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
```
### TCP СЕГМЕНТАЦИЯ В TPWS
tpws, как и nfqws, поддерживает множественную сегментацию запросов. Сплит позиции задаются в `--split-pos`.
Указываются маркеры через запятую. Описание маркеров см в разделе [nfqws](#tcp-сегментация).
На прикладном уровне в общем случае нет гарантированного средства заставить ядро выплюнуть
блок данных, порезанным в определенном месте. ОС держит буфер отсылки (SNDBUF) у каждого сокета.
Если у сокета включена опция TCP_NODELAY и буфер пуст, то каждый send приводит к отсылке
отдельного ip пакета или группы пакетов, если блок не вмещается в один ip пакет.
Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему,
никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии,
что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI.
Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса.
Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае.
Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда,
когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан,
но и принят другой стороной, а следовательно буфер отсылки пуст, и следующие 2 send приведут
к отсылке сегментов данных разными ip пакетами.
Таким образом tpws обеспечивает сплит только за счет раздельных вызовов send, и это обычно работает надежно,
если разбивать не на слишком много частей и не на слишком мелкие подряд следующие части.
В последнем случае Linux все же может обьединить некоторые части, что приведет к несоответствию реальной сегментации
указанным сплит позициям. Другие ОС в этом вопросе ведут себя более предсказуемо. Спонтанного обьединения замечено не было.
Поэтому не стоит злоупотреблять сплитами и в особенности мелкими соседними пакетами.
Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8.
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
Если вы его видите, это повод снизить количество сплит позиций.
Если это не вариант, есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
И производится оно только , если происходит split, и в ожидании есть реальная необходимость.
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
tpws работает на уровне сокетов, поэтому длинный запрос, не вмещающийся в 1 пакет (TLS с kyber), он получает целым блоком.
На каждую сплит часть он делает отдельный вызов `send()`. НоОС не сможет отослать данные в одном пакете, если размер превысит MTU.
В случае слишком большого сегмента ОС дополнительно его порежет на более мелкие. Результат должен быть аналогичен nfqws.
`--disorder` заставляет слать каждый 2-й пакет с TTL=1, начиная с первого.
К серверу приходят все четные пакеты сразу. На остальные ОС делает ретрансмиссию, и они приходят потом.
Это само по себе создает дополнительную задержку (200 мс в linux для первой ретрансмиссии).
Иным способом сделать disorder в сокет варианте не представляется возможным.
Итоговый порядок для 6 сегментов получается `2 4 6 1 3 5`.
`--oob` высылает 1 байт out-of-band data после первого сплит сегмента. `oob` в каждом сегменте сплита показал себя ненадежным.
Сервер получает oob в сокет.
Сочетание `oob` и `disorder` возможно только в Linux. Остальные ОС не умеют с таким справляться. Флаг URG теряется при ретрансмиссиях.
Сервер получает oob в сокет. Сочетание этих параметров в ос, кроме Linux, вызывает ошибку на этапе запуска.
### TLSREC
`--tlsrec` позволяют внутри одного tcp сегмента разрезать TLS ClientHello на 2 TLS records. Можно использовать стандартный
механизм маркеров для задания относительных позиций.
`--tlsrec` ломает значительное количество сайтов. Криптобиблиотеки (openssl, ...) на оконечных http серверах
без проблем принимают разделенные tls сегменты, но мидлбоксы - не всегда. К мидлбоксам можно отнести CDN
или системы ddos-защиты. Поэтому применение `--tlsrec` без ограничителей вряд ли целесообразно.
В РФ `--tlsrec` обычно не работает с TLS 1.2, потому что цензор парсит сертификат сервера из ServerHello.
Работает только с TLS 1.3, поскольку там эта информация шифруется.
Впрочем, сейчас сайтов, не поддерживающих TLS 1.3, осталось немного.
### MSS
`--mss` устанавливает опцию сокета TCP_MAXSEG. Клиент выдает это значение в tcp опциях SYN пакета.
Сервер в ответ в SYN,ACK выдает свой MSS. На практике сервера обычно снижают размеры отсылаемых ими пакетов, но они
все равно не вписываются в низкий MSS, указанный клиентом. Обычно чем больше указал клиент, тем больше
шлет сервер. На TLS 1.2 если сервер разбил заброс так, чтобы домен из сертификата не попал в первый пакет,
это может обмануть DPI, секущий ответ сервера.
Схема может значительно снизить скорость и сработать не на всех сайтах.
С фильтром по hostlist совместимо только в режиме socks при включенном удаленном ресолвинге хостов.
(firefox network.proxy.socks_remote_dns). Это единственный вариант, когда tpws может узнать имя хоста
еще на этапе установления соединения.
Применяя данную опцию к сайтам TLS1.3, если броузер тоже поддерживает TLS1.3, то вы делаете только хуже.
Но нет способа автоматически узнать когда надо применять, когда нет, поскольку MSS идет только в
3-way handshake еще до обмена данными, а версию TLS можно узнать только по ответу сервера, который
может привести к реакции DPI.
Использовать только когда нет ничего лучше или для отдельных ресурсов.
Для http использовать смысла нет, поэтому заводите отдельный desync profile с фильтром по порту 443.
Работает только на Linux, не работает на BSD и MacOS.
### ДРУГИЕ ПАРАМЕТРЫ ДУРЕНИЯ
Параметр `--hostpad=<bytes>` добавляет паддинг-хедеров перед `Host:` на указанное количество байтов.
Если размер `<bytes>` слишком большой, то идет разбивка на разные хедеры по 2K.
Общий буфер приема http запроса - 64K, больший паддинг не поддерживается, да и http сервера
такое уже не принимают.
Полезно против DPI, выполняющих реассемблинг TCP с ограниченным буфером.
Если техника работает, то после некоторого количества bytes http запрос начнет проходить до сайта.
Если при этом критический размер padding около MTU, значит скорее всего DPI не выполняет реассемблинг пакетов, и лучше будет использовать обычные опции TCP сегментации.
Если все же реассемблинг выполняется, то критический размер будет около размера буфера DPI. Он может быть 4K или 8K, возможны и другие значения.
### МНОЖЕСТВЕННЫЕ СТРАТЕГИИ
Работают аналогично `nfqws`, кроме некоторых моментов.
Нет параметра `--filter-udp`, поскольку `tpws` udp не поддерживает.
Методы нулевой фазы (`--mss`) могут работать по хостлисту в одном единственном случае:
если используется режим socks и удаленный ресолвинг хостов через прокси.
То есть работоспособность вашей настройки в одном и том же режиме может зависеть от того,
применяет ли клиент удаленный ресолвинг. Это может быть неочевидно.
В одной программе работает, в другой - нет.
Если вы используете профиль с хостлистом , и вам нужен mss, укажите mss в профиле с хостлистом,
создайте еще один профиль без хостлиста, если его еще нет, и в нем еще раз укажите mss.
Тогда при любом раскладе будет выполняться mss.
Используйте `curl --socks5` и `curl --socks5-hostname` для проверки вашей стратегии.
Смотрите вывод `--debug`, чтобы убедиться в правильности настроек.
### СЛУЖЕБНЫЕ ПАРАМЕТРЫ
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл.
Может быть важен порядок следования опций. `--debug` лучше всего указывать в самом начале.
Опции анализируются последовательно. Если ошибка будет при проверке опции, а до анализа `--debug` еще дело не дошло,
@ -978,6 +850,28 @@ tpws работает на уровне сокетов, поэтому длин
Вместо удаления лучше использовать truncate.
В шелле это можно сделать через команду ": >filename"
Параметры манипуляции могут сочетаться в любых комбинациях.
В случае http запроса `split-http-req` имеет преимущество над split-pos.
split-pos по умолчанию работает только на http и TLS ClientHello.
Чтобы он работал на любых пакетах, укажите `--split-any-protocol`.
На прикладном уровне в общем случае нет гарантированного средства заставить ядро выплюнуть
блок данных, порезанным в определенном месте. ОС держит буфер отсылки (SNDBUF) у каждого сокета.
Если у сокета включена опция TCP_NODELAY и буфер пуст, то каждый send приводит к отсылке
отдельного ip пакета или группы пакетов, если блок не вмещается в один ip пакет.
Однако, если в момент send уже имеется неотосланный буфер, то ОС присоединит данные к нему,
никакой отсылки отдельным пакетом не будет. Но в этом случае и так нет никакой гарантии,
что какой-то блок сообщения пойдет в начале пакета, на что собственно и заточены DPI.
Разбиение будет производится согласно MSS, который зависит от MTU исходящего интерфейса.
Таким образом DPI, смотрящие в начало поля данных TCP пакета, будут поломаны в любом случае.
Протокол http относится к запрос-ответным протоколам. Новое сообщение посылается только тогда,
когда сервер получил запрос и полностью вернул ответ. Значит запрос фактически был не только отослан,
но и принят другой стороной, а следовательно буфер отсылки пуст, и следующие 2 send приведут
к отсылке сегментов данных разными ip пакетами.
Резюме : tpws гарантирует сплит только за счет раздельных вызовов send, что на практике
вполне достаточно для протоколов http(s).
tpws может биндаться на множество интерфейсов и IP адресов (до 32 шт).
Порт всегда только один.
Параметры `--bind-iface*` и `--bind-addr` создают новый бинд.
@ -1001,17 +895,19 @@ tpws может биндаться на множество интерфейсо
Параметры rcvbuf и sndbuf позволяют установить setsockopt SO_RCVBUF SO_SNDBUF для локального и удаленного соединения.
`--skip-nodelay` может быть полезен, когда tpws используется без дурения, чтобы привести MTU к MTU системы, на которой работает tpws.
Это может быть полезно для скрытия факта использования VPN. Пониженный MTU - 1 из способов обнаружения
подозрительного подключения. С tcp proxy ваши соединения неотличимы от тех, что сделал бы сам шлюз.
`--local-tcp-user-timeout` и `--remote-tcp-user-timeout` устанавливают значение таймаута в секундах
для соединений клиент-прокси и прокси-сервер. Этот таймаут соответствует опции сокета linux
TCP_USER_TIMEOUT. Под таймаутом подразумевается время, в течение которого буферизированные данные
не переданы или на переданные данные не получено подтверждение (ACK) от другой стороны.
Этот таймаут никак не касается времени отсутствия какой-либо передачи через сокет лишь потому,
что данных для передачи нет. Полезно для сокращения время закрытия подвисших соединений.
Поддерживается только на Linux и MacOS.
Если не указан ни один из параметров модификации содержимого, tpws работает в режиме `tcp proxy mode`.
Он отличается тем, что в оба конца применяется splice для переброски данных из одного сокета в другой
без копирования в память процесса. Практически - это то же самое, но может быть чуть побыстрее.
TCP проксирование может быть полезно для обхода блокировок, когда DPI спотыкается на экзотических
хедерах IP или TCP. Вы вряд ли сможете поправить хедеры, исходящие от айфончиков и гаджетиков,
но на linux сможете влиять на них в какой-то степени через `sysctl`.
Когда соединение проходит через tpws, фактически прокси-сервер сам устанавливает подключение к удаленному
узлу от своего имени, и на это распространяются настройки системы, на которой работает прокси.
tpws можно использовать на мобильном устройстве, раздающем интернет на тарифе сотового оператора,
где раздача запрещена, в socks режиме даже без рута. Соединения от tpws неотличимы от соединений
с самого раздающего устройства. Отличить можно только по содержанию (типа обновлений windows).
Заодно можно и обойти блокировки. 2 зайца одним выстрелом.
Более подробную информацию по вопросу обхода ограничений операторов гуглите на 4pda.ru.
Режим `--socks` не требует повышенных привилегий (кроме бинда на привилегированные порты 1..1023).
Поддерживаются версии socks 4 и 5 без авторизации. Версия протокола распознается автоматически.
@ -1025,77 +921,82 @@ tpws поддерживает эту возможность асинхронно
Если задан параметр `--no-resolve`, то подключения по именам хостов запрещаются, а пул ресолверов не создается.
Тем самым экономятся ресурсы.
### IPTABLES ДЛЯ TPWS
Параметр `--hostpad=<bytes>` добавляет паддинг-хедеров перед Host: на указанное количество байтов.
Если размер `<bytes>` слишком большой, то идет разбивка на разные хедеры по 2K.
Общий буфер приема http запроса - 64K, больший паддинг не поддерживается, да и http сервера
такое уже не принимают.
Полезно против DPI, выполняющих реассемблинг TCP с ограниченным буфером.
Если техника работает, то после некоторого количества bytes http запрос начнет проходить до сайта.
Если при этом критический размер padding около MTU, значит скорее всего DPI не выполняет реассемблинг пакетов, и лучше будет использовать обычные опции `--split-…`
Если все же реассемблинг выполняется, то критический размер будет около размера буфера DPI. Он может быть 4K или 8K, возможны и другие значения.
Для перенаправления tcp соединения на transparent proxy используются команды следующего вида :
`--disorder` - это попытка симулировать режим `disorder2 nfqws`, используя особенности ОС по реализации stream сокетов.
Однако, в отличие от nfqws, здесь не требуются повышенные привилегии.
Реализовано это следующим образом. У сокета есть возможность выставить TTL. Все пакеты будут отправляться с ним.
Перед отправкой первого сегмента ставим TTL=1. Пакет будет дропнут на первом же роутере, он не дойдет ни до DPI, ни до сервера.
Затем возвращаем TTL в значение по умолчанию. ОС отсылает второй сегмент, и он уже доходит до сервера.
Сервер возвращает SACK, потому что не получил первый кусок, и ОСего отправляет повторно, но здесь уже мы ничего не делаем.
Этот режим работает как ожидается на Linux и MacOS. Однако, на FreeBSD и OpenBSD он работает не так хорошо.
Ядро этих ОС отсылает ретрансмиссию в виде полного пакета. Потому выходит, что до сервера идет сначала второй кусок,
а потом полный запрос без сплита. На него может отреагировать DPI штатным образом.
`--disorder` является дополнительным флагом к любому сплиту. Сам по себе он не делает ничего.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.