Hysteria2 — mihomo
mihomo speaks Hysteria2 on both sides. The outbound carries explicit port-hopping fields and a generous set of QUIC-go flow-control knobs. The inbound's user table is a flat map — one username/password pair per entry.
Outbound
Entry under proxies: with type: hysteria2. Embeds BasicOption (common outbound fields: interface-name, routing-mark, …).
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
name | string | (required) | <string> | Unique proxy name. |
server | string | (required) | <host> | Upstream server hostname or IP. |
port | int | (unset) | <port> | Single server port. Omit when `ports` is set. |
ports | string | (unset) | <port-list> | Port-hopping list. Accepts a comma-separated mix of single ports and ranges, e.g. `"20000,20002-20100"`. Mutually beneficial with `hop-interval`. |
hop-interval | string | 30 | <seconds string> | <duration> | Time between port-hops. Plain numeric string (`"30"`) is treated as seconds; Go-style duration (`"30s"`) is also accepted. Minimum is 5 (`adapter/outbound/hysteria2.go:25`). |
up | string | (unset) | <bandwidth> | Uplink bandwidth. String with unit, e.g. `"100 Mbps"`, `"500 kbps"`, `"1 Gbps"`. |
down | string | (unset) | <bandwidth> | Downlink bandwidth, same format. |
password | string | (unset) | <string> | User auth password. Optional only if the server allows unauthenticated peers. |
obfs | string | (disabled) | salamander | Obfuscation type. Currently only `salamander` is meaningful. |
obfs-password | string | (unset) | <string> | Obfuscation password, separate from the user password. |
obfs-min-packet-size | int | 0 | <bytes> | Minimum random padding size for Salamander obfuscation. Only meaningful with `obfs: salamander`. |
obfs-max-packet-size | int | 0 | <bytes> | Maximum random padding size for Salamander obfuscation. |
sni | string | (server) | <SNI> | TLS Server Name Indication. Defaults to `server`. |
ech-opts | ECHOptions | (disabled) | ECHOptions | Encrypted Client Hello configuration. |
skip-cert-verify | bool | false | true | false | Disable TLS verification (test only). |
fingerprint | string | (unset) | <SHA256 hex> | Pin the server's TLS certificate fingerprint. |
certificate | string | (unset) | <PEM file path> | Client certificate (mTLS). |
private-key | string | (unset) | <key file path> | Private key for `certificate`. |
alpn | []string | [h3] | h3 | ALPN list. Hysteria2 typically uses `h3`. |
cwnd | int | 0 | <int> | Initial QUIC congestion window override. |
bbr-profile | string | (unset) | default | aggressive | Tuning profile for the bundled Brutal/BBR variant. |
udp-mtu | int | 1200 | <bytes> | MTU used for fragmenting UDP payloads inside the QUIC datagram. |
realm-opts | Hysteria2RealmOption | (disabled) | Hysteria2RealmOption | Connect through a Hysteria2 *realm* — a multi-tenant server reached via a control endpoint. See the realm-opts table below. |
initial-stream-receive-window | uint64 | 0 (quic-go default) | <bytes> | Initial flow-control window per stream. |
max-stream-receive-window | uint64 | 0 (quic-go default) | <bytes> | Maximum flow-control window per stream. |
initial-connection-receive-window | uint64 | 0 (quic-go default) | <bytes> | Initial flow-control window for the whole connection. |
max-connection-receive-window | uint64 | 0 (quic-go default) | <bytes> | Maximum flow-control window for the whole connection. |
Source: adapter/outbound/hysteria2.go:39-71 · pinned at v1.19.27 (5184081)
Inbound
Entry under listeners: with type: hysteria2. Embeds BaseOption (listen, port).
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
users | map[string]string | {} | {<username>: <password>} | User table — map of username to password. Empty allows unauthenticated peers. |
obfs | string | (disabled) | salamander | Salamander obfuscation type. |
obfs-password | string | (unset) | <string> | Obfuscation password. |
obfs-min-packet-size | int | 0 | <bytes> | Minimum random padding size for Salamander obfuscation. Only meaningful with `obfs: salamander`. |
obfs-max-packet-size | int | 0 | <bytes> | Maximum random padding size for Salamander obfuscation. |
certificate | string | (required) | <PEM file path> | TLS server certificate. Required for inbound. |
private-key | string | (required) | <key file path> | TLS private key. |
client-auth-type | string | (none) | no-client-cert | request-client-cert | require-any-client-cert | verify-client-cert-if-given | require-and-verify-client-cert | Mutual-TLS client-auth mode. |
client-auth-cert | string | (unset) | <PEM file path> | CA bundle accepted as client roots. |
ech-key | string | (unset) | <ECH config> | Encrypted Client Hello material. |
max-idle-time | int | 0 | <seconds> | Idle timeout on the listener side. 0 keeps the QUIC default. |
alpn | []string | [h3] | h3 | ALPN list offered during the TLS handshake. |
up | string | (unset) | <bandwidth> | Uplink bandwidth (string with unit). |
down | string | (unset) | <bandwidth> | Downlink bandwidth. |
ignore-client-bandwidth | bool | false | true | false | Discard the client's bandwidth advertisement and impose the server's settings. |
masquerade | string | (unset) | <URL> | Masquerade target — a string URL (`file:///path` or `https://upstream/`). |
cwnd | int | 0 | <int> | Initial QUIC congestion window. |
bbr-profile | string | (unset) | default | aggressive | Brutal/BBR tuning profile. |
udp-mtu | int | 1200 | <bytes> | UDP datagram fragmentation MTU. |
mux-option | MuxOption | (disabled) | MuxOption | sing-style multiplex settings. |
realm-opts | Hysteria2RealmOption | (disabled) | Hysteria2RealmOption | Connect through a Hysteria2 *realm* — a multi-tenant server reached via a control endpoint. See the realm-opts table below. |
initial-stream-receive-window | uint64 | 0 (quic-go default) | <bytes> | Initial per-stream flow window. |
max-stream-receive-window | uint64 | 0 (quic-go default) | <bytes> | Maximum per-stream flow window. |
initial-connection-receive-window | uint64 | 0 (quic-go default) | <bytes> | Initial connection flow window. |
max-connection-receive-window | uint64 | 0 (quic-go default) | <bytes> | Maximum connection flow window. |
Source: listener/inbound/hysteria2.go:12-42 · pinned at v1.19.27 (5184081)
realm-opts
Both the outbound and inbound realm-opts blocks share the same shape. On an outbound, they point a proxy at a Hysteria2 realm — a tenant hosted on a multi-realm server — by way of a control endpoint that hands back the actual connection details. Realm mode is a newer, advanced feature; leave it disabled unless you are connecting to a realm server.
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
enable | bool | false | true | false | Enable realm mode for this proxy. |
server-url | string | (unset) | <URL> | URL of the realm control server used to obtain realm connection details. |
token | string | (unset) | <string> | Auth token presented to the realm control server. |
realm-id | string | (unset) | <string> | Identifier of the realm to join. |
stun-servers | []string | (unset) | <host:port list> | STUN servers used for realm NAT traversal. |
sni | string | (unset) | <SNI> | TLS SNI for the control-server connection. |
skip-cert-verify | bool | false | true | false | Skip TLS verification toward the control server (testing only). |
fingerprint | string | (unset) | <SHA256 hex> | Pin the control server's TLS certificate fingerprint. |
certificate | string | (unset) | <PEM file path> | Client certificate (mTLS) toward the control server. |
private-key | string | (unset) | <key file path> | Private key for `certificate`. |
alpn | []string | (unset) | <string list> | ALPN for the control-server connection. |
Source: adapter/outbound/hysteria2.go:73-87 · pinned at v1.19.27 (5184081)
Examples
Outbound — single port, salamander obfs, 100/300 Mbps:
proxies:
- name: hy2-plain
type: hysteria2
server: example.com
port: 443
password: <password>
obfs: salamander
obfs-password: <obfs>
sni: example.com
up: 100 Mbps
down: 300 Mbps
alpn: [h3]Outbound — port-hopping across 20000-20100:
proxies:
- name: hy2-hop
type: hysteria2
server: example.com
ports: 20000-20100
hop-interval: 30s
password: <password>
obfs: salamander
obfs-password: <obfs>
sni: example.com
up: 200 Mbps
down: 1 Gbps
alpn: [h3]Outbound connecting through a realm via a control server:
proxies:
- name: hy2-realm
type: hysteria2
server: example.com
port: 443
password: <password>
sni: example.com
alpn: [h3]
realm-opts:
enable: true
server-url: https://realm.example.com/control
token: <realm-token>
realm-id: team-a
stun-servers:
- stun.example.com:3478Inbound with two users and an HTTP-file masquerade:
listeners:
- name: hy2-in
type: hysteria2
listen: 0.0.0.0
port: 443
users:
alice: <alice-password>
bob: <bob-password>
obfs: salamander
obfs-password: <obfs>
certificate: /etc/mihomo/server.crt
private-key: /etc/mihomo/server.key
up: 500 Mbps
down: 1 Gbps
masquerade: file:///var/www
alpn: [h3]Notes
portsaccepts a mix of single ports and ranges separated by commas, e.g."20000,20002-20100,30000".portandportsare mutually exclusive — pick one. Whenportsis set, mihomo dials a fresh randomly-selected member everyhop-interval.hop-intervalminimum is 5 seconds (adapter/outbound/hysteria2.go:25) — values below 5 are clamped up.- The bandwidth values accept unit suffixes (
b,kbps,Mbps,Gbps,Tbps) with a space between the number and the unit —"100 Mbps". The strings are parsed by mihomo'stools.StringToBpshelper. obfs-min-packet-sizeandobfs-max-packet-sizeonly apply withobfs: salamander. They set the random-padding bounds for the Salamander obfuscator; with any other (or no)obfsthey are ignored.- mihomo's inbound
usersis a YAML mapping, not an object list. The key is the username and the value is the password, e.g.users: { alice: pw1, bob: pw2 }. To allow anonymous clients, leave the map empty. - The four
*-receive-windowfields are direct knobs for the bundled quic-go stack. Most users should leave them at0(default). Increase the connection-level windows to improve throughput over high-BDP links.
Cross-core notes
- Xray-core splits the config across
settings(version/clients) andstreamSettings.hysteriaSettings(auth/bandwidth/masquerade). See Hysteria2 — Xray-core. - sing-box keeps the config in a single block but uses plain integer Mbps for bandwidth (no unit suffix) and offers a polymorphic
masqueradevalue (string URL or typed object). See Hysteria2 — sing-box. - mihomo can also host realms — see Hysteria2 realm listener.
Source: adapter/outbound/hysteria2.go:39-87 · v1.19.27 (5184081)
