fix(xray): keep XDRIVE storage and Vision flow within what xray-core runs

xray-core opens an XDRIVE stream's storage only when the inbound starts
listening, so a Google Drive inbound saved with the form's defaults (no
folder, no secrets), a local one without a folder, or a template one
whose template xray cannot use stopped xray and every other inbound with
it. validateXDriveStorage applies the core's storage rules at save, on
inbound add/update and on the xray template's inbounds and outbounds:
the service must be local, Google Drive or template; local and Google
Drive need a remoteFolder; Google Drive needs its three non-empty
secrets; a template must pass newTemplateStorage's checks (put, get,
list and delete urls, and a list namesRegex with one capture group).

A VLESS client kept its xtls-rprx-vision flow when its inbound moved to
a transport that cannot carry it, and GetXrayConfig only honoured
DisableFlow, so the server demanded Vision there and refused every
client. GetXrayConfig and the outbound form now apply the Vision gate,
and that gate now follows the core in the backend, the subscription
service and the frontend: TLS/REALITY on raw TCP, or VLESS encryption on
any transport (xray runs Vision inside encryption.CommonConn whatever
the transport, not only on XHTTP). The outbound modal passes the VLESS
encryption into the gate and gates Mux on the effective flow.
This commit is contained in:
MHSanaei
2026-10-12 00:49:11 +02:00
parent 8fe7be943f
commit c5e1e54c75
22 changed files with 439 additions and 72 deletions
+7 -21
View File
@@ -27,35 +27,21 @@ func inboundShadowsocksMethod(protocol, settings string) string {
return s.Method
}
// inboundCanEnableTlsFlow mirrors canEnableTlsFlow() from the frontend
// (frontend/src/lib/xray/protocol-capabilities.ts). XTLS Vision is valid for
// VLESS on TCP with tls or reality (classic), and on XHTTP when VLESS encryption
// (vlessenc / ML-KEM) is enabled — there the post-quantum, VLESS-level
// encryption stands in for the transport TLS that Vision relies on. settings is
// the inbound's raw settings JSON, which carries the encryption value
// (streamSettings does not).
// inboundCanEnableTlsFlow mirrors the frontend's canEnableTlsFlow: xray-core runs Vision over
// TLS/REALITY on raw TCP, or inside VLESS encryption (encryption.CommonConn) on any transport.
func inboundCanEnableTlsFlow(protocol, streamSettings, settings string) bool {
if protocol != string(model.VLESS) {
return false
}
if streamSettings == "" {
return false
}
var stream struct {
Network string `json:"network"`
Security string `json:"security"`
}
if err := json.Unmarshal([]byte(streamSettings), &stream); err != nil {
return false
}
switch stream.Network {
case "tcp":
return stream.Security == "tls" || stream.Security == "reality"
case "xhttp":
return vlessEncryptionEnabled(settings)
default:
return false
if json.Unmarshal([]byte(streamSettings), &stream) == nil && stream.Network == "tcp" &&
(stream.Security == "tls" || stream.Security == "reality") {
return true
}
return vlessEncryptionEnabled(settings)
}
// nodeEligibleProtocols mirrors the frontend's NODE_ELIGIBLE_PROTOCOLS. A sidecar
@@ -141,7 +127,7 @@ func vlessEncValueSet(v string) bool {
// inboundCanHostFallbacks gates the settings.fallbacks injection.
// Xray only honors fallbacks on VLESS and Trojan inbounds carried over
// TCP transport with TLS or Reality security. This is intentionally stricter
// than inboundCanEnableTlsFlow (which also accepts XHTTP+vlessenc): fallbacks
// than inboundCanEnableTlsFlow (which also accepts any vlessenc stream): fallbacks
// are a raw-TCP-only feature.
func inboundCanHostFallbacks(ib *model.Inbound) bool {
if ib == nil {