fix: enable XTLS vision flow for VLESS+XHTTP+vlessenc in UI and share links (#5157) (#5185)

* fix: enable XTLS vision flow for VLESS+XHTTP+vlessenc in UI and share links (#5157)

* fix: enable xtls-rprx-vision flow for VLESS XHTTP with vlessenc encryption (#5157)

The flow selector was hidden and the vless:// link omitted flow= because:
1. The backend gate (inboundCanEnableTlsFlow) only accepted tcp+tls/reality.
2. The PR #5185 frontend check used `encryption === 'vlessenc'`, which never
   matches — the stored value is a generated ML-KEM dotted string, not the CLI
   subcommand name.

Fix: extend inboundCanEnableTlsFlow to also return true for XHTTP when a
non-none vlessenc encryption/decryption value is present. Update all three
call-sites (inbound.go TlsFlowCapable field, client_crud.go clientWithInboundFlow,
inbound_clients.go copy-flow path) and the sub/service.go link generator.
Scope is XHTTP-only: TCP without tls/reality is intentionally excluded.

Add inbound_protocol_test.go covering the new and existing gate combinations,
extend client_flow_isolation_test.go with xhttp+vlessenc cases, and add
frontend tests for canEnableTlsFlow with real ML-KEM key values.

---------

Co-authored-by: rqzbeh <rqzbeh@users.noreply.github.com>
Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
Rouzbeh†
2026-06-11 12:04:02 +02:00
committed by GitHub
parent eee652c4a5
commit c7a76e9626
12 changed files with 239 additions and 31 deletions
+29
View File
@@ -180,6 +180,35 @@ describe('protocol-capability helpers with raw coerced shapes', () => {
streamSettings: { network: 'tcp', security: 'tls' },
})).toBe(false);
});
it('canEnableTlsFlow allows vless + xhttp when vlessenc encryption is set', () => {
const enc = 'mlkem768x25519plus.native.0rtt.G3cdPSd1-NnlpTbWNSM5vHsT5VNzWfFzYSKwbUMnV1Y';
const dec = 'mlkem768x25519plus.native.600s.mMFxPe7lz5xoq2qBk22cQYefu5fpc_2dGR8lMOKem0E';
// XHTTP + a real (generated) encryption value → Vision flow allowed.
expect(canEnableTlsFlow({
protocol: 'vless',
settings: { encryption: enc },
streamSettings: { network: 'xhttp', security: 'none' },
})).toBe(true);
// decryption alone (server-side value) is enough on XHTTP.
expect(canEnableTlsFlow({
protocol: 'vless',
settings: { decryption: dec, encryption: 'none' },
streamSettings: { network: 'xhttp', security: 'none' },
})).toBe(true);
// No encryption → stays gated off.
expect(canEnableTlsFlow({
protocol: 'vless',
settings: { encryption: 'none' },
streamSettings: { network: 'xhttp', security: 'none' },
})).toBe(false);
// vlessenc is XHTTP-only: TCP without tls/reality is not Vision-capable.
expect(canEnableTlsFlow({
protocol: 'vless',
settings: { decryption: dec, encryption: enc },
streamSettings: { network: 'tcp', security: 'none' },
})).toBe(false);
});
});
describe('getInboundClients with schema-shaped inbound', () => {