Skip to content

Hysteria2 — sing-box ​

Реализация Hysteria2 в sing-box — самая аккуратная из трёх ядер: один плоский блок с каждой стороны, полиморфная маскировка и явные поля перескока портов на исходящей стороне.

Входящий ​

Входящий type: "hysteria2":

ПолеТипПо умолчаниюДопустимые значенияОписание
up_mbpsint0<Mbps>Оценка пропускной способности исходящего канала в Мбит/с. Сервер использует её как подсказку для управления перегрузкой.
down_mbpsint0<Mbps>Оценка пропускной способности входящего канала в Мбит/с.
obfs*Hysteria2Obfs(disabled)Hysteria2ObfsБлок обфускации (salamander или gecko). Если задан, настройки обеих сторон должны совпадать.
users[]Hysteria2User[][Hysteria2User]Принимаемые пользователи.
ignore_client_bandwidthboolfalsetrue | falseИгнорировать заявленную клиентом пропускную способность и односторонне использовать настройки пропускной способности сервера.
masquerade*Hysteria2Masquerade(disabled)Hysteria2MasqueradeМаскировка HTTP-ответом для неаутентифицированного трафика. Принимает строку URL или типизированный объект.
bbr_profilestringstandardconservative | standard | aggressiveПрофиль управления перегрузкой BBR; применяется всякий раз, когда выбран BBR.
brutal_debugboolfalsetrue | falseЖурналировать внутренности управления перегрузкой Brutal.
realm*Hysteria2InboundRealm(disabled)Hysteria2InboundRealmРегистрировать этот сервер в сервисе-посреднике Hysteria Realm для обхода NAT: сервер определяет свои публичные адреса через STUN, регистрирует их под realm_id и принимает клиентов через пробивание UDP — публично доступный адрес прослушивания не нужен.

Исходный код: option/hysteria2.go:17-30 · зафиксировано на v1.14.2 (af6e64c)

Структура встраивает ListenOptions, InboundTLSOptionsContainer и QUICOptions (см. «Поля QUIC» ниже). Конфигурация TLS обязательна — Hysteria2 работает поверх QUIC, и режима без шифрования нет.

obfs ​

ПолеТипПо умолчаниюДопустимые значенияОписание
typestring(required)salamander | geckoТип обфускации. gecko дополнительно принимает min_packet_size / max_packet_size.
passwordstring(required)<string>Пароль обфускации (отдельный от пароля пользователя).

Исходный код: option/hysteria2.go:64-68 · зафиксировано на v1.14.2 (af6e64c)

При type: "gecko" тот же объект также принимает:

ПолеТипПо умолчаниюДопустимые значенияОписание
min_packet_sizeint512<bytes>Минимальный размер пакета на проводе, в байтах. Только gecko.
max_packet_sizeint1200<bytes>Максимальный размер пакета на проводе, в байтах. Только gecko.

Исходный код: option/hysteria2.go:59-62 · зафиксировано на v1.14.2 (af6e64c)

users[] ​

ПолеТипПо умолчаниюДопустимые значенияОписание
namestring(unset)<string>Отображаемое имя, используемое в статистике и журналах.
passwordstring(required)<string>Пароль аутентификации пользователя.

Исходный код: option/hysteria2.go:116-119 · зафиксировано на v1.14.2 (af6e64c)

masquerade ​

Поле masquerade полиморфно (option/hysteria2.go:121-181):

  • Обычная строка URL. Схемы:
    • file:///var/www — эквивалент { "type": "file", "directory": "/var/www" }.
    • https://upstream.example.com — эквивалент { "type": "proxy", "url": "..." }.
  • Объект с полем type, выбирающим одну из трёх форм:
ПолеТипПо умолчаниюДопустимые значенияОписание
typestring(unset)file | proxy | stringВыбирает, какой из вложенных блоков активен.

Исходный код: option/hysteria2.go:121-126 · зафиксировано на v1.14.2 (af6e64c)

type: "file" ​

ПолеТипПо умолчаниюДопустимые значенияОписание
directorystring(required)<dir path>Локальный каталог, раздаваемый маскировочной конечной точкой.

Исходный код: option/hysteria2.go:195-197 · зафиксировано на v1.14.2 (af6e64c)

type: "proxy" ​

ПолеТипПо умолчаниюДопустимые значенияОписание
urlstring(required)<URL>Вышестоящий URL, на который маскировочная конечная точка выполняет обратное проксирование.
rewrite_hostboolfalsetrue | falseПереписывать заголовок Host в соответствии с вышестоящим URL.

Исходный код: option/hysteria2.go:199-202 · зафиксировано на v1.14.2 (af6e64c)

type: "string" ​

