diff options
| author | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-04-18 21:04:06 +0300 |
|---|---|---|
| committer | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-04-18 21:04:06 +0300 |
| commit | 3e0faecaaebd8394a1a9d18ec11b5a60f210b654 (patch) | |
| tree | 70226a9e7a73155d05410bda80a38673f8db2a83 | |
| parent | dc7dbae14a37492ac3a7e3822b3e0b250e248173 (diff) | |
improve reality setting
split xtls from tls - remove iran warp - remove old setting reality from franzkafka (it was a messy code) -and other improvement
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
| -rw-r--r-- | web/assets/css/custom.css | 5 | ||||
| -rw-r--r-- | web/assets/js/model/xray.js | 333 | ||||
| -rw-r--r-- | web/assets/js/util/utils.js | 46 | ||||
| -rw-r--r-- | web/controller/inbound.go | 10 | ||||
| -rw-r--r-- | web/controller/server.go | 16 | ||||
| -rw-r--r-- | web/controller/sub.go | 8 | ||||
| -rw-r--r-- | web/html/xui/client_bulk_modal.html | 46 | ||||
| -rw-r--r-- | web/html/xui/client_modal.html | 9 | ||||
| -rw-r--r-- | web/html/xui/form/client.html | 6 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/trojan.html | 4 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vless.html | 4 | ||||
| -rw-r--r-- | web/html/xui/form/protocol/vmess.html | 2 | ||||
| -rw-r--r-- | web/html/xui/form/tls_settings.html | 92 | ||||
| -rw-r--r-- | web/html/xui/inbound_info_modal.html | 6 | ||||
| -rw-r--r-- | web/html/xui/inbound_modal.html | 55 | ||||
| -rw-r--r-- | web/html/xui/inbounds.html | 34 | ||||
| -rw-r--r-- | web/html/xui/setting.html | 18 | ||||
| -rw-r--r-- | web/service/inbound.go | 167 | ||||
| -rw-r--r-- | web/service/server.go | 26 | ||||
| -rw-r--r-- | web/service/sub.go | 70 |
20 files changed, 630 insertions, 327 deletions
diff --git a/web/assets/css/custom.css b/web/assets/css/custom.css index 229d8500..741b01ae 100644 --- a/web/assets/css/custom.css +++ b/web/assets/css/custom.css @@ -246,6 +246,11 @@ background-color: #2e3b52; } +.ant-card-dark .ant-select-disabled .ant-select-selection { + border: 1px solid rgba(255, 255, 255, 0.2); + background-color: #242c3a; +} + .ant-card-dark .ant-collapse-item { color: hsla(0,0%,100%,.65); background-color: #161b22; diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index f5c7da3f..3e3ff9cb 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -49,6 +49,7 @@ const XTLS_FLOW_CONTROL = { const TLS_FLOW_CONTROL = { VISION: "xtls-rprx-vision", + VISION_UDP443: "xtls-rprx-vision-udp443", }; const TLS_VERSION_OPTION = { @@ -91,9 +92,6 @@ const UTLS_FINGERPRINT = { UTLS_RANDOMIZED: "randomized", }; -const bytesToHex = e => Array.from(e).map(e => e.toString(16).padStart(2, 0)).join(''); -const hexToBytes = e => new Uint8Array(e.match(/[0-9a-f]{2}/gi).map(e => parseInt(e, 16))); - const ALPN_OPTION = { H3: "h3", H2: "h2", @@ -481,7 +479,7 @@ class TlsStreamSettings extends XrayCommonClass { cipherSuites = '', certificates=[new TlsStreamSettings.Cert()], alpn=[ALPN_OPTION.H2,ALPN_OPTION.HTTP1], - settings=[new TlsStreamSettings.Settings()]) { + settings=new TlsStreamSettings.Settings()) { super(); this.server = serverName; this.minVersion = minVersion; @@ -508,8 +506,7 @@ class TlsStreamSettings extends XrayCommonClass { } if (!ObjectUtil.isEmpty(json.settings)) { - let values = json.settings[0]; - settings = [new TlsStreamSettings.Settings(values.allowInsecure , values.fingerprint, values.serverName)]; + settings = new TlsStreamSettings.Settings(json.settings.allowInsecure , json.settings.fingerprint, json.settings.serverName); } return new TlsStreamSettings( json.serverName, @@ -530,7 +527,7 @@ class TlsStreamSettings extends XrayCommonClass { cipherSuites: this.cipherSuites, certificates: TlsStreamSettings.toJsonArray(this.certs), alpn: this.alpn, - settings: TlsStreamSettings.toJsonArray(this.settings), + settings: this.settings, }; } } @@ -598,71 +595,204 @@ TlsStreamSettings.Settings = class extends XrayCommonClass { }; } }; +class XtlsStreamSettings extends XrayCommonClass { + constructor(serverName='', + certificates=[new XtlsStreamSettings.Cert()], + alpn=[ALPN_OPTION.H2,ALPN_OPTION.HTTP1], + settings=new XtlsStreamSettings.Settings()) { + super(); + this.server = serverName; + this.certs = certificates; + this.alpn = alpn; + this.settings = settings; + } + + addCert(cert) { + this.certs.push(cert); + } + + removeCert(index) { + this.certs.splice(index, 1); + } + + static fromJson(json={}) { + let certs; + let settings; + if (!ObjectUtil.isEmpty(json.certificates)) { + certs = json.certificates.map(cert => XtlsStreamSettings.Cert.fromJson(cert)); + } + + if (!ObjectUtil.isEmpty(json.settings)) { + settings = new XtlsStreamSettings.Settings(json.settings.allowInsecure , json.settings.serverName); + } + return new XtlsStreamSettings( + json.serverName, + certs, + json.alpn, + settings, + ); + } + + toJson() { + return { + serverName: this.server, + certificates: XtlsStreamSettings.toJsonArray(this.certs), + alpn: this.alpn, + settings: this.settings, + }; + } +} + +XtlsStreamSettings.Cert = class extends XrayCommonClass { + constructor(useFile=true, certificateFile='', keyFile='', certificate='', key='') { + super(); + this.useFile = useFile; + this.certFile = certificateFile; + this.keyFile = keyFile; + this.cert = certificate instanceof Array ? certificate.join('\n') : certificate; + this.key = key instanceof Array ? key.join('\n') : key; + } + + static fromJson(json={}) { + if ('certificateFile' in json && 'keyFile' in json) { + return new XtlsStreamSettings.Cert( + true, + json.certificateFile, + json.keyFile, + ); + } else { + return new XtlsStreamSettings.Cert( + false, '', '', + json.certificate.join('\n'), + json.key.join('\n'), + ); + } + } + + toJson() { + if (this.useFile) { + return { + certificateFile: this.certFile, + keyFile: this.keyFile, + }; + } else { + return { + certificate: this.cert.split('\n'), + key: this.key.split('\n'), + }; + } + } +}; + +XtlsStreamSettings.Settings = class extends XrayCommonClass { + constructor(allowInsecure = false, serverName = '') { + super(); + this.allowInsecure = allowInsecure; + this.serverName = serverName; + } + static fromJson(json = {}) { + return new XtlsStreamSettings.Settings( + json.allowInsecure, + json.servername, + ); + } + toJson() { + return { + allowInsecure: this.allowInsecure, + serverName: this.serverName, + }; + } +}; class RealityStreamSettings extends XrayCommonClass { constructor( show = false,xver = 0, - fingerprint = UTLS_FINGERPRINT.UTLS_FIREFOX, dest = 'yahoo.com:443', serverNames = 'yahoo.com,www.yahoo.com', - privateKey = RandomUtil.randomX25519PrivateKey(), - publicKey = '', + privateKey = '', minClient = '', maxClient = '', maxTimediff = 0, - shortIds = RandomUtil.randowShortId() - ) - { + shortIds = RandomUtil.randowShortId(), + settings= new RealityStreamSettings.Settings() + ){ super(); this.show = show; this.xver = xver; - this.fingerprint = fingerprint; this.dest = dest; this.serverNames = serverNames instanceof Array ? serverNames.join(",") : serverNames; this.privateKey = privateKey; - this.publicKey = RandomUtil.randomX25519PublicKey(this.privateKey); this.minClient = minClient; this.maxClient = maxClient; this.maxTimediff = maxTimediff; this.shortIds = shortIds instanceof Array ? shortIds.join(",") : shortIds; + this.settings = settings; + } + + static fromJson(json = {}) { + let settings; + if (!ObjectUtil.isEmpty(json.settings)) { + settings = new RealityStreamSettings.Settings(json.settings.publicKey , json.settings.fingerprint, json.settings.serverName); } - static fromJson(json = {}) { return new RealityStreamSettings( json.show, json.xver, - json.fingerprint, json.dest, json.serverNames, json.privateKey, - json.publicKey, json.minClient, json.maxClient, json.maxTimediff, - json.shortIds + json.shortIds, + json.settings, ); - } - toJson() { + + } + toJson() { return { show: this.show, xver: this.xver, - fingerprint: this.fingerprint, dest: this.dest, - serverNames: this.serverNames.split(/,|,|\s+/), + serverNames: this.serverNames.split(","), privateKey: this.privateKey, - publicKey: this.publicKey, minClient: this.minClient, maxClient: this.maxClient, maxTimediff: this.maxTimediff, - shortIds: this.shortIds.split(/,|,|\s+/) - }; - } + shortIds: this.shortIds.split(","), + settings: this.settings, + }; } +} + +RealityStreamSettings.Settings = class extends XrayCommonClass { + constructor(publicKey = '', fingerprint = UTLS_FINGERPRINT.UTLS_FIREFOX, serverName = '') { + super(); + this.publicKey = publicKey; + this.fingerprint = fingerprint; + this.serverName = serverName; + } + static fromJson(json = {}) { + return new RealityStreamSettings.Settings( + json.publicKey, + json.fingerprint, + json.serverName, + ); + } + toJson() { + return { + publicKey: this.publicKey, + fingerprint: this.fingerprint, + serverName: this.serverName, + }; + } +}; class StreamSettings extends XrayCommonClass { constructor(network='tcp', security='none', tlsSettings=new TlsStreamSettings(), + xtlsSettings=new XtlsStreamSettings(), realitySettings = new RealityStreamSettings(), tcpSettings=new TcpStreamSettings(), kcpSettings=new KcpStreamSettings(), @@ -675,6 +805,7 @@ class StreamSettings extends XrayCommonClass { this.network = network; this.security = security; this.tls = tlsSettings; + this.xtls = xtlsSettings; this.reality = realitySettings; this.tcp = tcpSettings; this.kcp = kcpSettings; @@ -685,7 +816,7 @@ class StreamSettings extends XrayCommonClass { } get isTls() { - return this.security === 'tls'; + return this.security === "tls"; } set isTls(isTls) { @@ -696,12 +827,12 @@ class StreamSettings extends XrayCommonClass { } } - get isXTLS() { + get isXtls() { return this.security === "xtls"; } - set isXTLS(isXTLS) { - if (isXTLS) { + set isXtls(isXtls) { + if (isXtls) { this.security = 'xtls'; } else { this.security = 'none'; @@ -715,27 +846,19 @@ class StreamSettings extends XrayCommonClass { set isReality(isReality) { if (isReality) { - this.security = "reality"; + this.security = 'reality'; } else { - this.security = "none"; + this.security = 'none'; } } - - static fromJson(json = {}) { - let tls, reality; - if (json.security === "xtls") { - tls = TlsStreamSettings.fromJson(json.XTLSSettings); - } else if (json.security === "tls") { - tls = TlsStreamSettings.fromJson(json.tlsSettings); - } - if (json.security === "reality") { - reality = RealityStreamSettings.fromJson(json.realitySettings) - } + + static fromJson(json={}) { return new StreamSettings( json.network, json.security, - tls, - reality, + TlsStreamSettings.fromJson(json.tlsSettings), + XtlsStreamSettings.fromJson(json.xtlsSettings), + RealityStreamSettings.fromJson(json.realitySettings), TcpStreamSettings.fromJson(json.tcpSettings), KcpStreamSettings.fromJson(json.kcpSettings), WsStreamSettings.fromJson(json.wsSettings), @@ -751,9 +874,9 @@ class StreamSettings extends XrayCommonClass { network: network, security: this.security, tlsSettings: this.isTls ? this.tls.toJson() : undefined, - XTLSSettings: this.isXTLS ? this.tls.toJson() : undefined, - tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined, + xtlsSettings: this.isXtls ? this.xtls.toJson() : undefined, realitySettings: this.isReality ? this.reality.toJson() : undefined, + tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined, kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined, wsSettings: network === 'ws' ? this.ws.toJson() : undefined, httpSettings: network === 'http' ? this.http.toJson() : undefined, @@ -826,22 +949,18 @@ class Inbound extends XrayCommonClass { set tls(isTls) { if (isTls) { - this.xtls = false; - this.reality = false; this.stream.security = 'tls'; } else { this.stream.security = 'none'; } } - get XTLS() { + get xtls() { return this.stream.security === 'xtls'; } - set XTLS(isXTLS) { - if (isXTLS) { - this.xtls = false; - this.reality = false; + set xtls(isXtls) { + if (isXtls) { this.stream.security = 'xtls'; } else { this.stream.security = 'none'; @@ -850,19 +969,14 @@ class Inbound extends XrayCommonClass { //for Reality get reality() { - if (this.stream.security === "reality") { - return this.network === "tcp" || this.network === "grpc" || this.network === "http"; - } - return false; + return this.stream.security === 'reality'; } set reality(isReality) { if (isReality) { - this.tls = false; - this.xtls = false; - this.stream.security = "reality"; + this.stream.security = 'reality'; } else { - this.stream.security = "none"; + this.stream.security = 'none'; } } @@ -969,7 +1083,7 @@ class Inbound extends XrayCommonClass { } get serverName() { - if (this.stream.isTls || this.stream.isXTLS) { + if (this.stream.isTls || this.stream.isXtls || this.stream.isReality) { return this.stream.tls.server; } return ""; @@ -1070,7 +1184,14 @@ class Inbound extends XrayCommonClass { default: return false; } - return this.network === "tcp" || this.network === "grpc" || this.network === "http"; + switch (this.network) { + case "tcp": + case "http": + case "grpc": + return true; + default: + return false; + } } //this is used for xtls-rprx-vision @@ -1090,7 +1211,7 @@ class Inbound extends XrayCommonClass { return this.canEnableTls(); } - canEnableXTLS() { + canEnableXtls() { switch (this.protocol) { case Protocols.VLESS: case Protocols.TROJAN: @@ -1195,10 +1316,10 @@ class Inbound extends XrayCommonClass { host: host, path: path, tls: this.stream.security, - sni: this.stream.tls.settings[0]['serverName'], - fp: this.stream.tls.settings[0]['fingerprint'], + sni: this.stream.tls.settings.serverName, + fp: this.stream.tls.settings.fingerprint, alpn: this.stream.tls.alpn.join(','), - allowInsecure: this.stream.tls.settings[0].allowInsecure, + allowInsecure: this.stream.tls.settings.allowInsecure, }; return 'vmess://' + base64(JSON.stringify(obj, null, 2)); } @@ -1257,54 +1378,54 @@ class Inbound extends XrayCommonClass { if (this.tls) { params.set("security", "tls"); - params.set("fp" , this.stream.tls.settings[0]['fingerprint']); + params.set("fp" , this.stream.tls.settings.fingerprint); params.set("alpn", this.stream.tls.alpn); - if(this.stream.tls.settings[0].allowInsecure){ + if(this.stream.tls.settings.allowInsecure){ params.set("allowInsecure", "1"); } if (!ObjectUtil.isEmpty(this.stream.tls.server)) { address = this.stream.tls.server; } - if (this.stream.tls.settings[0]['serverName'] !== ''){ - params.set("sni", this.stream.tls.settings[0]['serverName']); + if (this.stream.tls.settings.serverName !== ''){ + params.set("sni", this.stream.tls.settings.serverName); } if (type === "tcp" && this.settings.vlesses[clientIndex].flow.length > 0) { params.set("flow", this.settings.vlesses[clientIndex].flow); } } - if (this.XTLS) { + if (this.xtls) { params.set("security", "xtls"); - params.set("alpn", this.stream.tls.alpn); - if(this.stream.tls.settings[0].allowInsecure){ + params.set("alpn", this.stream.xtls.alpn); + if(this.stream.xtls.settings.allowInsecure){ params.set("allowInsecure", "1"); } - if (!ObjectUtil.isEmpty(this.stream.tls.server)) { - address = this.stream.tls.server; - } + if (!ObjectUtil.isEmpty(this.stream.xtls.server)) { + address = this.stream.xtls.server; + } params.set("flow", this.settings.vlesses[clientIndex].flow); } if (this.reality) { params.set("security", "reality"); + params.set("pbk", this.stream.reality.settings.publicKey); if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) { - params.set("sni", this.stream.reality.serverNames.split(/,|,|\s+/)[0]); - } - if (this.stream.reality.publicKey != "") { - //params.set("pbk", Ed25519.getPublicKey(this.stream.reality.privateKey)); - params.set("pbk", this.stream.reality.publicKey); + params.set("sni", this.stream.reality.serverNames.split(",")[0]); } if (this.stream.network === 'tcp') { params.set("flow", this.settings.vlesses[clientIndex].flow); } if (this.stream.reality.shortIds != "") { - params.set("sid", this.stream.reality.shortIds); + params.set("sid", this.stream.reality.shortIds.split(",")[0]); + } + if (this.stream.reality.settings.fingerprint != "") { + params.set("fp", this.stream.reality.settings.fingerprint); } - if (this.stream.reality.fingerprint != "") { - params.set("fp", this.stream.reality.fingerprint); + if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { + address = this.stream.reality.settings.serverName; } } - + const link = `vless://${uuid}@${address}:${port}`; const url = new URL(link); for (const [key, value] of params) { @@ -1376,47 +1497,47 @@ class Inbound extends XrayCommonClass { if (this.tls) { params.set("security", "tls"); - params.set("fp" , this.stream.tls.settings[0]['fingerprint']); + params.set("fp" , this.stream.tls.settings.fingerprint); params.set("alpn", this.stream.tls.alpn); - if(this.stream.tls.settings[0].allowInsecure){ + if(this.stream.tls.settings.allowInsecure){ params.set("allowInsecure", "1"); } if (!ObjectUtil.isEmpty(this.stream.tls.server)) { address = this.stream.tls.server; } - if (this.stream.tls.settings[0]['serverName'] !== ''){ - params.set("sni", this.stream.tls.settings[0]['serverName']); + if (this.stream.tls.settings.serverName !== ''){ + params.set("sni", this.stream.tls.settings.serverName); } } if (this.reality) { params.set("security", "reality"); + params.set("pbk", this.stream.reality.settings.publicKey); if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) { - params.set("sni", this.stream.reality.serverNames.split(/,|,|\s+/)[0]); + params.set("sni", this.stream.reality.serverNames.split(",")[0]); } - if (this.stream.reality.publicKey != "") { - //params.set("pbk", Ed25519.getPublicKey(this.stream.reality.privateKey)); - params.set("pbk", this.stream.reality.publicKey); - } - if (this.stream.network === 'tcp') { - params.set("flow", this.settings.trojans[clientIndex].flow); + if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { + address = this.stream.reality.settings.serverName; } if (this.stream.reality.shortIds != "") { - params.set("sid", this.stream.reality.shortIds); + params.set("sid", this.stream.reality.shortIds.split(",")[0]); + } + if (this.stream.reality.settings.fingerprint != "") { + params.set("fp", this.stream.reality.settings.fingerprint); } - if (this.stream.reality.fingerprint != "") { - params.set("fp", this.stream.reality.fingerprint); + if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { + address = this.stream.reality.settings.serverName; } } - if (this.XTLS) { + if (this.xtls) { params.set("security", "xtls"); - params.set("alpn", this.stream.tls.alpn); - if(this.stream.tls.settings[0].allowInsecure){ + params.set("alpn", this.stream.xtls.alpn); + if(this.stream.xtls.settings.allowInsecure){ params.set("allowInsecure", "1"); } if (!ObjectUtil.isEmpty(this.stream.tls.server)) { - address = this.stream.tls.server; + address = this.stream.xtls.server; } params.set("flow", this.settings.trojans[clientIndex].flow); } diff --git a/web/assets/js/util/utils.js b/web/assets/js/util/utils.js index 405985da..451f63e9 100644 --- a/web/assets/js/util/utils.js +++ b/web/assets/js/util/utils.js @@ -94,26 +94,6 @@ const shortIdSeq = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ]; -const x25519Map = new Map( - [ - ['EH2FWe-Ij_FFAa2u9__-aiErLvVIneP601GOCdlyPWw', "goY3OtfaA4UYbiz7Hn0NysI5QJrK0VT_Chg6RLgUPQU"], - ['cKI_6DoMSP1IepeWWXrG3G9nkehl94KYBhagU50g2U0', "VigpKFbSLnHLzBWobZaS1IBmw--giJ51w92y723ajnU"], - ['qM2SNyK3NyHB6deWpEP3ITyCGKQFRTna_mlKP0w1QH0', "HYyIGuyNFslmcnNT7mrDdmuXwn4cm7smE_FZbYguKHQ"], - ['qCWg5GMEDFd3n1nxDswlIpOHoPUXMLuMOIiLUVzubkI', "rJFC3dUjJxMnVZiUGzmf_LFsJUwFWY-CU5RQgFOHCWM"], - ['4NOBxDrEsOhNI3Y3EnVIy_TN-uyBoAjQw6QM0YsOi0s', "CbcY9qc4YuMDJDyyL0OITlU824TBg1O84ClPy27e2RM"], - ['eBvFb0M4HpSOwWjtXV8zliiEs_hg56zX4a2LpuuqpEI', "CjulQ2qVIky7ImIfysgQhNX7s_drGLheCGSkVHcLZhc"], - ['yEpOzQV04NNcycWVeWtRNTzv5TS-ynTuKRacZCH-6U8', "O9RSr5gSdok2K_tobQnf_scyKVqnCx6C4Jrl7_rCZEQ"], - ['CNt6TAUVCwqM6xIBHyni0K3Zqbn2htKQLvLb6XDgh0s', "d9cGLVBrDFS02L2OvkqyqwFZ1Ux3AHs28ehl4Rwiyl0"], - ['EInKw-6Wr0rAHXlxxDuZU5mByIzcD3Z-_iWPzXlUL1k', "LlYD2nNVAvyjNvjZGZh4R8PkMIwkc6EycPTvR2LE0nQ"], - ['GKIKo7rcXVyle-EUHtGIDtYnDsI6osQmOUl3DTJRAGc', "VcqHivYGGoBkcxOI6cSSjQmneltstkb2OhvO53dyhEM"], - ['-FVDzv68IC17fJVlNDlhrrgX44WeBfbhwjWpCQVXGHE', "PGG2EYOvsFt2lAQTD7lqHeRxz2KxvllEDKcUrtizPBU"], - ['0H3OJEYEu6XW7woqy7cKh2vzg6YHkbF_xSDTHKyrsn4', "mzevpYbS8kXengBY5p7tt56QE4tS3lwlwRemmkcQeyc"], - ['8F8XywN6ci44ES6em2Z0fYYxyptB9uaXY9Hc1WSSPE4', "qCZUdWQZ2H33vWXnOkG8NpxBeq3qn5QWXlfCOWBNkkc"], - ['IN0dqfkC10dj-ifRHrg2PmmOrzYs697ajGMwcLbu-1g', "2UW_EO3r7uczPGUUlpJBnMDpDmWUHE2yDzCmXS4sckE"], - ['uIcmks5rAhvBe4dRaJOdeSqgxLGGMZhsGk4J4PEKL2s', "F9WJV_74IZp0Ide4hWjiJXk9FRtBUBkUr3mzU-q1lzk"], - ] -); - class RandomUtil { static randomIntRange(min, max) { @@ -170,26 +150,6 @@ class RandomUtil { }); } - static randowShortId() { - let str = ''; - str += this.randomShortIdSeq(8) - return str; - } - - static randomX25519PrivateKey() { - let num = x25519Map.size; - let index = this.randomInt(num); - let cntr = 0; - for (let key of x25519Map.keys()) { - if (cntr++ === index) { - return key; - } - } - } - - static randomX25519PublicKey(key) { - return x25519Map.get(key) - } static randomText() { var chars = 'abcdefghijklmnopqrstuvwxyz1234567890'; var string = ''; @@ -199,6 +159,12 @@ class RandomUtil { } return string; } + + static randowShortId() { + let str = ''; + str += this.randomShortIdSeq(8) + return str; + } } class ObjectUtil { diff --git a/web/controller/inbound.go b/web/controller/inbound.go index f7ea35eb..8e385248 100644 --- a/web/controller/inbound.go +++ b/web/controller/inbound.go @@ -33,7 +33,7 @@ func (a *InboundController) initRouter(g *gin.RouterGroup) { g.POST("/update/:id", a.updateInbound) g.POST("/clientIps/:email", a.getClientIps) g.POST("/clearClientIps/:email", a.clearClientIps) - g.POST("/addClient/", a.addInboundClient) + g.POST("/addClient", a.addInboundClient) g.POST("/delClient/:email", a.delInboundClient) g.POST("/updateClient/:index", a.updateInboundClient) g.POST("/:id/resetClientTraffic/:email", a.resetClientTraffic) @@ -151,19 +151,19 @@ func (a *InboundController) clearClientIps(c *gin.Context) { jsonMsg(c, "Log Cleared", nil) } func (a *InboundController) addInboundClient(c *gin.Context) { - inbound := &model.Inbound{} - err := c.ShouldBind(inbound) + data := &model.Inbound{} + err := c.ShouldBind(data) if err != nil { jsonMsg(c, I18n(c, "pages.inbounds.revise"), err) return } - err = a.inboundService.AddInboundClient(inbound) + err = a.inboundService.AddInboundClient(data) if err != nil { jsonMsg(c, "something worng!", err) return } - jsonMsg(c, "Client added", nil) + jsonMsg(c, "Client(s) added", nil) if err == nil { a.xrayService.SetToNeedRestart() } diff --git a/web/controller/server.go b/web/controller/server.go index 24c3d623..c365ae4b 100644 --- a/web/controller/server.go +++ b/web/controller/server.go @@ -41,6 +41,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) { g.POST("/logs/:count", a.getLogs) g.POST("/getConfigJson", a.getConfigJson) g.GET("/getDb", a.getDb) + g.POST("/getNewX25519Cert", a.getNewX25519Cert) } func (a *ServerController) refreshStatus() { @@ -114,7 +115,7 @@ func (a *ServerController) getLogs(c *gin.Context) { count := c.Param("count") logs, err := a.serverService.GetLogs(count) if err != nil { - jsonMsg(c, I18n(c, "getLogs"), err) + jsonMsg(c, "getLogs", err) return } jsonObj(c, logs, nil) @@ -123,7 +124,7 @@ func (a *ServerController) getLogs(c *gin.Context) { func (a *ServerController) getConfigJson(c *gin.Context) { configJson, err := a.serverService.GetConfigJson() if err != nil { - jsonMsg(c, I18n(c, "getLogs"), err) + jsonMsg(c, "get config.json", err) return } jsonObj(c, configJson, nil) @@ -132,7 +133,7 @@ func (a *ServerController) getConfigJson(c *gin.Context) { func (a *ServerController) getDb(c *gin.Context) { db, err := a.serverService.GetDb() if err != nil { - jsonMsg(c, I18n(c, "getLogs"), err) + jsonMsg(c, "get Database", err) return } // Set the headers for the response @@ -142,3 +143,12 @@ func (a *ServerController) getDb(c *gin.Context) { // Write the file contents to the response c.Writer.Write(db) } + +func (a *ServerController) getNewX25519Cert(c *gin.Context) { + cert, err := a.serverService.GetNewX25519Cert() + if err != nil { + jsonMsg(c, "get x25519 certificate", err) + return + } + jsonObj(c, cert, nil) +} diff --git a/web/controller/sub.go b/web/controller/sub.go index 5695f032..9a8dfc19 100644 --- a/web/controller/sub.go +++ b/web/controller/sub.go @@ -29,14 +29,18 @@ func (a *SUBController) initRouter(g *gin.RouterGroup) { func (a *SUBController) subs(c *gin.Context) { subId := c.Param("subid") host := strings.Split(c.Request.Host, ":")[0] - subs, err := a.subService.GetSubs(subId, host) - if err != nil { + subs, header, err := a.subService.GetSubs(subId, host) + if err != nil || len(subs) == 0 { c.String(400, "Error!") } else { result := "" for _, sub := range subs { result += sub + "\n" } + + // Add subscription-userinfo + c.Writer.Header().Set("subscription-userinfo", header) + c.String(200, base64.StdEncoding.EncodeToString([]byte(result))) } } diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html index 4e282ccd..46bc6657 100644 --- a/web/html/xui/client_bulk_modal.html +++ b/web/html/xui/client_bulk_modal.html @@ -33,6 +33,30 @@ <span slot="label">{{ i18n "pages.client.clientCount" }}</span> <a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number> </a-form-item> + <a-form-item> + <span slot="label"> + <span>{{ i18n "pages.inbounds.IPLimit" }}</span> + <a-tooltip> + <template slot="title"> + <span>{{ i18n "pages.inbounds.IPLimitDesc" }}</span> + </template> + <a-icon type="question-circle" theme="filled"></a-icon> + </a-tooltip> + </span> + <a-input type="number" v-model.number="clientsBulkModal.limitIp" min="0" style="width: 70px;" ></a-input> + </a-form-item> + <a-form-item v-if="clientsBulkModal.inbound.xtls" label="Flow"> + <a-select v-model="clientsBulkModal.flow" style="width: 150px" :dropdown-class-name="siderDrawer.isDarkTheme ? 'ant-card-dark' : ''"> + <a-select-option value="">{{ i18n "none" }}</a-select-option> + <a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option> + </a-select> + </a-form-item> + <a-form-item v-if="clientsBulkModal.inbound.canEnableTlsFlow()" label="Flow" layout="inline"> + <a-select v-model="clientsBulkModal.flow" style="width: 150px"> + <a-select-option value="" selected>{{ i18n "none" }}</a-select-option> + <a-select-option v-for="key in TLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option> + </a-select> + </a-form-item> <a-form-item label="Subscription"> <a-input v-model.trim="clientsBulkModal.subId"></a-input> </
|
