Skip to content

TLS — sing-box

Every sing-box inbound and outbound embeds a tls: { ... } block via InboundTLSOptionsContainer / OutboundTLSOptionsContainer. The same block carries REALITY, ECH, and uTLS sub-blocks as nested options — they're not separate top-level features.

Inbound tls

FieldTypeDefaultAllowed valuesDescription
enabledboolfalsetrue | falseMaster switch. When false, the rest of the block is ignored.
server_namestring(inferred from SNI)<hostname>Expected server name for ACME provisioning. Required if `acme` is set.
insecureboolfalsetrue | falseSkip TLS verification. Test only.
alpnbadoption.Listable[string][]<ALPN string>ALPN list offered to clients.
min_versionstring1.21.0 | 1.1 | 1.2 | 1.3Minimum acceptable TLS version.
max_versionstring1.31.0 | 1.1 | 1.2 | 1.3Maximum acceptable TLS version.
cipher_suitesbadoption.Listable[string](library default)<cipher>Override the cipher suite list (TLS 1.2 only).
curve_preferencesbadoption.Listable[CurvePreference](library default)P256 | P384 | P521 | X25519 | X25519MLKEM768Key-exchange curve preference list.
certificatebadoption.Listable[string][]<PEM block>Inline server certificate PEM. List form supports the full chain.
certificate_pathstring(unset)<PEM file path>Path to server certificate.
client_authenticationClientAuthTypenono | request | require-any | verify-if-given | require-and-verifyMutual-TLS client-auth policy. Maps to crypto/tls's ClientAuthType values.
client_certificatebadoption.Listable[string][]<PEM block>Trusted client-certificate roots (mTLS).
client_certificate_pathbadoption.Listable[string][]<PEM file path>Path-form trusted client roots.
client_certificate_public_key_sha256badoption.Listable[[]byte][]<SHA-256 bytes>Pin the client cert by public-key SHA-256. Useful when issuing throw-away client certs.
keybadoption.Listable[string][]<PEM block>Inline server private key.
key_pathstring(unset)<file path>Path to server private key.
kernel_txboolfalsetrue | falseLinux KTLS — offload TLS encryption to the kernel for outgoing traffic. Requires kernel TLS support and the right crypto modules.
kernel_rxboolfalsetrue | falseLinux KTLS for incoming traffic.
acme*InboundACMEOptions(unset)InboundACMEOptionsAutomatic Let's-Encrypt certificate provisioning. Mutually exclusive with explicit `certificate`/`key`.
ech*InboundECHOptions(unset)InboundECHOptionsEncrypted Client Hello configuration.
reality*InboundRealityOptions(unset)InboundRealityOptionsREALITY server configuration. Mutually exclusive with normal TLS — REALITY replaces the TLS handshake.

Source: option/tls.go:12-34 · pinned at v1.13.11 (553cfa1)

Outbound tls

FieldTypeDefaultAllowed valuesDescription
enabledboolfalsetrue | falseMaster switch.
disable_sniboolfalsetrue | falseOmit the SNI extension entirely from the ClientHello.
server_namestring(server address)<hostname>SNI sent to the server, and the name verified against the leaf certificate.
insecureboolfalsetrue | falseSkip server-certificate verification.
alpnbadoption.Listable[string][]<ALPN string>ALPN list offered to the server.
min_versionstring1.21.0 | 1.1 | 1.2 | 1.3Minimum acceptable TLS version.
max_versionstring1.31.0 | 1.1 | 1.2 | 1.3Maximum acceptable TLS version.
cipher_suitesbadoption.Listable[string](library default)<cipher>Override cipher suite list.
curve_preferencesbadoption.Listable[CurvePreference](library default)<see inbound>Key-exchange curve preference.
certificatebadoption.Listable[string][]<PEM block>Trusted CA certificates appended to the system root store. Use with `insecure: false` for self-signed servers.
certificate_pathstring(unset)<file path>Path-form trusted CAs.
certificate_public_key_sha256badoption.Listable[[]byte][]<SHA-256 bytes>Pin the server certificate by public-key SHA-256.
client_certificatebadoption.Listable[string][]<PEM block>Client certificate (mTLS).
client_certificate_pathstring(unset)<file path>Path-form client certificate.
client_keybadoption.Listable[string][]<PEM block>Client private key.
client_key_pathstring(unset)<file path>Path-form client private key.
fragmentboolfalsetrue | falseTCP-level handshake fragmentation. Splits the ClientHello across packets to evade SNI-based DPI.
fragment_fallback_delaybadoption.Duration500ms<duration>If the fragmented handshake doesn't complete by this deadline, retry without fragmentation.
record_fragmentboolfalsetrue | falseTLS-record-layer fragmentation (more aggressive than `fragment` — splits inside the TLS record stream, not just TCP packets).
kernel_txboolfalsetrue | falseLinux KTLS for outgoing traffic.
kernel_rxboolfalsetrue | falseLinux KTLS for incoming traffic.
ech*OutboundECHOptions(unset)OutboundECHOptionsECH configuration. When unset, ECH is not used (unless auto-discovered via HTTPS records).
utls*OutboundUTLSOptions(unset)OutboundUTLSOptionsuTLS client-hello mimicry.
reality*OutboundRealityOptions(unset)OutboundRealityOptionsREALITY client configuration. Mutually exclusive with normal TLS.

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

