TUIC — sing-box
sing-box implements TUIC v5 — the modern, UUID+password form. The historic v4 "token" form is not supported. TUIC always runs over QUIC, so the embedded tls block is required.
Inbound
type: "tuic" inbound:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
users | []TUICUser | [] | [TUICUser] | Accepted users. Each carries a UUID + password pair. |
congestion_control | string | cubic | cubic | new_reno | bbr | QUIC congestion-control algorithm. Setting it here only changes the server-side outgoing direction; clients pick their own. |
auth_timeout | badoption.Duration | 3s | <duration> | How long to wait for the client to complete the authentication frame before closing the QUIC connection. |
zero_rtt_handshake | bool | false | true | false | Accept 0-RTT TLS handshakes. Enables slightly faster connect at the cost of replay-attack resistance for the first 0-RTT-payload window. |
heartbeat | badoption.Duration | 10s | <duration> | Interval between QUIC PING frames the server sends to keep NAT mappings alive. |
Source: option/tuic.go:5-13 · pinned at v1.13.11 (553cfa1)
The struct embeds ListenOptions and InboundTLSOptionsContainer. A TLS configuration is required.
users[]
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
name | string | (unset) | <string> | Display name used in stats and logs. |
uuid | string | (required) | <UUID> | Client UUID. |
password | string | (required) | <string> | Client password. |
Source: option/tuic.go:15-19 · pinned at v1.13.11 (553cfa1)
Outbound
type: "tuic" outbound:
| Field | Type | Default | Allowed values | Description |
|---|---|---|---|---|
uuid | string | (required) | <UUID> | User UUID accepted by the server. |
password | string | (required) | <string> | User password. |
congestion_control | string | cubic | cubic | new_reno | bbr | QUIC congestion-control algorithm for client-to-server direction. |
udp_relay_mode | string | native | native | quic | How UDP packets are tunneled. `native` uses QUIC datagrams; `quic` wraps each UDP packet in a dedicated QUIC stream. `native` is faster; `quic` survives middleboxes that drop QUIC datagrams. |
udp_over_stream | bool | false | true | false | Use the UDP-over-stream framing introduced for TUIC clients that talk to QUIC stacks without datagram support. Negotiated; both sides must enable it. |
zero_rtt_handshake | bool | false | true | false | Use 0-RTT TLS handshake on reconnect. |
heartbeat | badoption.Duration | 10s | <duration> | QUIC PING interval. |
network | NetworkList | (tcp+udp) | tcp | udp | | Restrict to TCP-only or UDP-only. |
Source: option/tuic.go:21-33 · pinned at v1.13.11 (553cfa1)
Embeds DialerOptions, ServerOptions, and OutboundTLSOptionsContainer.
Examples
Inbound:
json
{
"inbounds": [
{
"type": "tuic",
"tag": "tuic-in",
"listen": "::",
"listen_port": 443,
"users": [
{ "name": "alice", "uuid": "a3482e88-686a-4a58-8126-99c9df64b7bf", "password": "<password>" }
],
"congestion_control": "bbr",
"auth_timeout": "3s",
"heartbeat": "10s",
"tls": {
"enabled": true,
"alpn": ["h3"],
"certificate_path": "/etc/ssl/cert.pem",
"key_path": "/etc/ssl/key.pem"
}
}
]
}Outbound:
json
{
"outbounds": [
{
"type": "tuic",
"tag": "tuic-out",
"server": "example.com",
"server_port": 443,
"uuid": "a3482e88-686a-4a58-8126-99c9df64b7bf",
"password": "<password>",
"congestion_control": "bbr",
"udp_relay_mode": "native",
"zero_rtt_handshake": false,
"heartbeat": "10s",
"tls": { "enabled": true, "server_name": "example.com", "alpn": ["h3"] }
}
]
}Notes
udp_relay_mode: nativeis the recommended default. Switch toquiconly if you are running across a middlebox that DPI-drops QUIC datagrams.zero_rtt_handshake: trueenables 0-RTT on reconnect. The first connection still does a full handshake. The optimization is most visible on mobile networks that frequently re-resolve / reconnect.auth_timeoutis enforced on the server. If the inbound sees no auth frame within this window, the QUIC connection is closed silently.udp_over_streamis a compatibility knob — there is no TUIC server spec deviation involved; both sides simply have to agree.
Cross-core notes
- Xray-core does not support TUIC. See TUIC — Xray-core.
- mihomo uses field names in
kebab-case(congestion-controller,udp-relay-mode), supports the oldertokenform for compatibility, and exposes more QUIC tuning knobs (window sizes, MTU discovery, BBR profile). It also has a unique top-leveltuic-serverblock as an alternative way to declare an inbound. See TUIC — mihomo.
Source: option/tuic.go:5-33 · v1.13.11 (553cfa1)
