From 46684dd164eef7ce75f69b201361da9001ae1943 Mon Sep 17 00:00:00 2001 From: jq <291330184+fs438187@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:39:54 +0800 Subject: [PATCH] fix(sub): emit VLESS encryption in Clash configs (#5053) Co-authored-by: jq --- sub/subClashService.go | 7 +++-- sub/subClashService_test.go | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/sub/subClashService.go b/sub/subClashService.go index 23518fa3..73806bfa 100644 --- a/sub/subClashService.go +++ b/sub/subClashService.go @@ -221,8 +221,11 @@ func (s *SubClashService) buildProxy(inbound *model.Inbound, client model.Client } var inboundSettings map[string]any json.Unmarshal([]byte(inbound.Settings), &inboundSettings) - if encryption, ok := inboundSettings["encryption"].(string); ok && encryption != "" { - proxy["packet-encoding"] = encryption + if encryption, ok := inboundSettings["encryption"].(string); ok { + encryption = strings.TrimSpace(encryption) + if encryption != "" && encryption != "none" { + proxy["encryption"] = encryption + } } case model.Trojan: proxy["type"] = "trojan" diff --git a/sub/subClashService_test.go b/sub/subClashService_test.go index c8a1195d..7eccc9fc 100644 --- a/sub/subClashService_test.go +++ b/sub/subClashService_test.go @@ -3,6 +3,8 @@ package sub import ( "reflect" "testing" + + "github.com/mhsanaei/3x-ui/v3/database/model" ) func TestEnsureUniqueProxyNames(t *testing.T) { @@ -113,3 +115,60 @@ func TestApplyTransport_HTTPUpgrade(t *testing.T) { t.Fatalf("headers.Host = %v, want example.com", headers["Host"]) } } + +func TestBuildProxy_VLESSPostQuantumEncryptionUsesMihomoEncryptionField(t *testing.T) { + svc := &SubClashService{SubService: &SubService{remarkModel: "-i"}} + encryption := "mlkem768x25519plus.native.0rtt.client" + inbound := &model.Inbound{ + Listen: "203.0.113.1", + Port: 443, + Protocol: model.VLESS, + Remark: "pq", + Settings: `{"encryption":"` + encryption + `"}`, + } + client := model.Client{ID: "11111111-2222-4333-8444-555555555555"} + stream := map[string]any{ + "network": "xhttp", + "xhttpSettings": map[string]any{ + "path": "/", + "mode": "auto", + }, + "security": "reality", + "realitySettings": map[string]any{ + "publicKey": "pub", + "serverName": "example.com", + "shortId": "abcd", + }, + } + + proxy := svc.buildProxy(inbound, client, stream, "") + + if proxy["encryption"] != encryption { + t.Fatalf("encryption = %v, want %q", proxy["encryption"], encryption) + } +} + +func TestBuildProxy_VLESSNoneEncryptionOmittedForClash(t *testing.T) { + svc := &SubClashService{SubService: &SubService{remarkModel: "-i"}} + inbound := &model.Inbound{ + Listen: "203.0.113.1", + Port: 443, + Protocol: model.VLESS, + Remark: "plain", + Settings: `{"encryption":"none"}`, + } + client := model.Client{ID: "11111111-2222-4333-8444-555555555555"} + stream := map[string]any{ + "network": "tcp", + "security": "none", + "tcpSettings": map[string]any{ + "header": map[string]any{"type": "none"}, + }, + } + + proxy := svc.buildProxy(inbound, client, stream, "") + + if _, ok := proxy["encryption"]; ok { + t.Fatalf("plain vless encryption should be omitted for mihomo: %#v", proxy) + } +}