diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index c8b02641..22573a23 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -1012,66 +1012,6 @@ class Inbound extends XrayCommonClass { return this.network === "http"; } - // VMess & VLess - get uuid() { - switch (this.protocol) { - case Protocols.VMESS: - return this.settings.vmesses[0].id; - case Protocols.VLESS: - return this.settings.vlesses[0].id; - default: - return ""; - } - } - - // VLess & Trojan - get flow() { - switch (this.protocol) { - case Protocols.VLESS: - return this.settings.vlesses[0].flow; - case Protocols.TROJAN: - return this.settings.trojans[0].flow; - default: - return ""; - } - } - - // VMess - get alterId() { - switch (this.protocol) { - case Protocols.VMESS: - return this.settings.vmesses[0].alterId; - default: - return ""; - } - } - - // Socks & HTTP - get username() { - switch (this.protocol) { - case Protocols.SOCKS: - case Protocols.HTTP: - return this.settings.accounts[0].user; - default: - return ""; - } - } - - // Trojan & Shadowsocks & Socks & HTTP - get password() { - switch (this.protocol) { - case Protocols.TROJAN: - return this.settings.trojans[0].password; - case Protocols.SHADOWSOCKS: - return this.settings.password; - case Protocols.SOCKS: - case Protocols.HTTP: - return this.settings.accounts[0].pass; - default: - return ""; - } - } - // Shadowsocks get method() { switch (this.protocol) { @@ -1146,9 +1086,13 @@ class Inbound extends XrayCommonClass { return this.settings.vlesses[index].expiryTime < new Date().getTime(); return false case Protocols.TROJAN: - if(this.settings.trojans[index].expiryTime > 0) - return this.settings.trojans[index].expiryTime < new Date().getTime(); - return false + if(this.settings.trojans[index].expiryTime > 0) + return this.settings.trojans[index].expiryTime < new Date().getTime(); + return false + case Protocols.SHADOWSOCKS: + if(this.settings.shadowsockses[index].expiryTime > 0) + return this.settings.shadowsockses[index].expiryTime < new Date().getTime(); + return false default: return false; } @@ -1159,7 +1103,6 @@ class Inbound extends XrayCommonClass { case Protocols.VMESS: case Protocols.VLESS: case Protocols.TROJAN: - case Protocols.SHADOWSOCKS: break; default: return false; @@ -1228,7 +1171,6 @@ class Inbound extends XrayCommonClass { case Protocols.VMESS: case Protocols.VLESS: case Protocols.TROJAN: - case Protocols.SHADOWSOCKS: return true; default: return false; @@ -1443,13 +1385,11 @@ class Inbound extends XrayCommonClass { return url.toString(); } - genSSLink(address='', remark='') { + genSSLink(address='', remark='', clientIndex = 0) { let settings = this.settings; - const server = this.stream.tls.server; - if (!ObjectUtil.isEmpty(server)) { - address = server; - } - return 'ss://' + safeBase64(settings.method + ':' + settings.password) + `@${address}:${this.port}#${encodeURIComponent(remark)}`; + const port = this.port; + + return 'ss://' + safeBase64(settings.method + ':' + settings.password + ':' +settings.shadowsockses[clientIndex].password) + '@' + address + ':' + this.port + '#' + encodeURIComponent(remark); } genTrojanLink(address = '', remark = '', clientIndex = 0) { @@ -1569,7 +1509,11 @@ class Inbound extends XrayCommonClass { remark += '-' + this.settings.vlesses[clientIndex].email } return this.genVLESSLink(address, remark, clientIndex); - case Protocols.SHADOWSOCKS: return this.genSSLink(address, remark); + case Protocols.SHADOWSOCKS: + if (this.settings.shadowsockses[clientIndex].email != ""){ + remark = this.settings.shadowsockses[clientIndex].email + } + return this.genSSLink(address, remark, clientIndex); case Protocols.TROJAN: if (this.settings.trojans[clientIndex].email != ""){ remark += '-' + this.settings.trojans[clientIndex].email @@ -2033,13 +1977,15 @@ Inbound.TrojanSettings.Fallback = class extends XrayCommonClass { Inbound.ShadowsocksSettings = class extends Inbound.Settings { constructor(protocol, method=SSMethods.BLAKE3_AES_256_GCM, - password=RandomUtil.randomSeq(44), - network='tcp,udp' + password=RandomUtil.randomShadowsocksPassword(), + network='tcp,udp', + shadowsockses=[new Inbound.ShadowsocksSettings.Shadowsocks()] ) { super(protocol); this.method = method; this.password = password; this.network = network; + this.shadowsockses = shadowsockses; } static fromJson(json={}) { @@ -2048,6 +1994,7 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings { json.method, json.password, json.network, + json.clients.map(client => Inbound.ShadowsocksSettings.Shadowsocks.fromJson(client)), ); } @@ -2056,10 +2003,77 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings { method: this.method, password: this.password, network: this.network, + clients: Inbound.ShadowsocksSettings.toJsonArray(this.shadowsockses) }; } }; +Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass { + constructor(password=RandomUtil.randomShadowsocksPassword(), email=RandomUtil.randomText(),limitIp=0, totalGB=0, expiryTime=0, enable=true, tgId='', subId='') { + super(); + this.password = password; + this.email = email; + this.limitIp = limitIp; + this.totalGB = totalGB; + this.expiryTime = expiryTime; + this.enable = enable; + this.tgId = tgId; + this.subId = subId; + } + + toJson() { + return { + password: this.password, + email: this.email, + limitIp: this.limitIp, + totalGB: this.totalGB, + expiryTime: this.expiryTime, + enable: this.enable, + tgId: this.tgId, + subId: this.subId, + }; + } + + static fromJson(json = {}) { + return new Inbound.ShadowsocksSettings.Shadowsocks( + json.password, + json.email, + json.limitIp, + json.totalGB, + json.expiryTime, + json.enable, + json.tgId, + json.subId, + ); + } + + get _expiryTime() { + if (this.expiryTime === 0 || this.expiryTime === "") { + return null; + } + if (this.expiryTime < 0){ + return this.expiryTime / -86400000; + } + return moment(this.expiryTime); + } + + set _expiryTime(t) { + if (t == null || t === "") { + this.expiryTime = 0; + } else { + this.expiryTime = t.valueOf(); + } + } + get _totalGB() { + return toFixed(this.totalGB / ONE_GB, 2); + } + + set _totalGB(gb) { + this.totalGB = toFixed(gb * ONE_GB, 0); + } + +}; + Inbound.DokodemoSettings = class extends Inbound.Settings { constructor(protocol, address, port, network='tcp,udp', followRedirect=false) { super(protocol); diff --git a/web/assets/js/util/utils.js b/web/assets/js/util/utils.js index 451f63e9..9c441537 100644 --- a/web/assets/js/util/utils.js +++ b/web/assets/js/util/utils.js @@ -165,6 +165,12 @@ class RandomUtil { str += this.randomShortIdSeq(8) return str; } + + static randomShadowsocksPassword(){ + let array = new Uint8Array(32); + window.crypto.getRandomValues(array); + return btoa(String.fromCharCode.apply(null, array)); + } } class ObjectUtil { diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index bf4ed92a..e459b520 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -44,7 +44,7 @@ if (this.clients[index].expiryTime < 0){ this.delayedStart = true; } - this.oldClientId = this.dbInbound.protocol == "trojan" ? this.clients[index].password : this.clients[index].id; + this.oldClientId = this.getClientId(dbInbound.protocol,clients[index]); } else { this.addClient(this.inbound.protocol, this.clients); } @@ -56,14 +56,23 @@ case Protocols.VMESS: return clientSettings.vmesses; case Protocols.VLESS: return clientSettings.vlesses; case Protocols.TROJAN: return clientSettings.trojans; + case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; default: return null; } }, + getClientId(protocol, client) { + switch(protocol){ + case Protocols.TROJAN: return client.password; + case Protocols.SHADOWSOCKS: return client.email; + default: return client.id; + } + }, addClient(protocol, clients) { switch (protocol) { 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()); default: return null; } }, diff --git a/web/html/xui/form/client.html b/web/html/xui/form/client.html index 501861db..1740e74b 100644 --- a/web/html/xui/form/client.html +++ b/web/html/xui/form/client.html @@ -18,7 +18,8 @@ - + + diff --git a/web/html/xui/form/protocol/shadowsocks.html b/web/html/xui/form/protocol/shadowsocks.html index 718ba894..3c63fe01 100644 --- a/web/html/xui/form/protocol/shadowsocks.html +++ b/web/html/xui/form/protocol/shadowsocks.html @@ -1,5 +1,87 @@ {{define "form/shadowsocks"}} + + + + + {{ i18n "pages.inbounds.Email" }} + + + + + + + + + + + + + + + + + + + + {{ i18n "pages.inbounds.IPLimit" }} + + + + + + + + + + {{ i18n "pages.inbounds.totalFlow" }} (GB) + + + + + + + + + + + + + + + + {{ i18n "pages.inbounds.expireDate" }} + + + + + + + + + + + + + + + + + + +
[[ col ]]
[[ col ]]
+
+
[[ method ]] @@ -15,5 +97,4 @@ UDP -
{{end}} \ No newline at end of file diff --git a/web/html/xui/form/protocol/trojan.html b/web/html/xui/form/protocol/trojan.html index e63943e6..1581b07c 100644 --- a/web/html/xui/form/protocol/trojan.html +++ b/web/html/xui/form/protocol/trojan.html @@ -53,6 +53,12 @@
+ + + + + + {{ i18n "pages.inbounds.expireDate" }} diff --git a/web/html/xui/form/protocol/vless.html b/web/html/xui/form/protocol/vless.html index 33e0c170..023c04b9 100644 --- a/web/html/xui/form/protocol/vless.html +++ b/web/html/xui/form/protocol/vless.html @@ -59,6 +59,12 @@ + + + + + + {{ i18n "pages.inbounds.expireDate" }} diff --git a/web/html/xui/form/protocol/vmess.html b/web/html/xui/form/protocol/vmess.html index 6471e20d..62b80468 100644 --- a/web/html/xui/form/protocol/vmess.html +++ b/web/html/xui/form/protocol/vmess.html @@ -50,6 +50,12 @@ + + + + + + {{ i18n "pages.inbounds.expireDate" }} diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html index 966de8dd..7c338e26 100644 --- a/web/html/xui/inbound_modal.html +++ b/web/html/xui/inbound_modal.html @@ -48,6 +48,7 @@ case Protocols.VMESS: return clientSettings.vmesses; case Protocols.VLESS: return clientSettings.vlesses; case Protocols.TROJAN: return clientSettings.trojans; + case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; default: return null; } }, diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 2792eb75..5d7e041f 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -116,15 +116,11 @@ {{ i18n "pages.inbounds.operate" }} - - - {{ i18n "qrCode" }} - {{ i18n "edit" }} -