From d9b599b9aa6d7b8447fc84c3859c465e5150d469 Mon Sep 17 00:00:00 2001 From: Sanaei Date: Mon, 24 Aug 2026 02:38:40 +0200 Subject: [PATCH] fix(sub): forward tlsSettings.cipherSuites into the JSON subscription tlsData rebuilds the client-side tlsSettings from a whitelist of keys and never copied cipherSuites, so an inbound configured with e.g. "TLS_AES_256_GCM_SHA384" handed clients a config that negotiated any suite. Copy it through when non-empty; it is a real xray-core tlsSettings field, unlike the non-standard "cs" share-link param. --- internal/sub/json_service.go | 3 +++ internal/sub/json_service_test.go | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/internal/sub/json_service.go b/internal/sub/json_service.go index 043324434..7ce537a5f 100644 --- a/internal/sub/json_service.go +++ b/internal/sub/json_service.go @@ -639,6 +639,9 @@ func (s *SubJsonService) tlsData(tData map[string]any) map[string]any { if fingerprint, ok := tlsClientSettings["fingerprint"].(string); ok { tlsData["fingerprint"] = fingerprint } + if cs, ok := tData["cipherSuites"].(string); ok && cs != "" { + tlsData["cipherSuites"] = cs + } if ech, ok := tlsClientSettings["echConfigList"].(string); ok && ech != "" { tlsData["echConfigList"] = ech } diff --git a/internal/sub/json_service_test.go b/internal/sub/json_service_test.go index 392e30fc4..c7c6a4890 100644 --- a/internal/sub/json_service_test.go +++ b/internal/sub/json_service_test.go @@ -120,6 +120,22 @@ func TestSubJsonServicePinnedCertJoinedToString(t *testing.T) { } } +func TestSubJsonServiceTLSCipherSuitesForwarded(t *testing.T) { + svc := NewSubJsonService("", "", "", nil) + stream := svc.streamData(`{"network":"tcp","security":"tls","tlsSettings":{"serverName":"a.example.com","cipherSuites":"TLS_AES_256_GCM_SHA384","settings":{}}}`, "") + + tls, _ := stream["tlsSettings"].(map[string]any) + if got := tls["cipherSuites"]; got != "TLS_AES_256_GCM_SHA384" { + t.Fatalf("cipherSuites = %#v, want %q", got, "TLS_AES_256_GCM_SHA384") + } + + stream = svc.streamData(`{"network":"tcp","security":"tls","tlsSettings":{"serverName":"a.example.com","cipherSuites":"","settings":{}}}`, "") + tls, _ = stream["tlsSettings"].(map[string]any) + if _, present := tls["cipherSuites"]; present { + t.Fatalf("empty cipherSuites must be omitted, got %#v", tls["cipherSuites"]) + } +} + func TestSubJsonServiceVlessFlattened(t *testing.T) { inbound := &model.Inbound{Listen: "1.2.3.4", Port: 443, Protocol: model.VLESS, Settings: `{"encryption":"none"}`} client := model.Client{ID: "uuid-1", Flow: "xtls-rprx-vision"}