VLESS REALITY: `reality verification failed` against Xray-core v26.9.8+ servers (server now requires X25519MLKEM768 key share)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 38.2k
- Forks
- 4.6k
- Avg merge
- 19d 15h
- Merged PRs (30d)
- 1
Description
Operating system
Linux
System version
Debian GNU/Linux 13 (amd64); also reproduced on Windows 11 x64 (client side is OS-independent)
Installation type
Original sing-box Command Line
If you are using a graphical client, please provide the version of the client.
No response
Version
sing-box version 1.12.25
Environment: go1.23.12 linux/mipsle
Also affected: 1.14.0 (go1.25.8 windows/amd64), 1.15.0-alpha.2, dev f6ce1d5 (metacubex/utls v1.8.7)
Description
What happened?
Since Xray-core v26.9.8 / v26.9.9 upgraded github.com/xtls/reality to v0.0.0-20260908062103-8cdf7bf9c7f0, every sing-box version I tested can no longer connect to REALITY servers running these builds. The client always fails with:
connection: open connection to <host>:443 using outbound/vless[out]: reality verification failed
Server-side root cause
REALITY commit 8cdf7bf9c7f0 ("REALITY protocol: Reject outdated/strange Client Hello that doesn't have X25519MLKEM768 before optional X25519") makes the REALITY server require the client ClientHello to contain an X25519MLKEM768 key share (listed before any plain X25519). If it is missing, the server treats the handshake as unauthorized and silently falls back to the configured destination, so the client-side session verification fails.
sing-box's chrome uTLS fingerprint (HelloChrome_Auto from metacubex/utls) does not emit an X25519MLKEM768 key share, so all sing-box REALITY handshakes are rejected by these servers.
Control experiments
- The exact same client config against a server built from the same Xray-core v26.9.9 source but with
github.com/xtls/realitypinned to the parent commit e1986a4d31ca (i.e. without this ClientHello check) connects fine (full-tunnel curl returns HTTP 204/200). - Current Xray-core clients (uTLS chrome) still connect to the v26.9.9 server without issues.
So the only variable is the server-side REALITY bump: sing-box's ClientHello is now classified as "outdated/strange" and rejected.
Suggested fix
Could sing-box, via metacubex/utls, emit an X25519MLKEM768-first key share for the chrome-family fingerprints (sync the Chrome fingerprint definitions from upstream refraction-networking/utls, or extend HelloChrome_Auto)? Otherwise all sing-box (and mihomo, same fork) REALITY users are locked out of servers running Xray-core >= v26.9.8 - the version server operators are now encouraged to run for the REALITY memory-leak fix.
Reproduction
Server (Xray-core v26.9.9, official release binary)
server.json:
{
"inbounds": [
{
"tag": "reality",
"listen": "127.0.0.1",
"port": 8443,
"protocol": "vless",
"settings": {
"clients": [{ "id": "48796f85-218b-42fb-88dd-55ac99d0a767", "flow": "xtls-rprx-vision" }],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"dest": "www.sonic.com:443",
"serverNames": ["www.sonic.com"],
"privateKey": "GNcg__Kp68P5txlaRHOQX-TYxlYS_fvsnWZ4W53g0Ek",
"shortIds": ["87ed"]
}
}
}
],
"outbounds": [{ "protocol": "freedom" }]
}
Run: xray run -c server.json
Client (any affected sing-box build)
client.json:
{
"inbounds": [{ "type": "mixed", "tag": "in", "listen": "127.0.0.1", "listen_port": 10808 }],
"outbounds": [
{
"type": "vless",
"tag": "out",
"server": "127.0.0.1",
"server_port": 8443,
"uuid": "48796f85-218b-42fb-88dd-55ac99d0a767",
"flow": "xtls-rprx-vision",
"tls": {
"enabled": true,
"server_name": "www.sonic.com",
"utls": { "enabled": true, "fingerprint": "chrome" },
"reality": { "enabled": true, "public_key": "ywFgsEouyJvRVRxWvkhes19RSblBm6y0p6NT5IHSFD8", "short_id": "87ed" }
}
}
]
}
Run: sing-box run -c client.json, then curl --socks5 127.0.0.1:10808 https://www.gstatic.com/generate_204 -> fails; the sing-box log shows reality verification failed.
Clients tested (all fail)
- 1.12.25 (go1.23.12, linux/mipsle)
- 1.14.0 (go1.25.8, windows/amd64)
- 1.15.0-alpha.2
- dev f6ce1d5 (metacubex/utls v1.8.7), with fingerprints
chrome,chrome_pq,chrome_pq_psk
Control experiment
Rebuild the server from the same v26.9.9 source tree with only github.com/xtls/reality pinned to the parent commit (go get github.com/xtls/reality@v0.0.0-20260908045812-e1986a4d31ca, commit e1986a4d31ca, i.e. without the ClientHello check). The exact same configs then work and curl returns 204.
Logs
dev f6ce1d5, fingerprint chrome:
ERROR [...] connection: open connection to www.gstatic.com:443 using outbound/vless[out]: reality verification failed
1.12.25 / 1.14.0 / 1.15.0-alpha.2 show the same `reality verification failed` error.
Supporter
- I am a sponsor
Integrity requirements
- I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values.
- I confirm that I have provided the server and client configuration files and process that can be reproduced locally, instead of a complicated client configuration file that has been stripped of sensitive data.
- I confirm that I have provided the simplest configuration that can be used to reproduce the error I reported, instead of depending on remote servers, TUN, graphical interface clients, or other closed-source software.
- I confirm that I have provided the complete configuration files and logs, rather than just providing parts I think are useful out of confidence in my own intelligence.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducible server.json and client.json configurations and the chrome/HelloChrome_Auto fingerprint behavior described in the issue. Compare the affected fingerprint definitions with upstream uTLS and verify against Xray-core v26.9.9; done means the supplied curl request succeeds and the client no longer reports reality verification failed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100