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.
When TLS is used
Section titled “When TLS is used”| 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.
TLS fields
Section titled “TLS fields”| 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. |
Which TLS implementation is used
Section titled “Which TLS implementation is used”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: trueskips both the chain and the signature checks.
REALITY
Section titled “REALITY”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 toserver). It must match one of theserverNamesconfigured on the server. - Sends a Chrome 133 ClientHello (see Fingerprints). It includes the post-quantum
X25519MLKEM768key share, which recent REALITY servers require, on every supported OS version. - Offers ALPN
h2andhttp/1.1like Chrome does. Thealpnfield is ignored. - Verifies the server through REALITY’s own certificate check.
skip-cert-verifyhas no effect. If the server does not prove it holds the matching private key (wrongpublic-keyorshort-id, or you reached the real website), the connection fails before any proxy data is sent. - Works with the
ws,grpcandxhttptransports, with XTLS Vision, and throughdialer-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.
Fingerprints
Section titled “Fingerprints”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.
Ignored fields
Section titled “Ignored fields”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. |
