Skip to content

TLS and REALITY

Several protocols run on top of a TLS or REALITY layer: VMess, VLESS, Trojan, AnyTLS and HTTP (HTTPS proxies) share the fields on this page. Miu also reads sni / servername, skip-cert-verify and reality-opts, with differences described on its page. Hysteria 2 and the Shadowsocks shadow-tls plugin have their own TLS settings.

Protocol TLS by default How to change it
trojan on tls: false turns it off
anytls always on the tls field is not read
vmess, vless, http off tls: true turns it on

If reality-opts.public-key is set, REALITY replaces TLS, whatever tls says. It is still a good idea to write tls: true on REALITY nodes so that the same file works in other clients.

Field Type Default Description
tls boolean see table above Enable TLS.
servername string — Server name sent as SNI and used to verify the certificate.
sni string — Same as servername. Both spellings are accepted for every protocol. If both are present, servername wins. If neither is set, server is used.
alpn list of strings none ALPN protocols to offer, in order, for example [h2, http/1.1]. When omitted, no ALPN extension is sent, except with network: grpc, which offers h2 automatically.
skip-cert-verify boolean false Accept any certificate: skip chain, expiry and host name checks. Needed for self-signed certificates. It makes you vulnerable to interception, so only use it when you trust the network path or pin the server some other way.

MeowX uses one of two TLS stacks, depending on how the node is reached:

  • Direct connection (normal case). The operating system’s TLS stack (Apple Network framework) is used, and the certificate is verified by the system.
  • Through dialer-proxy. The system stack cannot run on top of another proxy’s stream, so MeowX uses its own TLS client:
    • TLS 1.3 only. A server that only speaks TLS 1.2 cannot be reached through a chain.
    • Cipher suites: AES-128-GCM, AES-256-GCM and ChaCha20-Poly1305.
    • The certificate chain is verified against the system trust store and the handshake signature is checked. Missing intermediate certificates are not downloaded, so the server must send its full chain.
    • Compressed certificates (sent by some large CDNs) are supported.
    • skip-cert-verify: true skips both the chain and the signature checks.

REALITY lets a proxy server borrow the TLS identity of a real website. A probe that connects to the server sees that website’s genuine certificate. Only a client holding the server’s public key is recognized and served as a proxy.

proxies:
- name: vless-reality
type: vless
server: 192.0.2.1
port: 443
uuid: 00000000-0000-0000-0000-000000000000
flow: xtls-rprx-vision
tls: true
servername: www.example.com # must be one of the server's serverNames
reality-opts:
public-key: "SERVER-PUBLIC-KEY-BASE64URL"
short-id: "0123456789abcdef"
reality-opts field Type Required Default Description
public-key string yes — The server’s X25519 public key: 32 bytes, base64url-encoded (with or without padding), as printed by xray x25519. A 64-digit hex key is also accepted.
short-id string no empty One of the server’s short IDs, as hex (0–16 hex digits). Leave empty only if the server allows an empty short ID.

REALITY in MeowX:

  • Is used by any node that has reality-opts.public-key. It is commonly used with VLESS, and also works with Trojan, VMess and AnyTLS (and with Miu).
  • Takes its server name from servername / sni (falling back to server). It must match one of the serverNames configured on the server.
  • Sends a Chrome 133 ClientHello (see Fingerprints). It includes the post-quantum X25519MLKEM768 key share, which recent REALITY servers require, on every supported OS version.
  • Offers ALPN h2 and http/1.1 like Chrome does. The alpn field is ignored.
  • Verifies the server through REALITY’s own certificate check. skip-cert-verify has no effect. If the server does not prove it holds the matching private key (wrong public-key or short-id, or you reached the real website), the connection fails before any proxy data is sent.
  • Works with the ws, grpc and xhttp transports, with XTLS Vision, and through dialer-proxy.

Not supported with REALITY: a target website that answers with a HelloRetryRequest, which happens only if it needs a key-exchange group other than X25519 / X25519MLKEM768. Mainstream sites do not.

A malformed public-key does not stop the configuration from loading. Every connection to that node fails with an error naming the key.

MeowX does not read client-fingerprint. The ClientHello it sends is fixed by the code path:

Connection ClientHello
TLS, direct connection Apple’s system TLS, the same as Safari and other apps on the device.
TLS through dialer-proxy MeowX’s minimal TLS 1.3 ClientHello.
REALITY (any protocol) Chrome 133
Shadowsocks shadow-tls plugin, Snell ShadowTLS Chrome 133
Miu (TLS or REALITY) Chrome 133

The Chrome 133 ClientHello matches real Chrome. Its extension order is randomized on every connection, and it includes GREASE values, an ECH GREASE extension, ALPS and the X25519MLKEM768 + X25519 key shares, so its JA4 fingerprint is the same as Chrome’s.

These TLS-related fields are not read by MeowX:

Field Note
client-fingerprint See Fingerprints.
fingerprint Certificate pinning is not supported. For a self-signed server that you used to pin with fingerprint, set skip-cert-verify: true instead. Otherwise verification against the system trust store will fail.
certificate, private-key Client certificates (mutual TLS) are not supported.
ech-opts Encrypted Client Hello is not supported.
reality-opts.support-x25519mlkem768 Not needed: MeowX always offers X25519MLKEM768 with REALITY.