Skip to content

Hysteria2 — sing-box

sing-box's Hysteria2 implementation is the cleanest of the three cores: a single flat block on each side, polymorphic masquerade, and explicit port-hopping fields on the outbound.

Inbound

type: "hysteria2" inbound:

FieldTypeDefaultAllowed valuesDescription
up_mbpsint0<Mbps>Estimated uplink bandwidth in Mbps. The server uses this as a hint for congestion control.
down_mbpsint0<Mbps>Estimated downlink bandwidth in Mbps.
obfs*Hysteria2Obfs(disabled)Hysteria2ObfsSalamander obfuscation block. When set, both sides must match.
users[]Hysteria2User[][Hysteria2User]Accepted users.
ignore_client_bandwidthboolfalsetrue | falseDiscard the client's bandwidth advertisement and use the server's bandwidth settings unilaterally.
masquerade*Hysteria2Masquerade(disabled)Hysteria2MasqueradeHTTP-response masquerade for unauthenticated traffic. Accepts a string URL or a typed object.
brutal_debugboolfalsetrue | falseLog Brutal congestion-control internals.

Source: option/hysteria2.go:13-23 · pinned at v1.13.11 (553cfa1)

The struct embeds ListenOptions and InboundTLSOptionsContainer. A TLS configuration is required — Hysteria2 runs on QUIC and there is no plaintext mode.

obfs

FieldTypeDefaultAllowed valuesDescription
typestring(required)salamanderObfuscation type. Only `salamander` is currently defined.
passwordstring(required)<string>Obfuscation password (separate from the user password).

Source: option/hysteria2.go:25-28 · pinned at v1.13.11 (553cfa1)

users[]

FieldTypeDefaultAllowed valuesDescription
namestring(unset)<string>Display name used in stats and logs.
passwordstring(required)<string>User authentication password.

Source: option/hysteria2.go:30-33 · pinned at v1.13.11 (553cfa1)

masquerade

The masquerade field is polymorphic (option/hysteria2.go:44-95):

  • A plain string URL. Schemes:
    • file:///var/www — equivalent to { "type": "file", "directory": "/var/www" }.
    • https://upstream.example.com — equivalent to { "type": "proxy", "url": "..." }.
  • An object with a type field selecting one of three shapes:
FieldTypeDefaultAllowed valuesDescription
typestring(unset)file | proxy | stringSelects which sub-block is active.

Source: option/hysteria2.go:35-40 · pinned at v1.13.11 (553cfa1)

type: "file"

FieldTypeDefaultAllowed valuesDescription
directorystring(required)<dir path>Local directory served at the masquerade endpoint.

Source: option/hysteria2.go:97-99 · pinned at v1.13.11 (553cfa1)

type: "proxy"

FieldTypeDefaultAllowed valuesDescription
urlstring(required)<URL>Upstream URL the masquerade endpoint reverse-proxies to.
rewrite_hostboolfalsetrue | falseRewrite the Host header to match the upstream URL.

Source: option/hysteria2.go:101-104 · pinned at v1.13.11 (553cfa1)

type: "string"

FieldTypeDefaultAllowed valuesDescription
status_codeint200<int>HTTP status code returned.
headersbadoption.HTTPHeader{}{<header>: <value>}Extra response headers.
contentstring(required)<text>Response body.

Source: option/hysteria2.go:106-110 · pinned at v1.13.11 (553cfa1)

Outbound

type: "hysteria2" outbound:

FieldTypeDefaultAllowed valuesDescription
server_portsbadoption.Listable[string][]<range>Port-hopping list. Each entry is a port (e.g. `"20001"`) or a hyphenated range (e.g. `"20001-20100"`).
hop_intervalbadoption.Duration30s<duration>How often to switch to a new port. Accepts Go-style durations.
up_mbpsint0<Mbps>Estimated uplink bandwidth in Mbps.
down_mbpsint0<Mbps>Estimated downlink bandwidth in Mbps.
obfs*Hysteria2Obfs(disabled)Hysteria2ObfsSalamander obfuscation; must match the server.
passwordstring(required)<string>User auth password.
networkNetworkList(tcp+udp)tcp | udp | Restrict to TCP-only or UDP-only.
brutal_debugboolfalsetrue | falseLog Brutal CC internals on the client side.

Source: option/hysteria2.go:112-124 · pinned at v1.13.11 (553cfa1)

Embeds DialerOptions, ServerOptions (server, server_port), and OutboundTLSOptionsContainer (tlsrequired).

Examples

Inbound with port hopping not exposed (server side just listens on one port), Salamander obfs, and a file-masquerade:

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"
    }
  ]
}

Outbound with port hopping (20000-20100, switch every 30 seconds):

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" }
    }
  ]
}

Notes

  • Bandwidth values are plain integer Mbps here — no unit string. Xray and mihomo accept suffixed strings ("100mbps"), sing-box does not.
  • obfs.type only has one defined value today (salamander). Configs that omit obfs use the unobfuscated path.
  • masquerade accepts both the polymorphic typed object and a plain string URL — both are unmarshaled to the same internal representation (option/hysteria2.go:59-78).
  • ignore_client_bandwidth: true is the recommended setting for servers whose admin already knows the real bandwidth — it prevents a malicious client from understating its capacity to extract more from the server.

Cross-core notes

  • Xray-core supports Hysteria2 but splits config between settings and streamSettings.hysteriaSettings. See Hysteria2 — Xray-core.
  • mihomo uses a single-block outbound with up/down as strings (with unit suffixes like Xray). Port-hopping is ports + hop-interval. Users on the inbound are a map[string]string (username → password) rather than an object list. See Hysteria2 — mihomo.

Source: option/hysteria2.go:13-124 · v1.13.11 (553cfa1)

Core Tutorial by Argsment