diff --git a/sub/subService.go b/sub/subService.go index d344fcfa..5de64d33 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -657,7 +657,10 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st } } - encPart := fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password) + encPart := fmt.Sprintf("%s:%s", method, clients[clientIndex].Password) + if method[0] == '2' { + encPart = fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password) + } link := fmt.Sprintf("ss://%s@%s:%d", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port) url, _ := url.Parse(link) q := url.Query() diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index c9eab40c..5ae0a865 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -16,9 +16,10 @@ const VmessMethods = { }; const SSMethods = { - CHACHA20_POLY1305: 'chacha20-poly1305', AES_256_GCM: 'aes-256-gcm', AES_128_GCM: 'aes-128-gcm', + CHACHA20_POLY1305: 'chacha20-poly1305', + XCHACHA20_POLY1305: 'xchacha20-poly1305', BLAKE3_AES_128_GCM: '2022-blake3-aes-128-gcm', BLAKE3_AES_256_GCM: '2022-blake3-aes-256-gcm', BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305', @@ -873,7 +874,10 @@ class Inbound extends XrayCommonClass { } } get isSSMultiUser() { - return [SSMethods.BLAKE3_AES_128_GCM,SSMethods.BLAKE3_AES_256_GCM].includes(this.method); + return this.method != SSMethods.BLAKE3_CHACHA20_POLY1305; + } + get isSS2022(){ + return this.method.substring(0,4) === "2022"; } get serverName() { @@ -1274,9 +1278,11 @@ class Inbound extends XrayCommonClass { break; } - let clientPassword = this.isSSMultiUser ? ':' + settings.shadowsockses[clientIndex].password : ''; + let password = new Array(); + if (this.isSSMultiUser) password.push(settings.shadowsockses[clientIndex].password); + if (this.isSS2022) password.push(settings.password); - let link = `ss://${safeBase64(settings.method + ':' + settings.password + clientPassword)}@${address}:${this.port}`; + let link = `ss://${safeBase64(settings.method + ':' + password.join(':'))}@${address}:${this.port}`; const url = new URL(link); for (const [key, value] of params) { url.searchParams.set(key, value) @@ -1872,8 +1878,9 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings { }; Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass { - constructor(password=RandomUtil.randomShadowsocksPassword(), email=RandomUtil.randomText(), totalGB=0, expiryTime=0, enable=true, tgId='', subId=RandomUtil.randomText(16,16)) { + constructor(method='', password=RandomUtil.randomShadowsocksPassword(), email=RandomUtil.randomText(), totalGB=0, expiryTime=0, enable=true, tgId='', subId=RandomUtil.randomText(16,16)) { super(); + this.method = method; this.password = password; this.email = email; this.totalGB = totalGB; @@ -1885,6 +1892,7 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass { toJson() { return { + method: this.method, password: this.password, email: this.email, totalGB: this.totalGB, @@ -1897,6 +1905,7 @@ Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass { static fromJson(json = {}) { return new Inbound.ShadowsocksSettings.Shadowsocks( + json.method, json.password, json.email, json.totalGB, diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index dcd6537b..ef4003c4 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -69,7 +69,7 @@ case Protocols.VMESS: return clients.push(new Inbound.VmessSettings.Vmess()); case Protocols.VLESS: return clients.push(new Inbound.VLESSSettings.VLESS()); case Protocols.TROJAN: return clients.push(new Inbound.TrojanSettings.Trojan()); - case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks()); + case Protocols.SHADOWSOCKS: return clients.push(new Inbound.ShadowsocksSettings.Shadowsocks(clients[0].method)); default: return null; } }, diff --git a/web/html/xui/form/protocol/shadowsocks.html b/web/html/xui/form/protocol/shadowsocks.html index ef266507..808eed7d 100644 --- a/web/html/xui/form/protocol/shadowsocks.html +++ b/web/html/xui/form/protocol/shadowsocks.html @@ -125,7 +125,7 @@ - + {{ i18n "password" }} diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html index 94f73169..131709e2 100644 --- a/web/html/xui/inbound_modal.html +++ b/web/html/xui/inbound_modal.html @@ -110,6 +110,15 @@ if (this.inModal.inbound.settings.shadowsockses.length ==0){ this.inModal.inbound.settings.shadowsockses = [new Inbound.ShadowsocksSettings.Shadowsocks()]; } + if (["aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305"].includes(this.inModal.inbound.settings.method)) { + this.inModal.inbound.settings.shadowsockses.forEach(client => { + client.method = this.inModal.inbound.settings.method; + }) + } else { + this.inModal.inbound.settings.shadowsockses.forEach(client => { + client.method = ""; + }) + } } else { if (this.inModal.inbound.settings.shadowsockses.length > 0){ this.inModal.inbound.settings.shadowsockses = []; diff --git a/web/service/inbound.go b/web/service/inbound.go index 8655de6d..90ac2400 100644 --- a/web/service/inbound.go +++ b/web/service/inbound.go @@ -448,11 +448,16 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) { if len(client.Email) > 0 { s.AddClientStat(tx, data.Id, &client) if client.Enable { + cipher := "" + if oldInbound.Protocol == "shadowsocks" { + cipher = oldSettings["method"].(string) + } err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{ "email": client.Email, "id": client.ID, "flow": client.Flow, "password": client.Password, + "cipher": cipher, }) if err1 == nil { logger.Debug("Client added by api:", client.Email) @@ -631,11 +636,16 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin s.xrayApi.Init(p.GetAPIPort()) s.xrayApi.RemoveUser(oldInbound.Tag, oldEmail) if clients[0].Enable { + cipher := "" + if oldInbound.Protocol == "shadowsocks" { + cipher = oldSettings["method"].(string) + } err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{ "email": clients[0].Email, "id": clients[0].ID, "flow": clients[0].Flow, "password": clients[0].Password, + "cipher": cipher, }) if err1 == nil { logger.Debug("Client edited by api:", clients[0].Email) @@ -645,7 +655,6 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin } } else { logger.Debug("Client disabled by api:", clients[0].Email) - needRestart = false } s.xrayApi.Close() } else { @@ -928,11 +937,21 @@ func (s *InboundService) ResetClientTraffic(id int, clientEmail string) (bool, e for _, client := range clients { if client.Email == clientEmail { s.xrayApi.Init(p.GetAPIPort()) + cipher := "" + if string(inbound.Protocol) == "shadowsocks" { + var oldSettings map[string]interface{} + err = json.Unmarshal([]byte(inbound.Settings), &oldSettings) + if err != nil { + return false, err + } + cipher = oldSettings["method"].(string) + } err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]interface{}{ "email": client.Email, "id": client.ID, "flow": client.Flow, "password": client.Password, + "cipher": cipher, }) if err1 == nil { logger.Debug("Client enabled due to reset traffic:", clientEmail) diff --git a/web/service/xray.go b/web/service/xray.go index 668d6952..4a9bf7b2 100644 --- a/web/service/xray.go +++ b/web/service/xray.go @@ -116,7 +116,7 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) { } } for key := range c { - if key != "email" && key != "id" && key != "password" && key != "flow" { + if key != "email" && key != "id" && key != "password" && key != "flow" && key != "method" { delete(c, key) } if c["flow"] == "xtls-rprx-vision-udp443" {