Реализация некоторых способов запутывания DPI. Программа представляет собой локальный SOCKS прокси сервер. -------------- Использование: $ ./ciadpi --disorder 3 -A --tlsrec 1+s Описание аргументов: -i, --ip Прослушиваемый IP, по умолчанию 0.0.0.0 -p, --port Прослушиваемый порт, по умолчанию 1080 -c, --max-conn Максимальное количество клиентских подключений, по умолчанию 512 -I --conn-ip Адрес, к которому будут привязаны исходящие соединения, по умолчанию :: При указании IPv4 адреса запросы на IPv6 будут отклоняться -b, --buf-size Максимальный размер данных, получаемых и отправляемых за один вызов recv/send Размер указывается в байтах, по умолчанию равен 16384 -g, --def-ttl Значение TTL для всех исходящий соединений Может быть полезен для обхода обнаружения нестандартного/уменьшенного TTL -N, --no-domain Отбрасывать запросы, если в качестве адреса указан домен Т.к. резолвинг выполняется синхронно, то он может замедлить или даже заморозить работу -K, --desync-known Отключить запутывание для нераспознанных протоколов Распознаваемые протоколы: HTTP и TLS с SNI -F, --tfo Включает TCP Fast Open Если сервер его поддерживает, то первый пакет будет отправлен сразу вместе с SYN Поддерживается только в Linux (4.11+) -L, --late-conn Выполнять настоящее подключение только после получения первого пакета от клиента Полезно при сочетании --hosts с --dst -A, --auto[=t,r,c,s,a,n] Автоматический режим Если произошло событие, похожее на блокировку или поломку, то будут применены параметры обхода, следующие за данной опцией Возможные события: torst : Вышло время ожидания или сервер сбросил подключение после первого запроса redirect: HTTP Redirect с Location, домен которого не совпадает с исходящим cl_err : HTTP ответ, код которого равен 40x, но не 429 sid_inv : session_id в TLS ServerHello и ClientHello не совпадают alert : TLS Error Alert в ответе nop : Предыдущая группа пропущена, например из-за ограничения по hosts По умолчанию обрабатывается только torst Можно указывать несколько групп опций, раделяя их данным параметром Если соединение успешно прошло, то параметры для данного IP будут закешированны Параметры, которые можно вынести в отдельную группу: hosts, dst, split, disorder, oob, fake, ttl, ip-opt, md5sig, mod-http, tlsrec Пример: --auto=redirect --split=1+h --auto=torst --fake -1 --auto=sid_inv,alert --tlsrec 1+s -u, --cache-ttl Время жизни значения в кеше, по умолчанию 100800 (28 часов) -T, --timeout Таймаут ожидания первого ответа от сервера в секундах В Linux переводится в миллисекунды, поэтому можно указать дробное число Истечение таймаута будет обработано --auto -H, --hosts Ограничить область действия параметров списком доменов Домены должны быть разделены новой строкой или пробелом -D, --dst Заменить адрес назначения из запроса на указанный Полезно совмещать с --auto и --hosts -s, --split Разбить запрос по указанному смещению После числа можно добавить флаг: +s: добавить смещение SNI +h: добавить смещение Host Можно указывать несколько раз, чтобы разбить запрос по нескольким позициям При указании отрицательного значения к нему прибавляется размер пакета -d, --disorder Подобен --split, но части отправляются в обратном порядке ! Поведение в Windows отлично: сначала отправляется лишь часть, но затем целый запрос -o, --oob Подобен --split, но после части отсылается один или несколько байт OOB данных -f, --fake Подобен --disorder, только перед отправкой первого куска отправляется часть поддельного Количество байт отправляемого из фейка равно рамеру разбиваемой части -t, --ttl TTL для поддельного пакета, по умолчанию 8 Необходимо подобрать такое значение, чтобы пакет не дошел до сервера, но был обработан DPI -k, --ip-opt[=file|:str] Установить опции для фейкового IP пакета Существенно снизит вероятность, что пакет дойдет до сервера Стоит учесть, что до DPI он также может не дойти В Windows поддержка может быть отключена -S, --md5sig Установить опцию TCP MD5 Signature для фейкового пакета Большинство серверов (в основном на Linux) отбрасывают пакеты с данной опцией Поддерживается только в Linux, может быть выключен в некоторых сборках ядра (< 3.9, Android) -l, --fake-tls -j, --fake-http Указать свои поддельные пакеты, вместо дефолтных -e, --oob-data Данные, отсылаемые вне основного потока, по умолчанию один байт 'a' ! При размере более одного байта может работать нестабильно -n, --tls-sni Изменить SNI в fake пакете на указанный -M, --mod-http Всякие манипуляции с HTTP пакетом, можно комбинировать hcsmix: "Host: name" -> "hOsT: name" dcsmix: "Host: name" -> "Host: NaMe" rmspace: "Host: name" -> "Host:name\t" -r, --tlsrec Разделить ClientHello на отдельные записи по указанному смещению Можно указывать несколько раз ------- Детали: --split Разбивает запрос на части. Пример на запросе в 30 байт: - Параметры: --split 3 --split 7 - Порядок отправки: 1-3, 3-7, 7-30 --disorder Часть, попадающая под disorder, будет отправлена с TTL=1, т.е. фактически не будет никуда доставлена. Однако ОС узнает об этом лишь после отсылки последующей части, когда сервер сообщит о потере с помощью SACK. Системе придется отослать предыдущий пакет заново, тем самым нарушив порядок. Использовать disorder на нескольких позициях подряд нет смысла, т.к. они объединятся в один сегмент: - Параметры: --disorder 3 --disorder 7 - Порядок отправки: 7-30, 1-7 Сервер получает лишь 7-30 и сообщает о недостаче 1-7. Однако, можно использовать split: - Параметры: --disorder 3 --split 7 --disorder 23 - Порядок отправки: 3-7, 23-30, 1-3, 7-23 Сервер получает 3-7 и 23-30 и сообщает, что не получил 1-3 и 7-23. Вышесказанное распространяется только на Linux. В Windows выполняется полная ретрансмиссия: - Параметры: --disorder 7 - Порядок отправки: 7-30, 1-30 Когда сервер сообщает о пропуске 1-7, система отсылает 1-30, т.е. и доставленные данные тоже. DPI может среагировать на второй пакет, т.к. он никак не фрагментирован. Тут выручает split: - Параметры: --split 7 --disorder 23 - Порядок отправки: 1-7, 23-30, 7-30 Сервер полчует 1-7 и 23-30, сообщает о пропуске 7-23. В таком случае система отправит лишь 7-30. На практике оптимально использовать: Linux: --disorder 3 Windows: --split 1+s --disorder 3+s --fake Пример: - Параметры: --fake 7 - Порядок отправки: 1-7 фейк, 7-30 оригинал, 1-7 оригинал Данные в первой части запроса заменяются на поддельные. Эта часть должна пройти через DPI, но не дойти до сервера. А раз часть не дойдет, то ОС отправит ее снова, тем самым изменив порядок подобно disorder. Для того, чтобы фейк не дошел до сервера, есть опции ttl, ip-opt и md5sig. Можно подобрать такой TTL, чтобы пакет прошел через все DPI, но уничтожился по пути к серверу. Однако некоторые серверы расположены ближе DPI и поддельные пакеты до них могут все таки дойти. Тогда, скорее всего, сайт пришлет ошибку и разорвет соединение. Для того, чтобы обнаружить подобные ситуации, есть опция --auto: --fake -1 --ttl 10 --auto=cl_err,sid_inv,alert --fake -1 --ttl 6 В данном примере - если возникнет ошибка с ttl=10, то он будет уменьшен до 6-ти Помимо ttl, есть ip-opt. Он устанавливает IP Options для пакета. Пакеты с такой опцией наверняка отбросятся на магистрали, пройдя через несколько маршрутизаторов. Есть еще md5sig. Он устанавливает опцию TCP MD5 Signature, что не дает пакету быть принятым многими серверами. Однако, md5sig работает не во всех сборках Linux, а ip-opt не работает на многих версиях Windows. Для Windows есть еще один способ избежать обработки фейка сервером. Это комбинирование fake с disorder: - Параметры: --disorder 1 --fake 7 - Порядок отправки: 2-7 фейк, 7-30 оригинал, 1-30 оригинал Если поддельный пакет и дойдет до сервера, то он будет перезаписан из-за полной ретрансмисси. На практике оптимально использовать: Linux: --fake -1 --md5sig Windows: --disorder 1 --fake -1 --oob TCP может отсылать данные вне основного потока, используя флаг URG, однако лишь 1 байт в пакете. Все данные в таком пакете будут доставлены приложению, кроме последнего байта, который и является внеканальным: - Параметры: --oob 3 - Отправка: 1-4 с флагом URG (1-3 данные запроса + 4-й байт, который будет усечен), 3-30 Этот байт можно поместить, например, в SNI: --oob 3+s --tlsrec Одну TLS запись можно разбить на несколько, немного переделав заголовок. На месте разбиения вставляется новый заголовок, увеличивая размер запроса на 5 байт. Этот заголовок можно поместить в середину SNI, не давая возможность DPI правильно его прочитать: --tlsrec 3+s Хоть tlsrec и oob запутывают DPI, они также могут запутать всякие мидлбоксы, которые не поддерживают полноценный стек TCP/TLS, тем самым ограничив доступ к некоторым серверам. Поэтому их следует использовать вместе с --auto: --auto=torst --timeout 3 --tlsrec 3+s В примере tlsrec будет применяться лишь в случаях, когда сброшено подключение или вышел таймаут, т.е. когда, скорее всего, произошла блокировка. Можно наоборот - отменять tlsrec, если сервер сбрасывает подключение или откидывает пакет: --tlsrec 3+s --auto=torst --timeout 3 --auto, --hosts Параметр auto делит опции на группы. Для каждого запроса они обходятся слева на право. Сначала проверяется триггер указанный в auto, затем hosts. Примеры: --fake -1 --ttl 10 --auto=alert,sid_inv --fake -1 --ttl 5 По умолчанию использовать fake с ttl=10, в случае ошибки использовать fake с ttl=5 --hosts list.txt --disorder 3 --auto=nop Применять запутывание только для доменов из list.txt --hosts list.txt --auto=nop --disorder 3 Не применять запутывание для доменов из list.txt --late-conn --hosts ':one.one.one.one' --dst 1.1.1.1 --disorder 3 --auto=nop --auto=torst --timeout 3 --tlsrec 1+s Для указанного домена применять disorder, подключаясь только на указанный IP и игнорируя адрес из запроса. Для остальных ничего не делать, однако если обнаружится блокировка, то попробовать применить tlsrec. --auto=torst --hosts list.txt --disorder 3 По умолчанию ничего не делать, использовать disorder при условии, что произошла блокировка и домен входит в list.txt. ------- Сборка: Для сборки понадобится: make, gcc/clang для Linux, mingw для Windows # Linux $ make # Windows $ make windows CC=x86_64-w64-mingw32-gcc ------------- Дополнительная информация о DPI: https://github.com/bol-van/zapret/blob/master/docs/readme.txt https://geneva.cs.umd.edu/papers/geneva_ccs19.pdf https://habr.com/ru/post/335436