Skip to content

fix: preserve VLESS Reality ML-KEM option in Mihomo output - #441

Open
miyunda wants to merge 2 commits into
7Sageer:mainfrom
miyunda:fix/vless-reality-mlkem768
Open

miyunda wants to merge 2 commits into
7Sageer:mainfrom
miyunda:fix/vless-reality-mlkem768

Conversation

@miyunda

@miyunda miyunda commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Problem and observed impact

VLESS Reality share links containing support-x25519mlkem768=true lose that option when converted to Mihomo/Clash YAML. A node that needs the option can therefore fail Reality handshakes even though its server TCP port is reachable.

This was found in the following workflow:

3x-ui / Xray VLESS share link
  -> Sublink Worker on Cloudflare
  -> Mihomo YAML
  -> OpenClash on OpenWrt

An existing node worked, while a newly added VLESS + TCP + Reality + xtls-rprx-vision node repeatedly failed delay tests. Mihomo's API returned {"message":"An error occurred in the delay test"}, with alive: false and a zero-delay history entry. Testing more than one URL produced the same failure.

During the original troubleshooting session, adding only support-x25519mlkem768: true to that node's generated reality-opts, then hot-reloading the configuration, produced a successful delay result of 404 ms. This isolated the missing field as a sufficient fix for that tested client/server combination.

Versions recorded during that initial diagnosis: 3x-ui v3.11.0, Xray-core v26.10.21, OpenClash v0.47.001, and Mihomo alpha-gbc76c13 (linux-amd64-v2).

Minimal reproduction

Synthetic input; the UUID, domains and public-key placeholder below are not live node credentials:

vless://00000000-0000-4000-8000-000000000001@node.example.net:443?encryption=none&flow=xtls-rprx-vision&fp=chrome&pbk=TEST_PUBLIC_KEY&security=reality&sid=c94&sni=front.example.org&support-x25519mlkem768=true&type=tcp#Reality

Before this change, the generated node has only:

reality-opts:
  public-key: TEST_PUBLIC_KEY
  short-id: c94

After this change:

reality-opts:
  public-key: TEST_PUBLIC_KEY
  short-id: c94
  support-x25519mlkem768: true

The output value is a YAML boolean, not a string. The field is documented in Mihomo's TLS configuration.

Root cause and changes

There were two loss points: createTlsConfig() discarded the URI parameter while constructing the internal Reality object, and ClashConfigBuilder mapped only the public key and short ID.

  • Reuse parseBool() to store recognized values as optional tls.reality.support_x25519mlkem768.
  • Map that property into Mihomo's reality-opts.support-x25519mlkem768 for VLESS and the existing Trojan Reality branch.
  • Strip the internal property in SingboxConfigBuilder, since this option is outside the sing-box Reality TLS schema. Copy the nested objects before removing it so the parsed proxy is not mutated.

Explicit false remains false; 1/0 and case-insensitive true/false follow the existing boolean parser. Missing, empty or unrecognized values do not add the option. Legacy links retain their existing output, and no default is forced onto all Reality nodes. No dependencies are added.

This preserves a Reality TLS option; it does not add support for VLESS post-quantum encryption values or guarantee compatibility across all Xray/Mihomo versions.

Validation

Automated checks:

  • Added 23 regression tests, including URI -> parser -> builder -> parsed YAML checks for true, false, 1, 0, uppercase values, omitted values, empty values and invalid values.
  • Assert the existing UUID, server, SNI, fingerprint, public key, short ID, flow and other output fields remain intact.
  • Cover unchanged sing-box output, non-mutating sanitization, ordinary TLS links, and consistent Trojan Reality mapping.
  • Before the source fix: 9 new tests failed, reproducing the missing-field behavior. After the fix: all 23 passed.
  • npm test: 39 test files, 315 tests passed.
  • npm run build and npm run build:node: passed.
  • git diff --check: passed. No lint script is configured.

Manual integration:

  • Deployed the fixed branch as a separate Cloudflare application.
  • Tested successfully with OpenClash on OpenWrt.

Related: #417 describes other VLESS conversion field-loss problems. This PR is limited to the Reality ML-KEM option and does not close that broader issue.

@vercel

vercel Bot commented Nov 4, 2026

Copy link
Copy Markdown

@miyunda is attempting to deploy a commit to the 7sageer's projects Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant