Исходящий desync
Исходящий desync приспосабливает прямые соединения к сетям с DPI-фильтрацией. Он подключается как DIRECT и до отправки преобразует первый TLS ClientHello соединения: делит его на несколько TLS-записей или TCP-записей, может отправить часть с числом хопов, которое истечёт по пути, или с последующим срочным байтом, а первую передачу может заменить подделка с малым TTL. Сервер получает тот же handshake. Всё после ClientHello и соединения, которые начинаются не с него, проходят без изменений. Это не туннель, сервер ему не нужен. Преобразования берутся из библиотеки desync версии v0.1.0.
proxies: - name: desync-yt type: desync tlsrec: "1+s" # позиции через запятую # split: "2" # по желанию: отдельные TCP-записи # split-delay: 0 # пауза между ними в мс, 0–1000 # split-wait: sent # sent | acked # disorder: true # нужен split # oob: true # нужен split # random: # tlsrec: [{ from: "-8+s", to: "8+s", count: 2 }] # fake: { ttl: 4, prefix: -1, sni: [www.example.com], randomize: true } # udp: { ttl: 4, template: quic, quic-only: true }
proxy-groups: - name: youtube type: fallback proxies: [desync-yt, vpn-node] # сначала desync, узел прокси в резерве url: https://www.youtube.com/generate_204 interval: 300
rules: - DOMAIN-SUFFIX,youtube.com,youtube - DOMAIN-SUFFIX,googlevideo.com,youtube - MATCH,DIRECTПараметры
Заголовок раздела «Параметры»| Ключ | Что задаёт |
|---|---|
tlsrec |
Где делить ClientHello на TLS-записи. 3 — байт 3 TLS-потока (считая от заголовка первой записи), 1+s — один байт после начала имени сервера, -2+s — два байта до него. |
split |
Где делить его на отдельные TCP-записи, в той же нотации. Как поток делится на TCP-сегменты, решает операционная система. |
split-delay |
Пауза между частями в миллисекундах, 0–1000. Нужны позиции разделения. |
split-wait |
sent или acked: перед каждой следующей частью ждать, пока ядро сообщит, что все прежние байты отправлены или подтверждены сервером. Ожидание заканчивается, как только это сообщено, и никогда не заменяется паузой по времени. Нужны позиции разделения. |
split-wait-timeout |
Предел каждого ожидания в миллисекундах, 0–60000 (по умолчанию 2000). Он же ограничивает ожидание disorder. Если время вышло, соединение закрывается. |
disorder |
Первая часть уходит с числом хопов 1 и истекает на первом маршрутизаторе; TCP передаёт её повторно после того, как сервер получил следующие части (ByeDPI --disorder). Нужны позиции разделения; не сочетается со split-wait: acked. |
oob |
После первой части отправляется один срочный (MSG_OOB) байт (ByeDPI --oob, вместе с disorder — --disoob). TCP сервера убирает его из потока. Нужны позиции разделения. |
oob-byte |
Этот байт, один ASCII-символ (по умолчанию a). Нужен oob. |
random |
Случайные разрезы для каждого соединения в дополнение к tlsrec/split: списки диапазонов в tlsrec и split, каждый { from, to, count, min-piece }. Диапазон даёт count разрезов (1–64, по умолчанию 1) из from..to (включительно, оба абсолютные или оба +s), не ближе min-piece байт друг к другу (по умолчанию 1); диапазон, который не помещается, обрезается. Не больше 16 диапазонов в списке. seed: 0 (по умолчанию) берёт новое зерно для каждого соединения; другое значение режет все соединения одинаково — для тестов и отчётов об ошибках. Случайные разрезы записей считаются позициями разделения. |
fake |
Windows, Linux и Android. Первая передача префикса ClientHello несёт подделку с малым числом хопов, повторная — исходные байты. С позициями разделения (или с disorder, oob) конец префикса — ещё один разрез, и подделкой становится часть, которая на нём кончается; первая часть тогда должна остаться обычной, иначе запись завершится ошибкой до отправки. prefix считается после деления на записи, отрицательный — от конца (по умолчанию -1); timeout ограничивает системную отправку в миллисекундах (по умолчанию 3000). Не сочетается со split-wait: acked. |
fake.ttl |
Число хопов подделки, 1–255. Обязателен без auto-ttl; с ним — запасное значение, когда путь не наблюдается (0 или не задан: такое соединение завершится ошибкой). |
fake.auto-ttl |
{ delta, min, max }: вывести число хопов из TTL пакета SYN-ACK сервера, хопы - delta в пределах min..max (по умолчанию 1, 3, 20; auto-ttl: {} берёт их). Наблюдается только на Linux и Android по IPv6, см. таблицу ниже. |
fake.sni |
Список имён сервера для поддельного ClientHello, для каждого соединения выбирается одно; * заменяется случайной буквой или цифрой, ? — буквой, # — цифрой. Только DNS-имена, не больше 64. |
fake.randomize |
Новые random, session ID и key share в подделке для каждого соединения. |
fake.from-original |
Строить подделку из собственного ClientHello соединения вместо встроенного шаблона. Нужен sni или randomize. |
fake.offset |
Начинать подделку с этого байта, 0–65535, например чтобы совместить её с частью, которая начинается не с начала потока. |
udp |
Перед каждой из первых packets (1–8, по умолчанию 3) датаграмм к адресату отправляет repeats (1–16, по умолчанию 6) датаграмм с малым TTL (ttl); исходные не меняются. Без udp UDP этого исходящего — обычный DIRECT. |
udp.template |
zero (64 нулевых байта, по умолчанию) или quic: каждая серия — заново созданный QUIC v1 Initial для udp.sni (по умолчанию www.wikipedia.org). |
udp.quic-only |
Серия только перед датаграммами, похожими на QUIC Initial клиента; остальной UDP проходит без изменений и не учитывается в packets. |
interface-name, routing-mark, ip-version |
Как у direct. |
Нужен хотя бы один из tlsrec, split, random, fake или udp. tfo, mptcp и dialer-proxy не принимаются: с TFO ClientHello ушёл бы вместе с SYN, до того как его можно разделить. Способ, который операционная система не реализует, — ошибка конфига с названием системы и причиной, а не молчаливый DIRECT.
Операционные системы
Заголовок раздела «Операционные системы»| Параметр | Windows | Linux | Android | macOS |
|---|---|---|---|---|
tlsrec, split, split-delay, random |
✓ | ✓ | ✓ | ✓ |
split-wait: sent |
✓¹ | ✓ | ✓⁵ | — |
split-wait: acked |
✓¹ | ✓ | ✓ | ✓ |
disorder |
✓¹ | ✓ | ✓⁵ | ✓² |
oob, oob-byte |
✓ | ✓ | ✓ | ✓ |
fake (с sni, randomize, from-original, offset, частями) |
✓ | ✓ | ✓⁵ | —³ |
fake.auto-ttl |
только запасной ttl⁴ |
IPv6; IPv4 берёт запасной ttl⁴ |
IPv6; IPv4 берёт запасной ttl⁴ |
— |
udp (с template, sni, quic-only) |
✓ | ✓ | ✓ | ✓ |
¹ Windows сообщает о ходе отправки счётчиками (SIO_TCP_INFO), а не состоянием очереди, поэтому ожидание может закончиться раньше. ² macOS не видит неотправленные байты: часть с малым числом хопов пишется, когда буфер отправки пуст, сама передача выводится, а не наблюдается. ³ macOS не может сделать так, чтобы повторная передача несла другие байты, чем первая. ⁴ На Windows, macOS и для IPv4 на Linux нет непривилегированного способа узнать TTL пакетов, полученных TCP-сокетом. auto-ttl без ttl — ошибка конфига на Windows и на Linux с ip-version: ipv4-only; на Linux с IPv6 он принимается, а соединение по IPv4 тогда завершится ошибкой при первой записи (в журнал пишется предупреждение). На Android здесь всё как на Linux. ⁵ Проверяется для каждого соединения: Android не даёт приложениям читать неотправленные байты сокета через SIOCOUTQNSD, поэтому они читаются из TCP_INFO, а для этого нужно ядро Linux 4.6 или новее. Конфиг принимается, в журнал пишется, что метод проверяется для каждого соединения; на ядре без этого поля соединение завершается ошибкой с названием метода до того, как что-либо отправлено. Ничто не заменяется паузой или другим методом.
Маршрутизация
Заголовок раздела «Маршрутизация»Исходящий выбирается как любой другой: правила и группы ссылаются на него по имени, глобальный DIRECT не меняется. Проверки здоровья и URL-тесты исходящего проходят через преобразование, поэтому группа fallback или url-test переключится на узел прокси, когда маршрут через desync перестанет работать, и вернётся, когда он заработает. Имена он разрешает через direct-nameserver, как DIRECT, подключается к адресу, проверенному IP-правилом, и отклоняет собственное соединение, вернувшееся через листенер Citrus. Пользователь серверного входящего не может через него обратиться к частным адресам и loopback, как и через DIRECT.
Значения TTL вроде 4 — примеры, а не значения, подходящие любой сети: поддельный пакет должен истечь после фильтрующего оборудования и до сервера. Поможет ли способ, зависит от сети; локальная проверка показывает только, что байты отправлены так, как настроено.
API контроллера
Заголовок раздела «API контроллера»GET /proxies показывает исходящий с "type": "Desync" и объектом desync: действующая стратегия strategy (static — заданные параметры) и параметры tcp с подставленными значениями по умолчанию (split-wait, split-wait-timeout, disorder, oob, random, fake). В fake поле last-ttl — число хопов, с которым ушла последняя подделка, и вывел ли его auto-ttl (null до первой подделки). С udp — его параметры и счётчики исходных и поддельных датаграмм, ошибок и адресатов. Счётчики показывают, что датаграммы отправлены, а не что они помогли.