ПолеТипПо умолчаниюДопустимые значенияОписание
status_codeint200<int>Возвращаемый код состояния HTTP.
headersbadoption.HTTPHeader{}{<header>: <value>}Дополнительные заголовки ответа.
contentstring(required)<text>Тело ответа.

Исходный код: option/hysteria2.go:204-208 · зафиксировано на v1.14.2 (af6e64c)

Исходящий ​

Исходящий type: "hysteria2":

ПолеТипПо умолчаниюДопустимые значенияОписание
server_portsbadoption.Listable[string][]<range>Список для перескока портов. Каждый элемент — порт (например, "20001") или диапазон через дефис (например, "20001-20100").
hop_intervalbadoption.Duration30s<duration>Как часто переключаться на новый порт. Принимает длительности в стиле Go.
hop_interval_maxbadoption.Duration(unset)<duration>Верхняя граница случайного интервала перескока портов: каждый перескок ждёт случайное время между hop_interval и этим значением.
up_mbpsint0<Mbps>Оценка пропускной способности исходящего канала в Мбит/с.
down_mbpsint0<Mbps>Оценка пропускной способности входящего канала в Мбит/с.
obfs*Hysteria2Obfs(disabled)Hysteria2ObfsОбфускация (salamander или gecko); должна совпадать с настройками сервера.
passwordstring(required)<string>Пароль аутентификации пользователя.
networkNetworkList(tcp+udp)tcp | udp | Ограничение только TCP или только UDP.
bbr_profilestringstandardconservative | standard | aggressiveПрофиль управления перегрузкой BBR; применяется всякий раз, когда выбран BBR.
brutal_debugboolfalsetrue | falseЖурналировать внутренности Brutal CC на стороне клиента.
disable_chrome_parrotboolfalsetrue | falseОтключить имитацию QUIC-рукопожатия Chrome, которая включена по умолчанию. Имитация применяет QUIC-параметры Chrome (idle_timeout фиксирован на 30 с; max_concurrent_streams и initial_packet_size берутся из Chrome; окна приёма начинаются с начальных значений Chrome) и не проходит рукопожатие с серверами на сертификатах Ed25519.
realm*Hysteria2Realm(disabled)Hysteria2RealmПодключаться к серверу через Hysteria Realm: запросить у realm адреса, зарегистрированные под realm_id, пробить NAT и затем выполнить обычное QUIC-рукопожатие. Конфликтует с server, server_port и server_ports.

Исходный код: option/hysteria2.go:210-227 · зафиксировано на v1.14.2 (af6e64c)

Встраивает DialerOptions, ServerOptions (server, server_port), OutboundTLSOptionsContainer (tls — обязателен) и QUICOptions.

Realm (обход NAT) ​

Сервер за NAT задаёт realm на своём входящем и регистрируется в сервисе Hysteria Realm; клиенты задают realm на исходящем (вместо server), чтобы найти его. Обе стороны используют общую форму:

ПолеТипПо умолчаниюДопустимые значенияОписание
server_urlstring(required)<URL>URL сервиса-посредника realm.
tokenstring(unset)<string>Bearer-токен; должен совпадать с одним из users[].token на realm.
realm_idstring(required)<id>Идентификатор слота. Сервер регистрируется под ним, клиенты должны использовать то же значение; 1–64 символа, соответствующих ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$.
stun_serversbadoption.Listable[string](required)<host[:port]> | …STUN-серверы для определения публичных адресов. На исходящем доменные имена разрешаются через domain_resolver из полей подключения.
ip_versionint(both)4 | 6Ограничить STUN, пробивание NAT и итоговый QUIC-путь одной версией IP.
port_mapping*Hysteria2RealmPortMapping(disabled)Hysteria2RealmPortMappingПоддерживать проброс UDP-порта на локальном шлюзе через UPnP или NAT-PMP; ошибки не фатальны. Требует IPv4.
http_client*HTTPClientOptions(default)<tag> | HTTPClientOptionsHTTP-клиент для обращения к realm (встроенный объект или тег элемента http_clients).

Исходный код: option/hysteria2.go:32-40 · зафиксировано на v1.14.2 (af6e64c)

Форма для входящего добавляет:

ПолеТипПо умолчаниюДопустимые значенияОписание
stun_domain_resolver*DomainResolveOptions(default resolver)<dns server tag> | DomainResolveOptionsТолько для входящего: резолвер для доменных имён STUN-серверов (тот же формат, что у domain_resolver).

Исходный код: option/hysteria2.go:54-57 · зафиксировано на v1.14.2 (af6e64c)

port_mapping:

ПолеТипПо умолчаниюДопустимые значенияОписание
enabledboolfalsetrue | falseВключить проброс порта.
timeoutbadoption.Duration10s<duration>Тайм-аут обнаружения шлюза и операций проброса.
lifetimebadoption.Duration10m<duration>Срок аренды проброса; продлевается на половине срока.

