Hysteria2 — sing-box
Реализация Hysteria2 в sing-box — самая аккуратная из трёх ядер: один плоский блок с каждой стороны, полиморфная маскировка и явные поля перескока портов на исходящей стороне.
Входящий
Входящий type: "hysteria2":
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
up_mbps | int | 0 | <Mbps> | Оценка пропускной способности исходящего канала в Мбит/с. Сервер использует её как подсказку для управления перегрузкой. |
down_mbps | int | 0 | <Mbps> | Оценка пропускной способности входящего канала в Мбит/с. |
obfs | *Hysteria2Obfs | (disabled) | Hysteria2Obfs | Блок обфускации (salamander или gecko). Если задан, настройки обеих сторон должны совпадать. |
users | []Hysteria2User | [] | [Hysteria2User] | Принимаемые пользователи. |
ignore_client_bandwidth | bool | false | true | false | Игнорировать заявленную клиентом пропускную способность и односторонне использовать настройки пропускной способности сервера. |
masquerade | *Hysteria2Masquerade | (disabled) | Hysteria2Masquerade | Маскировка HTTP-ответом для неаутентифицированного трафика. Принимает строку URL или типизированный объект. |
bbr_profile | string | standard | conservative | standard | aggressive | Профиль управления перегрузкой BBR; применяется всякий раз, когда выбран BBR. |
brutal_debug | bool | false | true | 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
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
type | string | (required) | salamander | gecko | Тип обфускации. gecko дополнительно принимает min_packet_size / max_packet_size. |
password | string | (required) | <string> | Пароль обфускации (отдельный от пароля пользователя). |
Исходный код: option/hysteria2.go:64-68 · зафиксировано на v1.14.2 (af6e64c)
При type: "gecko" тот же объект также принимает:
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
min_packet_size | int | 512 | <bytes> | Минимальный размер пакета на проводе, в байтах. Только gecko. |
max_packet_size | int | 1200 | <bytes> | Максимальный размер пакета на проводе, в байтах. Только gecko. |
Исходный код: option/hysteria2.go:59-62 · зафиксировано на v1.14.2 (af6e64c)
users[]
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
name | string | (unset) | <string> | Отображаемое имя, используемое в статистике и журналах. |
password | string | (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, выбирающим одну из трёх форм:
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
type | string | (unset) | file | proxy | string | Выбирает, какой из вложенных блоков активен. |
Исходный код: option/hysteria2.go:121-126 · зафиксировано на v1.14.2 (af6e64c)
type: "file"
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
directory | string | (required) | <dir path> | Локальный каталог, раздаваемый маскировочной конечной точкой. |
Исходный код: option/hysteria2.go:195-197 · зафиксировано на v1.14.2 (af6e64c)
type: "proxy"
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
url | string | (required) | <URL> | Вышестоящий URL, на который маскировочная конечная точка выполняет обратное проксирование. |
rewrite_host | bool | false | true | false | Переписывать заголовок Host в соответствии с вышестоящим URL. |
Исходный код: option/hysteria2.go:199-202 · зафиксировано на v1.14.2 (af6e64c)
type: "string"
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
status_code | int | 200 | <int> | Возвращаемый код состояния HTTP. |
headers | badoption.HTTPHeader | {} | {<header>: <value>} | Дополнительные заголовки ответа. |
content | string | (required) | <text> | Тело ответа. |
Исходный код: option/hysteria2.go:204-208 · зафиксировано на v1.14.2 (af6e64c)
Исходящий
Исходящий type: "hysteria2":
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
server_ports | badoption.Listable[string] | [] | <range> | Список для перескока портов. Каждый элемент — порт (например, "20001") или диапазон через дефис (например, "20001-20100"). |
hop_interval | badoption.Duration | 30s | <duration> | Как часто переключаться на новый порт. Принимает длительности в стиле Go. |
hop_interval_max | badoption.Duration | (unset) | <duration> | Верхняя граница случайного интервала перескока портов: каждый перескок ждёт случайное время между hop_interval и этим значением. |
up_mbps | int | 0 | <Mbps> | Оценка пропускной способности исходящего канала в Мбит/с. |
down_mbps | int | 0 | <Mbps> | Оценка пропускной способности входящего канала в Мбит/с. |
obfs | *Hysteria2Obfs | (disabled) | Hysteria2Obfs | Обфускация (salamander или gecko); должна совпадать с настройками сервера. |
password | string | (required) | <string> | Пароль аутентификации пользователя. |
network | NetworkList | (tcp+udp) | tcp | udp | | Ограничение только TCP или только UDP. |
bbr_profile | string | standard | conservative | standard | aggressive | Профиль управления перегрузкой BBR; применяется всякий раз, когда выбран BBR. |
brutal_debug | bool | false | true | false | Журналировать внутренности Brutal CC на стороне клиента. |
disable_chrome_parrot | bool | false | true | 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_url | string | (required) | <URL> | URL сервиса-посредника realm. |
token | string | (unset) | <string> | Bearer-токен; должен совпадать с одним из users[].token на realm. |
realm_id | string | (required) | <id> | Идентификатор слота. Сервер регистрируется под ним, клиенты должны использовать то же значение; 1–64 символа, соответствующих ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$. |
stun_servers | badoption.Listable[string] | (required) | <host[:port]> | … | STUN-серверы для определения публичных адресов. На исходящем доменные имена разрешаются через domain_resolver из полей подключения. |
ip_version | int | (both) | 4 | 6 | Ограничить STUN, пробивание NAT и итоговый QUIC-путь одной версией IP. |
port_mapping | *Hysteria2RealmPortMapping | (disabled) | Hysteria2RealmPortMapping | Поддерживать проброс UDP-порта на локальном шлюзе через UPnP или NAT-PMP; ошибки не фатальны. Требует IPv4. |
http_client | *HTTPClientOptions | (default) | <tag> | HTTPClientOptions | HTTP-клиент для обращения к 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:
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
enabled | bool | false | true | false | Включить проброс порта. |
timeout | badoption.Duration | 10s | <duration> | Тайм-аут обнаружения шлюза и операций проброса. |
lifetime | badoption.Duration | 10m | <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_size | int | (QUIC default) | <bytes> | Начальный размер QUIC-пакета. |
disable_path_mtu_discovery | bool | false | true | false | Отключить обнаружение MTU пути в QUIC. |
Исходный код: option/http.go:22-26 · зафиксировано на v1.14.2 (af6e64c)
| Поле | Тип | По умолчанию | Допустимые значения | Описание |
|---|---|---|---|---|
idle_timeout | badoption.Duration | (default) | <duration> | Тайм-аут простоя соединения. |
keep_alive_period | badoption.Duration | (default) | <duration> | Период keep-alive. |
stream_receive_window | *byteformats.MemoryBytes | (default) | <size> | Окно приёма управления потоком на уровне потока, в формате размера памяти (например, 64 MB). |
connection_receive_window | *byteformats.MemoryBytes | (default) | <size> | Окно приёма управления потоком на уровне соединения, в формате размера памяти. |
max_concurrent_streams | int | (default) | <int> | Максимум одновременных потоков на соединение. |
Исходный код: option/http.go:14-20 · зафиксировано на v1.14.2 (af6e64c)
Примеры
Входящий без перескока портов (серверная сторона просто слушает один порт), с обфускацией Salamander и файловой маскировкой:
{
"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 секунд):
{
"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)
