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.
handshake_timeoutbadoption.Duration15s<duration>TLS handshake timeout (Go duration).
certificate_provider*CertificateProviderOptions(unset)<provider tag> | CertificateProviderOptionsCertificate managed by a certificate provider: the tag of an entry in top-level certificate_providers, or an inline provider object with a type (acme, tailscale, cloudflare-origin-ca). When set, certificate / key are not read. Mutually exclusive with acme; not available with reality.
acme*InboundACMEOptions(deprecated)InboundACMEOptionsDeprecated: inline ACME. Use certificate_provider with type: acme — the fields move over unchanged. Mutually exclusive with certificate_provider.
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:13-40 · pinned at v1.14.2 (af6e64c)

Outbound tls ​

FieldTypeDefaultAllowed valuesDescription
enabledboolfalsetrue | falseMaster switch.
enginestringgogo | apple | windowsTLS implementation for the handshake. apple uses Network.framework (Apple builds with CGO); windows uses Schannel via SSPI (Windows build 17763+, TLS 1.3 only on Windows 11 / Server 2022+). Non-go engines accept only server_name, insecure, alpn, min_version, max_version, certificate(_path), certificate_public_key_sha256 and handshake_timeout; any other TLS option is rejected at startup.
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).
spoofstring(unset)<hostname>Send a forged copy of the ClientHello carrying this SNI before the real one, to fool SNI-filtering middleboxes that allow specific hostnames. Must differ from server_name. Linux, macOS and Windows only; needs raw-socket privileges (CAP_NET_RAW + CAP_NET_ADMIN on Linux, root on macOS, Administrator on Windows; not on Windows ARM64).
spoof_methodstringwrong-sequencewrong-sequence | wrong-checksum | wrong-ack | wrong-md5 | wrong-timestampHow the real server is made to drop the forged segment: out-of-window sequence number (default), bad checksum, out-of-window ACK, TCP-MD5 option, or backdated timestamp (wrong-timestamp is not supported on macOS).
kernel_txboolfalsetrue | falseLinux KTLS for outgoing traffic.
kernel_rxboolfalsetrue | falseLinux KTLS for incoming traffic.
handshake_timeoutbadoption.Duration15s<duration>TLS handshake timeout (Go duration).
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:107-136 · pinned at v1.14.2 (af6e64c)

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:247-250 · pinned at v1.14.2 (af6e64c)

Certificate providers ​

A server's certificate can come from a certificate provider instead of files or the inline acme block. Define providers in the top-level certificate_providers array (each with type and tag) and reference one by tag from tls.certificate_provider, or put a provider object inline there. Types: acme (needs the with_acme build tag), tailscale (reuses a Tailscale endpoint; MagicDNS and HTTPS must be enabled in the tailnet) and cloudflare-origin-ca. Full option reference: Certificate providers. The acme provider:

FieldTypeDefaultAllowed valuesDescription
domainbadoption.Listable[string](required)<domain> | …Domains to request certificates for. Required.
data_directorystring(certmagic default)<dir path>Where ACME state and certificates are stored. Default: $XDG_DATA_HOME/certmagic or $HOME/.local/share/certmagic.
emailstring(unset)<e-mail>Account e-mail used to create or select the ACME account.
providerstringletsencryptletsencrypt | zerossl | <https:// directory URL>ACME CA. With zerossl, EAB credentials are requested automatically when email is set and external_account is empty.
account_keystring(unset)<PEM key>PEM private key of an existing ACME account.
dns01_challenge*ACMEProviderDNS01ChallengeOptions(unset)ACMEProviderDNS01ChallengeOptionsDNS-01 challenge settings (provider: alidns, cloudflare, acmedns, plus ttl, propagation_delay, propagation_timeout, resolvers, override_domain). When set, the other challenge types are disabled.
key_typeACMEKeyType(certmagic default)ed25519 | p256 | p384 | rsa2048 | rsa4096Key type for newly issued certificates.
profilestring(unset)<ACME profile>ACME profile for issuance. With Let's Encrypt, shortlived is chosen automatically when any domain is an IP address.
http_client*HTTPClientOptions(default client)<http_clients tag> | HTTPClientOptionsHTTP client for all ACME requests: an inline object or the tag of an http_clients entry.

Source: option/acme.go:15-31 · pinned at v1.14.2 (af6e64c)

Examples ​

Inbound with an inline ACME certificate provider:

json
{
  "inbounds": [{
    "type": "vless",
    "listen_port": 443,
    "users": [{ "uuid": "..." }],
    "tls": {
      "enabled": true,
      "server_name": "example.com",
      "alpn": ["h2", "http/1.1"],
      "certificate_provider": {
        "type": "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.
  • Inline tls.acme is deprecated. Move its fields unchanged into a certificate_provider of type: acme (inline, as in the example, or shared via certificate_providers + tag). certificate_provider and acme cannot be combined, and REALITY accepts neither.
  • engine: apple / windows hand the handshake to the OS TLS stack. They reject uTLS, REALITY, ECH, fragmentation, KTLS, client certificates, cipher_suites, curve_preferences, disable_sni and spoof at startup.
  • spoof (with spoof_method) is also available per connection as the tls_spoof / tls_spoof_method route rule action 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:13-250 · v1.14.2 (af6e64c)

Core Tutorial by Argsment