Исходный код: option/hysteria2.go:48-52 · зафиксировано на v1.14.2 (af6e64c)

Поля QUIC ​

Обе стороны встраивают параметры QUIC, общие с Hysteria, TUIC и HTTP/3-клиентами (QUICOptions, который в свою очередь встраивает HTTP2Options). При включённой имитации Chrome (по умолчанию на клиенте) idle_timeout фиксирован на 30 секундах, а max_concurrent_streams / initial_packet_size заменяются значениями Chrome.

ПолеТипПо умолчаниюДопустимые значенияОписание
initial_packet_sizeint(QUIC default)<bytes>Начальный размер QUIC-пакета.
disable_path_mtu_discoveryboolfalsetrue | falseОтключить обнаружение MTU пути в QUIC.

Исходный код: option/http.go:22-26 · зафиксировано на v1.14.2 (af6e64c)

ПолеТипПо умолчаниюДопустимые значенияОписание
idle_timeoutbadoption.Duration(default)<duration>Тайм-аут простоя соединения.
keep_alive_periodbadoption.Duration(default)<duration>Период keep-alive.
stream_receive_window*byteformats.MemoryBytes(default)<size>Окно приёма управления потоком на уровне потока, в формате размера памяти (например, 64 MB).
connection_receive_window*byteformats.MemoryBytes(default)<size>Окно приёма управления потоком на уровне соединения, в формате размера памяти.
max_concurrent_streamsint(default)<int>Максимум одновременных потоков на соединение.

Исходный код: option/http.go:14-20 · зафиксировано на v1.14.2 (af6e64c)

Примеры ​

Входящий без перескока портов (серверная сторона просто слушает один порт), с обфускацией Salamander и файловой маскировкой:

json
{
  "inbounds": [
    {
      "type": "hysteria2",
      "tag": "hy2-in",
      "listen": "::",
      "listen_port": 443,
      "users": [
        { "name": "alice", "password": "<password>" }
      ],
      "obfs": { "type": "salamander", "password": "<obfs>" },
      "tls": {
        "enabled": true,
        "alpn": ["h3"],
        "certificate_path": "/etc/ssl/cert.pem",
        "key_path": "/etc/ssl/key.pem"
      },
      "masquerade": "file:///var/www"
    }
  ]
}

Исходящий с перескоком портов (20000-20100, смена каждые 30 секунд):

json
{
  "outbounds": [
    {
      "type": "hysteria2",
      "tag": "hy2-out",
      "server": "example.com",
      "server_port": 443,
      "server_ports": ["20000-20100"],
      "hop_interval": "30s",
      "password": "<password>",
      "obfs": { "type": "salamander", "password": "<obfs>" },
      "up_mbps": 100,
      "down_mbps": 300,
      "tls": { "enabled": true, "server_name": "example.com" }
    }
  ]
}

Примечания ​

  • Значения пропускной способности здесь — обычные целые Мбит/с, без строк с единицами. Xray и mihomo принимают строки с суффиксами ("100mbps"), sing-box — нет.
  • obfs.type — salamander или gecko. Конфигурации без obfs используют путь без обфускации.
  • Клиент по умолчанию имитирует QUIC-рукопожатие Chrome. Chrome не объявляет поддержку Ed25519, поэтому рукопожатие с сервером на сертификате Ed25519 не проходит — используйте сертификат ECDSA или RSA либо задайте на клиенте disable_chrome_parrot: true.
  • Если на исходящем up_mbps / down_mbps не заданы, вместо Brutal используется BBR (настраивается через bbr_profile).
  • masquerade принимает как полиморфный типизированный объект, так и обычную строку URL — обе формы десериализуются в одно и то же внутреннее представление (option/hysteria2.go:145-164).
  • ignore_client_bandwidth: true — рекомендуемая настройка для серверов, чей администратор уже знает реальную пропускную способность: она не даёт злонамеренному клиенту занизить свою ёмкость, чтобы выжать из сервера больше.

Сравнение с другими ядрами ​

  • Xray-core поддерживает Hysteria2, но делит конфигурацию между settings и streamSettings.hysteriaSettings, а полоса пропускания, управление перегрузкой и перескок портов задаются в streamSettings.finalmask. См. Hysteria2 — Xray-core.
  • mihomo использует исходящий одним блоком с up/down в виде строк (с суффиксами единиц, как в Xray). Перескок портов — это ports + hop-interval. Пользователи на входящей стороне — это map[string]string (имя пользователя → пароль), а не список объектов. См. Hysteria2 — mihomo.

Исходный код: option/hysteria2.go:17-227 · v1.14.2 (af6e64c)

Core Tutorial от Argsment