utls

FieldTypeDefaultAllowed valuesDescription
enabledboolfalsetrue | falseTurn uTLS on.
fingerprintstringchromechrome | firefox | safari | ios | android | edge | 360 | qq | random | randomizedBrowser fingerprint to mimic. Drives the entire ClientHello (cipher suites, extensions, signatures).

Source: option/tls.go:229-232 · pinned at v1.13.11 (553cfa1)

Examples

Inbound with ACME provisioning:

json
{
  "inbounds": [{
    "type": "vless",
    "listen_port": 443,
    "users": [{ "uuid": "..." }],
    "tls": {
      "enabled": true,
      "server_name": "example.com",
      "alpn": ["h2", "http/1.1"],
      "acme": {
        "domain": ["example.com"],
        "email": "admin@example.com"
      }
    }
  }]
}

Outbound with uTLS chrome fingerprint and TCP-fragment SNI hiding:

json
{
  "outbounds": [{
    "type": "vless",
    "server": "example.com",
    "server_port": 443,
    "uuid": "...",
    "tls": {
      "enabled": true,
      "server_name": "example.com",
      "utls": { "enabled": true, "fingerprint": "chrome" },
      "fragment": true,
      "fragment_fallback_delay": "500ms"
    }
  }]
}

Mutual TLS — server requires client certificates:

json
{
  "inbounds": [{
    "type": "http",
    "listen_port": 8443,
    "tls": {
      "enabled": true,
      "certificate_path": "/etc/ssl/cert.pem",
      "key_path": "/etc/ssl/key.pem",
      "client_authentication": "require-and-verify",
      "client_certificate_path": ["/etc/ssl/clients-ca.pem"]
    }
  }]
}

Notes

  • The five client_authentication values map directly to Go's crypto/tls.ClientAuthType:
    • no — no client cert (default).
    • request — ask for one, accept without it.
    • require-any — require but don't validate.
    • verify-if-given — validate if provided.
    • require-and-verify — strict mTLS.
  • fragment and record_fragment are two different layers:
    • fragment splits the TCP packets carrying the TLS handshake.
    • record_fragment splits the TLS records themselves (Handshake records sent in multiple smaller pieces). Use fragment first; only enable record_fragment if SNI-based DPI still classifies the connection.
  • kernel_tx / kernel_rx enable Linux KTLS for AES-GCM and CHACHA20- POLY1305. The kernel must have the tls module loaded and the right crypto modules registered.
  • acme is mutually exclusive with explicit certificate/key. With ACME, sing-box uses the embedded autocert client — see the upstream docs for ACME provider options.
  • REALITY (the reality sub-block) replaces the TLS handshake entirely — see REALITY — sing-box.
  • ECH (the ech sub-block) plugs into the same handshake — see ECH — sing-box.

Cross-core notes

  • Xray-core uses streamSettings.tlsSettings rather than an embedded tls block. Field names are camelCase (serverName, cipherSuites). uTLS fingerprint is a top-level field, not a sub-block. See TLS — Xray-core.
  • mihomo has no consolidated TLS block — each proxy adapter carries TLS fields inline (tls, sni, alpn, skip-cert-verify, …). See TLS — mihomo.

Source: option/tls.go:12-232 · v1.13.11 (553cfa1)

Core Tutorial by Argsment