Skip to content

VLESS/REALITY fails with Xray 26.9.9 on iOS 27 / Shadowrocket 2.2.92: ClientHello lacks X25519MLKEM768 #4

Description

@wc7086

Summary

Shadowrocket 2.2.92 (3445) on iOS 27 cannot connect to a VLESS + TCP + REALITY + Vision server running Xray 26.9.9. Other clients can use the same inbound.

A complete ClientHello captured during a failing Shadowrocket request contains only GREASE and X25519 key shares, with no X25519MLKEM768 key share. This is incompatible with the new upstream REALITY requirement.

Could you confirm the supported Shadowrocket build, TLS profile and exact setting location for this server version, and investigate the effective profile selection if the selected compatible profile is not used by REALITY?

Environment

  • Shadowrocket: 2.2.92 (3445)
  • iOS: 27.0 (24A437)
  • Server: Xray-core 26.9.9, commit 52a412d, Linux amd64
  • Protocol: VLESS
  • Transport: TCP
  • Security: REALITY
  • Flow: xtls-rprx-vision
  • Failure reported on both Wi-Fi and cellular; the instrumented reproduction was on Wi-Fi.
  • Investigation date: 2026-09-16

Reproduction

  1. Use a working VLESS/TCP/REALITY/Vision inbound on Xray 26.9.9.
  2. Import the matching endpoint, UUID, REALITY public key, short ID and SNI into Shadowrocket 2.2.92.
  3. Enable the VPN and request an HTTPS resource through the node.
  4. Observe the request fail. Reproducing through Shadowrocket's LAN HTTP proxy returns 503 Service Unavailable.
  5. Capture the initial ClientHello at the server and inspect its key_share extension.

The starting node configuration logged tls=1, xtls=2, tlsProfile=chrome, and the expected public key, short ID and SNI. Credentials and addresses are intentionally omitted.

Actual behavior and packet evidence

Shadowrocket reports:

backend vless <redacted> vless stream operation => read error => -4

A complete failing phone ClientHello had:

ClientHello TCP payload: 517 bytes
TLS handshake record payload: 512 bytes

Initial key_share entries:
  GREASE:           1 byte
  X25519 (0x001d): 32 bytes
  X25519MLKEM768 (0x11ec): absent

The phone advertised TLS 1.3, then closed the connection after receiving the server-side handshake response. It did not complete the TLS handshake or send a VLESS request.

The actual in-memory server configuration was checked through Xray's API:

  • Public key, allowed SNI and short ID matched the phone configuration.
  • The live VLESS account had flow=xtls-rprx-vision.
  • Client-version restrictions were unset; maxTimeDiff=0.
  • The phone's encrypted REALITY authentication fields and short ID were independently validated inside the server, without exporting its key.

That last check does not mean the running server accepted the connection: the upstream key-share gate runs before the authentication-field check.

Upstream compatibility requirement

Xray 26.9.9 pins REALITY 8cdf7bf9c7f0, which requires an initial X25519MLKEM768 share before the optional X25519 share. A ClientHello missing it takes the fallback path.

Controlled comparison

Temporary Xray 26.9.9 clients connected to the same unchanged inbound with the same account, REALITY parameters and HTTPS URL. Only the fingerprint changed:

Xray client fingerprint Result
hellochrome_100 Connection reset; no HTTP response
hellochrome_120 Connection reset; no HTTP response
hellosafari_16_0 Connection reset; no HTTP response
hellochrome_131 HTTPS succeeded, HTTP 204

The Chrome120 control logged:

transport/internet/reality: REALITY: received real certificate (potential MITM or redirection)

The Chrome131 control succeeded without that error. Production configuration was not changed.

Profile changes tried and evidence limits

Chrome/Safari and later Chrome120/Chrome140 were tried in Shadowrocket's UI without restoring connectivity.

A fresh Chrome140 selection was not strictly correlated with a specific packet capture. Therefore this report does not assert that Chrome140 itself lacks ML-KEM, nor that profile selection is conclusively broken. The captured failing connections establish the missing-share condition, while the exact effective-profile selection remains unresolved.

The 2.2.93 (3450) announcement only removes incorrect X25519MLKEM768 labels from Chrome120; it does not announce added ML-KEM support. Build 3454 mentions default/profile selection fixes, but was not tested in this investigation, and no claim is made that upgrading resolves the problem.

Expected behavior / request

Please document which Shadowrocket build and REALITY-compatible profile emits the required initial key share, including whether it must be selected globally or per node. If a selected profile cannot satisfy the server requirement, an explicit compatibility warning would help instead of the current generic read error.

Related user reports: 3x-ui #6543. This report is directed to Shadowrocket for client-side compatibility guidance and effective-profile verification.

Server addresses, client UUIDs, keys, short IDs, subscription URLs and unrelated traffic have been omitted.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions