🦎 Hysteria 2 — обфускация и port hopping

О чём заметка

Что делать, если провайдер мешает Hysteria: два независимых приёма — обфускация (шифрует пакеты так, что они перестают выглядеть как QUIC/HTTP/3) и port hopping (постоянная смена порта, чтобы обойти блокировку/троттлинг конкретного UDP-порта). Базовые конфиги — в заметках сервер и клиент. Обзор протокола — тут.

TL;DR

  • Обфускация нужна, когда сеть блокирует именно QUIC/HTTP/3 (но не UDP вообще). Она превращает пакеты в «случайный шум», убирая узнаваемый почерк QUIC. Реализации — Salamander и экспериментальный Gecko.
  • Пароль обфускации должен совпадать на сервере и клиенте. Неверный пароль = таймаут подключения, как будто сервер выключен.
  • Port hopping нужен, когда провайдер блокирует или троттлит долгие UDP-сессии на конкретном порту. Клиент постоянно случайно меняет порт из заданного диапазона.
  • Включение обфускации ломает совместимость со стандартным QUIC — сервер перестаёт быть валидным HTTP/3-сервером, masquerade под настоящий сайт больше не работает. Это осознанный размен.
  • Оба приёма независимы: можно включить только один, оба или ни одного.

Когда что применять

Сначала разберитесь, что именно ломает провайдер — от этого зависит выбор приёма:

  • Всё работает, но иногда рвётся / троттлится через время — вероятно, режут долгие UDP-сессии на порту. → Port hopping.
  • Соединение вообще не поднимается, при этом другой UDP-трафик ходит — вероятно, DPI распознаёт и блокирует именно QUIC/HTTP/3. → Обфускация.
  • UDP зарезан полностью (любой) — ни один приём Hysteria не поможет, protocol работает поверх UDP. Держите про запас TCP-решение вроде VLESS+TLS.

Обфускация — маскировка от DPI

По умолчанию Hysteria имитирует HTTP/3. Но если сеть точечно блокирует QUIC/HTTP/3-трафик (при этом обычный UDP пропускает), обфускация помогает обойти это: она перемешивает пакеты так, что они теряют узнаваемый почерк протокола.

Доступны две реализации, обе требуют пароль, одинаковый на клиенте и сервере:

  • Salamander — превращает каждый пакет в набор псевдослучайных байт без видимого паттерна.
  • Gecko (экспериментальный) — надстройка над Salamander: дополнительно дробит пакеты QUIC-рукопожатия на куски случайного размера со случайным паддингом, чтобы усложнить их обнаружение по размеру.

На сервере (серверный конфиг), Salamander:

obfs:
  type: salamander
  salamander:
    password: cry_me_a_r1ver

На клиенте (клиентский конфиг) — ровно та же секция с тем же паролем.

Вариант Gecko (тоже симметрично на обеих сторонах):

obfs:
  type: gecko
  gecko:
    password: cry_me_a_r1ver
    minPacketSize: 512
    maxPacketSize: 1200

minPacketSize/maxPacketSize — границы размера дробящихся датаграмм рукопожатия (по умолчанию 512 и 1200 байт; maxPacketSize должен быть >= minPacketSize и <= 2048).

Обфускация ломает маскировку под HTTP/3

Включив obfs, вы делаете сервер несовместимым со стандартными QUIC-соединениями — он перестаёт быть валидным HTTP/3-сервером, и masquerade под настоящий сайт уже не сработает (браузер не откроет ваш «сайт»). Это размен: вы прячете почерк QUIC от DPI ценой того, что сервер больше не выглядит как обычный веб-сервер. Включайте обфускацию, только если DPI реально блокирует QUIC, — иначе вы теряете полезную маскировку без причины.

Неверный пароль обфускации = «сервер как будто выключен»

Если пароль обфускации на клиенте и сервере не совпадает, соединение просто уйдёт в таймаут — точно так же, как если бы сервер не был запущен. Никакой явной ошибки «неверный пароль» не будет. Поэтому при проблемах с подключением после включения obfs первым делом сверьте пароль на обеих сторонах.

Port hopping — смена порта

Некоторые провайдеры (изначально приём появился как обход ограничений в Китае) блокируют или троттлят долгие UDP-соединения, но ограничение часто действует только на конкретный порт. Port hopping обходит это: клиент постоянно перескакивает между портами из заданного диапазона, не давая привязать блокировку к одному порту. Для верхних уровней (ваших приложений) это прозрачно — данные не теряются и соединение не рвётся.

На клиенте — мульти-порт адрес

В поле server вместо одного порта укажите список/диапазон:

server: example.com:20000-50000

Форматы адреса: example.com:1234,5678,9012 (отдельные порты), example.com:20000-50000 (диапазон), либо комбинация example.com:1234,5000-6000,7044,8000-9000. Число портов не ограничено.

Интервал переключения задаётся в секции transport:

transport:
  udp:
    hopInterval: 30s

hopInterval — фиксированный интервал (по умолчанию 30s, минимум 5s). Для менее предсказуемого поведения можно задать случайный интервал через minHopInterval/maxHopInterval (тоже минимум 5s) — но одновременно с hopInterval их использовать нельзя.

На сервере — диапазон в listen (Linux)

На Linux серверу достаточно указать диапазон прямо в listen:

listen: :20000-50000

Сервер слушает первый порт диапазона и автоматически настраивает правила фаервола (nftables или iptables), перенаправляя трафик со всех остальных портов на первый. При остановке сервера правила автоматически убираются.

Серверный диапазон портов требует прав и Linux

Автоматический диапазон в listen работает только на Linux и требует наличия nft (nftables) или iptables/ip6tables. Серверу нужны привилегии для правки фаервола — запуск от root или с capability CAP_NET_ADMIN. Если ставите через Docker, для port hopping нужна cap_add: NET_ADMIN.

Если автоматический способ не подходит, диапазон можно пробросить вручную через DNAT (iptables/nftables) на порт, который слушает сервер. Готовые правила для iptables и nftables, а также подводные камни (постоянство правил после ребута, фаервол хостера) вынесены в отдельную заметку — Port hopping вручную (DNAT).

📚 См. также


🤖 Эти статьи открыты — можно обучать на них ИИ

При желании вы можете натренировать ИИ на наших статьях. Исходное форматирование и скачивание всего репозитория одним zip-архивом доступны в Forgejo: исходник этой заметки · весь репозиторий.