diff options
| author | mhsanaei <ho3ein.sanaei@gmail.com> | 2024-10-30 16:40:41 +0300 |
|---|---|---|
| committer | mhsanaei <ho3ein.sanaei@gmail.com> | 2024-10-30 16:46:27 +0300 |
| commit | 19a31686da26c0c8a8f0ee255d3b0728524bb95f (patch) | |
| tree | 89cb854958e838f3e41ea2ff4de8823585eaab7b /web/assets/js/model/inbound.js | |
| parent | 13f7e071285f57327c8c741d5c691ddf2a9f9621 (diff) | |
REALITY: SplitHTTP transport
Diffstat (limited to 'web/assets/js/model/inbound.js')
| -rw-r--r-- | web/assets/js/model/inbound.js | 2531 |
1 files changed, 2531 insertions, 0 deletions
diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js new file mode 100644 index 00000000..ea6f56fa --- /dev/null +++ b/web/assets/js/model/inbound.js @@ -0,0 +1,2531 @@ +const Protocols = { + VMESS: 'vmess', + VLESS: 'vless', + TROJAN: 'trojan', + SHADOWSOCKS: 'shadowsocks', + DOKODEMO: 'dokodemo-door', + SOCKS: 'socks', + HTTP: 'http', + WIREGUARD: 'wireguard', +}; + +const SSMethods = { + AES_256_GCM: 'aes-256-gcm', + AES_128_GCM: 'aes-128-gcm', + CHACHA20_POLY1305: 'chacha20-poly1305', + CHACHA20_IETF_POLY1305: 'chacha20-ietf-poly1305', + XCHACHA20_POLY1305: 'xchacha20-poly1305', + XCHACHA20_IETF_POLY1305: 'xchacha20-ietf-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', +}; + +const TLS_FLOW_CONTROL = { + VISION: "xtls-rprx-vision", + VISION_UDP443: "xtls-rprx-vision-udp443", +}; + +const TLS_VERSION_OPTION = { + TLS10: "1.0", + TLS11: "1.1", + TLS12: "1.2", + TLS13: "1.3", +}; + +const TLS_CIPHER_OPTION = { + RSA_AES_128_CBC: "TLS_RSA_WITH_AES_128_CBC_SHA", + RSA_AES_256_CBC: "TLS_RSA_WITH_AES_256_CBC_SHA", + RSA_AES_128_GCM: "TLS_RSA_WITH_AES_128_GCM_SHA256", + RSA_AES_256_GCM: "TLS_RSA_WITH_AES_256_GCM_SHA384", + AES_128_GCM: "TLS_AES_128_GCM_SHA256", + AES_256_GCM: "TLS_AES_256_GCM_SHA384", + CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256", + ECDHE_ECDSA_AES_128_CBC: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + ECDHE_ECDSA_AES_256_CBC: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + ECDHE_RSA_AES_128_CBC: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + ECDHE_RSA_AES_256_CBC: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", + ECDHE_ECDSA_AES_128_GCM: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + ECDHE_ECDSA_AES_256_GCM: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + ECDHE_RSA_AES_128_GCM: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + ECDHE_RSA_AES_256_GCM: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + ECDHE_ECDSA_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", + ECDHE_RSA_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", +}; + +const UTLS_FINGERPRINT = { + UTLS_CHROME: "chrome", + UTLS_FIREFOX: "firefox", + UTLS_SAFARI: "safari", + UTLS_IOS: "ios", + UTLS_android: "android", + UTLS_EDGE: "edge", + UTLS_360: "360", + UTLS_QQ: "qq", + UTLS_RANDOM: "random", + UTLS_RANDOMIZED: "randomized", +}; + +const ALPN_OPTION = { + H3: "h3", + H2: "h2", + HTTP1: "http/1.1", +}; + +const SNIFFING_OPTION = { + HTTP: "http", + TLS: "tls", + QUIC: "quic", + FAKEDNS: "fakedns" +}; + +const USAGE_OPTION = { + ENCIPHERMENT: "encipherment", + VERIFY: "verify", + ISSUE: "issue", +}; + +const DOMAIN_STRATEGY_OPTION = { + AS_IS: "AsIs", + USE_IP: "UseIP", + USE_IPV6V4: "UseIPv6v4", + USE_IPV6: "UseIPv6", + USE_IPV4V6: "UseIPv4v6", + USE_IPV4: "UseIPv4", + FORCE_IP: "ForceIP", + FORCE_IPV6V4: "ForceIPv6v4", + FORCE_IPV6: "ForceIPv6", + FORCE_IPV4V6: "ForceIPv4v6", + FORCE_IPV4: "ForceIPv4", +}; + +const TCP_CONGESTION_OPTION = { + BBR: "bbr", + CUBIC: "cubic", + RENO: "reno", +}; + +const USERS_SECURITY = { + AES_128_GCM: "aes-128-gcm", + CHACHA20_POLY1305: "chacha20-poly1305", + AUTO: "auto", + NONE: "none", + ZERO: "zero", +}; + +Object.freeze(Protocols); +Object.freeze(SSMethods); +Object.freeze(TLS_FLOW_CONTROL); +Object.freeze(TLS_VERSION_OPTION); +Object.freeze(TLS_CIPHER_OPTION); +Object.freeze(UTLS_FINGERPRINT); +Object.freeze(ALPN_OPTION); +Object.freeze(SNIFFING_OPTION); +Object.freeze(USAGE_OPTION); +Object.freeze(DOMAIN_STRATEGY_OPTION); +Object.freeze(TCP_CONGESTION_OPTION); +Object.freeze(USERS_SECURITY); + +class XrayCommonClass { + + static toJsonArray(arr) { + return arr.map(obj => obj.toJson()); + } + + static fromJson() { + return new XrayCommonClass(); + } + + toJson() { + return this; + } + + toString(format = true) { + return format ? JSON.stringify(this.toJson(), null, 2) : JSON.stringify(this.toJson()); + } + + static toHeaders(v2Headers) { + let newHeaders = []; + if (v2Headers) { + Object.keys(v2Headers).forEach(key => { + let values = v2Headers[key]; + if (typeof (values) === 'string') { + newHeaders.push({ name: key, value: values }); + } else { + for (let i = 0; i < values.length; ++i) { + newHeaders.push({ name: key, value: values[i] }); + } + } + }); + } + return newHeaders; + } + + static toV2Headers(headers, arr = true) { + let v2Headers = {}; + for (let i = 0; i < headers.length; ++i) { + let name = headers[i].name; + let value = headers[i].value; + if (ObjectUtil.isEmpty(name) || ObjectUtil.isEmpty(value)) { + continue; + } + if (!(name in v2Headers)) { + v2Headers[name] = arr ? [value] : value; + } else { + if (arr) { + v2Headers[name].push(value); + } else { + v2Headers[name] = value; + } + } + } + return v2Headers; + } +} + +class TcpStreamSettings extends XrayCommonClass { + constructor( + acceptProxyProtocol = false, + type = 'none', + request = new TcpStreamSettings.TcpRequest(), + response = new TcpStreamSettings.TcpResponse(), + ) { + super(); + this.acceptProxyProtocol = acceptProxyProtocol; + this.type = type; + this.request = request; + this.response = response; + } + + static fromJson(json = {}) { + let header = json.header; + if (!header) { + header = {}; + } + return new TcpStreamSettings(json.acceptProxyProtocol, + header.type, + TcpStreamSettings.TcpRequest.fromJson(header.request), + TcpStreamSettings.TcpResponse.fromJson(header.response), + ); + } + + toJson() { + return { + acceptProxyProtocol: this.acceptProxyProtocol, + header: { + type: this.type, + request: this.type === 'http' ? this.request.toJson() : undefined, + response: this.type === 'http' ? this.response.toJson() : undefined, + }, + }; + } +} + +TcpStreamSettings.TcpRequest = class extends XrayCommonClass { + constructor( + version = '1.1', + method = 'GET', + path = ['/'], + headers = [], + ) { + super(); + this.version = version; + this.method = method; + this.path = path.length === 0 ? ['/'] : path; + this.headers = headers; + } + + addPath(path) { + this.path.push(path); + } + + removePath(index) { + this.path.splice(index, 1); + } + + addHeader(name, value) { + this.headers.push({ name: name, value: value }); + } + + removeHeader(index) { + this.headers.splice(index, 1); + } + + static fromJson(json = {}) { + return new TcpStreamSettings.TcpRequest( + json.version, + json.method, + json.path, + XrayCommonClass.toHeaders(json.headers), + ); + } + + toJson() { + return { + version: this.version, + method: this.method, + path: ObjectUtil.clone(this.path), + headers: XrayCommonClass.toV2Headers(this.headers), + }; + } +}; + +TcpStreamSettings.TcpResponse = class extends XrayCommonClass { + constructor( + version = '1.1', + status = '200', + reason = 'OK', + headers = [], + ) { + super(); + this.version = version; + this.status = status; + this.reason = reason; + this.headers = headers; + } + + addHeader(name, value) { + this.headers.push({ name: name, value: value }); + } + + removeHeader(index) { + this.headers.splice(index, 1); + } + + static fromJson(json = {}) { + return new TcpStreamSettings.TcpResponse( + json.version, + json.status, + json.reason, + XrayCommonClass.toHeaders(json.headers), + ); + } + + toJson() { + return { + version: this.version, + status: this.status, + reason: this.reason, + headers: XrayCommonClass.toV2Headers(this.headers), + }; + } +}; + +class KcpStreamSettings extends XrayCommonClass { + constructor( + mtu = 1350, + tti = 50, + uplinkCapacity = 5, + downlinkCapacity = 20, + congestion = false, + readBufferSize = 2, + writeBufferSize = 2, + type = 'none', + seed = RandomUtil.randomSeq(10), + ) { + super(); + this.mtu = mtu; + this.tti = tti; + this.upCap = uplinkCapacity; + this.downCap = downlinkCapacity; + this.congestion = congestion; + this.readBuffer = readBufferSize; + this.writeBuffer = writeBufferSize; + this.type = type; + this.seed = seed; + } + + static fromJson(json = {}) { + return new KcpStreamSettings( + json.mtu, + json.tti, + json.uplinkCapacity, + json.downlinkCapacity, + json.congestion, + json.readBufferSize, + json.writeBufferSize, + ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type, + json.seed, + ); + } + + toJson() { + return { + mtu: this.mtu, + tti: this.tti, + uplinkCapacity: this.upCap, + downlinkCapacity: this.downCap, + congestion: this.congestion, + readBufferSize: this.readBuffer, + writeBufferSize: this.writeBuffer, + header: { + type: this.type, + }, + seed: this.seed, + }; + } +} + +class WsStreamSettings extends XrayCommonClass { + constructor( + acceptProxyProtocol = false, + path = '/', + host = '', + headers = [] + ) { + super(); + this.acceptProxyProtocol = acceptProxyProtocol; + this.path = path; + this.host = host; + this.headers = headers; + } + + addHeader(name, value) { + this.headers.push({ name: name, value: value }); + } + + removeHeader(index) { + this.headers.splice(index, 1); + } + + static fromJson(json = {}) { + return new WsStreamSettings( + json.acceptProxyProtocol, + json.path, + json.host, + XrayCommonClass.toHeaders(json.headers), + ); + } + + toJson() { + return { + acceptProxyProtocol: this.acceptProxyProtocol, + path: this.path, + host: this.host, + headers: XrayCommonClass.toV2Headers(this.headers, false), + }; + } +} + +class HttpStreamSettings extends XrayCommonClass { + constructor( + path = '/', + host = [''], + ) { + super(); + this.path = path; + this.host = host.length === 0 ? [''] : host; + } + + addHost(host) { + this.host.push(host); + } + + removeHost(index) { + this.host.splice(index, 1); + } + + static fromJson(json = {}) { + return new HttpStreamSettings(json.path, json.host); + } + + toJson() { + let host = []; + for (let i = 0; i < this.host.length; ++i) { + if (!ObjectUtil.isEmpty(this.host[i])) { + host.push(this.host[i]); + } + } + return { + path: this.path, + host: host, + } + } +} + +class GrpcStreamSettings extends XrayCommonClass { + constructor( + serviceName = "", + authority = "", + multiMode = false, + ) { + super(); + this.serviceName = serviceName; + this.authority = authority; + this.multiMode = multiMode; + } + + static fromJson(json = {}) { + return new GrpcStreamSettings( + json.serviceName, + json.authority, + json.multiMode + ); + } + + toJson() { + return { + serviceName: this.serviceName, + authority: this.authority, + multiMode: this.multiMode, + } + } +} + +class HTTPUpgradeStreamSettings extends XrayCommonClass { + constructor( + acceptProxyProtocol = false, + path = '/', + host = '', + headers = [] + ) { + super(); + this.acceptProxyProtocol = acceptProxyProtocol; + this.path = path; + this.host = host; + this.headers = headers; + } + + addHeader(name, value) { + this.headers.push({ name: name, value: value }); + } + + removeHeader(index) { + this.headers.splice(index, 1); + } + + static fromJson(json = {}) { + return new HTTPUpgradeStreamSettings( + json.acceptProxyProtocol, + json.path, + json.host, + XrayCommonClass.toHeaders(json.headers), + ); + } + + toJson() { + return { + acceptProxyProtocol: this.acceptProxyProtocol, + path: this.path, + host: this.host, + headers: XrayCommonClass.toV2Headers(this.headers, false), + }; + } +} + +class SplitHTTPStreamSettings extends XrayCommonClass { + constructor( + path = '/', + host = '', + headers = [], + scMaxConcurrentPosts = "100-200", + scMaxEachPostBytes = "1000000-2000000", + scMinPostsIntervalMs = "10-50", + noSSEHeader = false, + xPaddingBytes = "100-1000", + xmux = { + maxConcurrency: "16-32", + maxConnections: 0, + cMaxReuseTimes: "64-128", + cMaxLifetimeMs: 0 + } + ) { + super(); + this.path = path; + this.host = host; + this.headers = headers; + this.scMaxConcurrentPosts = scMaxConcurrentPosts; + this.scMaxEachPostBytes = scMaxEachPostBytes; + this.scMinPostsIntervalMs = scMinPostsIntervalMs; + this.noSSEHeader = noSSEHeader; + this.xPaddingBytes = xPaddingBytes; + this.xmux = xmux; + } + + addHeader(name, value) { + this.headers.push({ name: name, value: value }); + } + + removeHeader(index) { + this.headers.splice(index, 1); + } + + static fromJson(json = {}) { + return new SplitHTTPStreamSettings( + json.path, + json.host, + XrayCommonClass.toHeaders(json.headers), + json.scMaxConcurrentPosts, + json.scMaxEachPostBytes, + json.scMinPostsIntervalMs, + json.noSSEHeader, + json.xPaddingBytes, + json.xmux, + ); + } + + toJson() { + return { + path: this.path, + host: this.host, + headers: XrayCommonClass.toV2Headers(this.headers, false), + scMaxConcurrentPosts: this.scMaxConcurrentPosts, + scMaxEachPostBytes: this.scMaxEachPostBytes, + scMinPostsIntervalMs: this.scMinPostsIntervalMs, + noSSEHeader: this.noSSEHeader, + xPaddingBytes: this.xPaddingBytes, + xmux: { + maxConcurrency: this.xmux.maxConcurrency, + maxConnections: this.xmux.maxConnections, + cMaxReuseTimes: this.xmux.cMaxReuseTimes, + cMaxLifetimeMs: this.xmux.cMaxLifetimeMs + } + }; + } +} + +class TlsStreamSettings extends XrayCommonClass { + constructor( + serverName = '', + minVersion = TLS_VERSION_OPTION.TLS12, + maxVersion = TLS_VERSION_OPTION.TLS13, + cipherSuites = '', + rejectUnknownSni = false, + disableSystemRoot = false, + enableSessionResumption = false, + certificates = [new TlsStreamSettings.Cert()], + alpn = [ALPN_OPTION.H3, ALPN_OPTION.H2, ALPN_OPTION.HTTP1], + settings = new TlsStreamSettings.Settings() + ) { + super(); + this.sni = serverName; + this.minVersion = minVersion; + this.maxVersion = maxVersion; + this.cipherSuites = cipherSuites; + this.rejectUnknownSni = rejectUnknownSni; + this.disableSystemRoot = disableSystemRoot; + this.enableSessionResumption = enableSessionResumption; + this.certs = certificates; + this.alpn = alpn; + this.settings = settings; + } + + addCert() { + this.certs.push(new TlsStreamSettings.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 => TlsStreamSettings.Cert.fromJson(cert)); + } + + if (!ObjectUtil.isEmpty(json.settings)) { + settings = new TlsStreamSettings.Settings(json.settings.allowInsecure, json.settings.fingerprint, json.settings.serverName, json.settings.domains); + } + return new TlsStreamSettings( + json.serverName, + json.minVersion, + json.maxVersion, + json.cipherSuites, + json.rejectUnknownSni, + json.disableSystemRoot, + json.enableSessionResumption, + certs, + json.alpn, + settings, + ); + } + + toJson() { + return { + serverName: this.sni, + minVersion: this.minVersion, + maxVersion: this.maxVersion, + cipherSuites: this.cipherSuites, + rejectUnknownSni: this.rejectUnknownSni, + disableSystemRoot: this.disableSystemRoot, + enableSessionResumption: this.enableSessionResumption, + certificates: TlsStreamSettings.toJsonArray(this.certs), + alpn: this.alpn, + settings: this.settings, + }; + } +} + +TlsStreamSettings.Cert = class extends XrayCommonClass { + constructor( + useFile = true, + certificateFile = '', + keyFile = '', + certificate = '', + key = '', + ocspStapling = 3600, + oneTimeLoading = false, + usage = USAGE_OPTION.ENCIPHERMENT, + buildChain = false, + ) { + super(); + this.useFile = useFile; + this.certFile = certificateFile; + this.keyFile = keyFile; + this.cert = Array.isArray(certificate) ? certificate.join('\n') : certificate; + this.key = Array.isArray(key) ? key.join('\n') : key; + this.ocspStapling = ocspStapling; + this.oneTimeLoading = oneTimeLoading; + this.usage = usage; + this.buildChain = buildChain + } + + static fromJson(json = {}) { + if ('certificateFile' in json && 'keyFile' in json) { + return new TlsStreamSettings.Cert( + true, + json.certificateFile, + json.keyFile, '', '', + json.ocspStapling, + json.oneTimeLoading, + json.usage, + json.buildChain, + ); + } else { + return new TlsStreamSettings.Cert( + false, '', '', + json.certificate.join('\n'), + json.key.join('\n'), + json.ocspStapling, + json.oneTimeLoading, + json.usage, + json.buildChain, + ); + } + } + + toJson() { + if (this.useFile) { + return { + certificateFile: this.certFile, + keyFile: this.keyFile, + ocspStapling: this.ocspStapling, + oneTimeLoading: this.oneTimeLoading, + usage: this.usage, + buildChain: this.buildChain, + }; + } else { + return { + certificate: this.cert.split('\n'), + key: this.key.split('\n'), + ocspStapling: this.ocspStapling, + oneTimeLoading: this.oneTimeLoading, + usage: this.usage, + buildChain: this.buildChain, + }; + } + } +}; + +TlsStreamSettings.Settings = class extends XrayCommonClass { + constructor(allowInsecure = false, fingerprint = '') { + super(); + this.allowInsecure = allowInsecure; + this.fingerprint = fingerprint; + } + static fromJson(json = {}) { + return new TlsStreamSettings.Settings( + json.allowInsecure, + json.fingerprint, + ); + } + toJson() { + return { + allowInsecure: this.allowInsecure, + fingerprint: this.fingerprint, + }; + } +}; + + +class RealityStreamSettings extends XrayCommonClass { + constructor( + show = false, + xver = 0, + dest = 'yahoo.com:443', + serverNames = 'yahoo.com,www.yahoo.com', + privateKey = '', + minClient = '', + maxClient = '', + maxTimediff = 0, + shortIds = RandomUtil.randomShortIds(), + settings = new RealityStreamSettings.Settings() + ) { + super(); + this.show = show; + this.xver = xver; + this.dest = dest; + this.serverNames = Array.isArray(serverNames) ? serverNames.join(",") : serverNames; + this.privateKey = privateKey; + this.minClient = minClient; + this.maxClient = maxClient; + this.maxTimediff = maxTimediff; + this.shortIds = Array.isArray(shortIds) ? 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, + json.settings.spiderX + ); + } + return new RealityStreamSettings( + json.show, + json.xver, + json.dest, + json.serverNames, + json.privateKey, + json.minClient, + json.maxClient, + json.maxTimediff, + json.shortIds, + json.settings, + ); + } + + toJson() { + return { + show: this.show, + xver: this.xver, + dest: this.dest, + serverNames: this.serverNames.split(","), + privateKey: this.privateKey, + minClient: this.minClient, + maxClient: this.maxClient, + maxTimediff: this.maxTimediff, + shortIds: this.shortIds.split(","), + settings: this.settings, + }; + } +} + +RealityStreamSettings.Settings = class extends XrayCommonClass { + constructor( + publicKey = '', + fingerprint = UTLS_FINGERPRINT.UTLS_RANDOM, + serverName = '', + spiderX = '/' + ) { + super(); + this.publicKey = publicKey; + this.fingerprint = fingerprint; + this.serverName = serverName; + this.spiderX = spiderX; + } + static fromJson(json = {}) { + return new RealityStreamSettings.Settings( + json.publicKey, + json.fingerprint, + json.serverName, + json.spiderX, + ); + } + toJson() { + return { + publicKey: this.publicKey, + fingerprint: this.fingerprint, + serverName: this.serverName, + spiderX: this.spiderX, + }; + } +}; + +class SockoptStreamSettings extends XrayCommonClass { + constructor( + acceptProxyProtocol = false, + tcpFastOpen = false, + mark = 0, + tproxy = "off", + tcpMptcp = false, + tcpNoDelay = false, + domainStrategy = DOMAIN_STRATEGY_OPTION.USE_IP, + tcpMaxSeg = 1440, + dialerProxy = "", + tcpKeepAliveInterval = 0, + tcpKeepAliveIdle = 300, + tcpUserTimeout = 10000, + tcpcongestion = TCP_CONGESTION_OPTION.BBR, + V6Only = false, + tcpWindowClamp = 600, + interfaceName = "", + ) { + super(); + this.acceptProxyProtocol = acceptProxyProtocol; + this.tcpFastOpen = tcpFastOpen; + this.mark = mark; + this.tproxy = tproxy; + this.tcpMptcp = tcpMptcp; + this.tcpNoDelay = tcpNoDelay; + this.domainStrategy = domainStrategy; + this.tcpMaxSeg = tcpMaxSeg; + this.dialerProxy = dialerProxy; + this.tcpKeepAliveInterval = tcpKeepAliveInterval; + this.tcpKeepAliveIdle = tcpKeepAliveIdle; + this.tcpUserTimeout = tcpUserTimeout; + this.tcpcongestion = tcpcongestion; + this.V6Only = V6Only; + this.tcpWindowClamp = tcpWindowClamp; + this.interfaceName = interfaceName; + } + + static fromJson(json = {}) { + if (Object.keys(json).length === 0) return undefined; + return new SockoptStreamSettings( + json.acceptProxyProtocol, + json.tcpFastOpen, + json.mark, + json.tproxy, + json.tcpMptcp, + json.tcpNoDelay, + json.domainStrategy, + json.tcpMaxSeg, + json.dialerProxy, + json.tcpKeepAliveInterval, + json.tcpKeepAliveIdle, + json.tcpUserTimeout, + json.tcpcongestion, + json.V6Only, + json.tcpWindowClamp, + json.interface, + ); + } + + toJson() { + return { + acceptProxyProtocol: this.acceptProxyProtocol, + tcpFastOpen: this.tcpFastOpen, + mark: this.mark, + tproxy: this.tproxy, + tcpMptcp: this.tcpMptcp, + tcpNoDelay: this.tcpNoDelay, + domainStrategy: this.domainStrategy, + tcpMaxSeg: this.tcpMaxSeg, + dialerProxy: this.dialerProxy, + tcpKeepAliveInterval: this.tcpKeepAliveInterval, + tcpKeepAliveIdle: this.tcpKeepAliveIdle, + tcpUserTimeout: this.tcpUserTimeout, + tcpcongestion: this.tcpcongestion, + V6Only: this.V6Only, + tcpWindowClamp: this.tcpWindowClamp, + interface: this.interfaceName, + }; + } +} + +class StreamSettings extends XrayCommonClass { + constructor(network = 'tcp', + security = 'none', + externalProxy = [], + tlsSettings = new TlsStreamSettings(), + realitySettings = new RealityStreamSettings(), + tcpSettings = new TcpStreamSettings(), + kcpSettings = new KcpStreamSettings(), + wsSettings = new WsStreamSettings(), + httpSettings = new HttpStreamSettings(), + grpcSettings = new GrpcStreamSettings(), + httpupgradeSettings = new HTTPUpgradeStreamSettings(), + splithttpSettings = new SplitHTTPStreamSettings(), + sockopt = undefined, + ) { + super(); + this.network = network; + this.security = security; + this.externalProxy = externalProxy; + this.tls = tlsSettings; + this.reality = realitySettings; + this.tcp = tcpSettings; + this.kcp = kcpSettings; + this.ws = wsSettings; + this.http = httpSettings; + this.grpc = grpcSettings; + this.httpupgrade = httpupgradeSettings; + this.splithttp = splithttpSettings; + this.sockopt = sockopt; + } + + get isTls() { + return this.security === "tls"; + } + + set isTls(isTls) { + if (isTls) { + this.security = 'tls'; + } else { + this.security = 'none'; + } + } + + //for Reality + get isReality() { + return this.security === "reality"; + } + + set isReality(isReality) { + if (isReality) { + this.security = 'reality'; + } else { + this.security = 'none'; + } + } + + get sockoptSwitch() { + return this.sockopt != undefined; + } + + set sockoptSwitch(value) { + this.sockopt = value ? new SockoptStreamSettings() : undefined; + } + + static fromJson(json = {}) { + return new StreamSettings( + json.network, + json.security, + json.externalProxy, + TlsStreamSettings.fromJson(json.tlsSettings), + RealityStreamSettings.fromJson(json.realitySettings), + TcpStreamSettings.fromJson(json.tcpSettings), + KcpStreamSettings.fromJson(json.kcpSettings), + WsStreamSettings.fromJson(json.wsSettings), + HttpStreamSettings.fromJson(json.httpSettings), + GrpcStreamSettings.fromJson(json.grpcSettings), + HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings), + SplitHTTPStreamSettings.fromJson(json.splithttpSettings), + SockoptStreamSettings.fromJson(json.sockopt), + ); + } + + toJson() { + const network = this.network; + return { + network: network, + security: this.security, + externalProxy: this.externalProxy, + tlsSettings: this.isTls ? this.tls.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, + grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, + httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, + splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined, + sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, + }; + } +} + +class Sniffing extends XrayCommonClass { + constructor( + enabled = false, + destOverride = ['http', 'tls', 'quic', 'fakedns'], + metadataOnly = false, + routeOnly = false) { + super(); + this.enabled = enabled; + this.destOverride = destOverride; + this.metadataOnly = metadataOnly; + this.routeOnly = routeOnly; + } + + static fromJson(json = {}) { + let destOverride = ObjectUtil.clone(json.destOverride); + if (!ObjectUtil.isEmpty(destOverride) && !ObjectUtil.isArrEmpty(destOverride)) { + if (ObjectUtil.isEmpty(destOverride[0])) { + destOverride = ['http', 'tls', 'quic', 'fakedns']; + } + } + return new Sniffing( + !!json.enabled, + destOverride, + json.metadataOnly, + json.routeOnly, + ); + } +} + +class Allocate extends XrayCommonClass { + constructor( + strategy = "always", + refresh = 5, + concurrency = 3, + ) { + super(); + this.strategy = strategy; + this.refresh = refresh; + this.concurrency = concurrency; + } + + static fromJson(json = {}) { + return new Allocate( + json.strategy, + json.refresh, + json.concurrency, + ); + } +} + +class Inbound extends XrayCommonClass { + constructor( + port = RandomUtil.randomIntRange(10000, 60000), + listen = '', + protocol = Protocols.VLESS, + settings = null, + streamSettings = new StreamSettings(), + tag = '', + sniffing = new Sniffing(), + allocate = new Allocate(), + clientStats = '', + ) { + super(); + this.port = port; + this.listen = listen; + this._protocol = protocol; + this.settings = ObjectUtil.isEmpty(settings) ? Inbound.Settings.getSettings(protocol) : settings; + this.stream = streamSettings; + this.tag = tag; + this.sniffing = sniffing; + this.allocate = allocate; + this.clientStats = clientStats; + } + getClientStats() { + return this.clientStats; + } + + get clients() { + switch (this.protocol) { + case Protocols.VMESS: return this.settings.vmesses; + case Protocols.VLESS: return this.settings.vlesses; + case Protocols.TROJAN: return this.settings.trojans; + case Protocols.SHADOWSOCKS: return this.isSSMultiUser ? this.settings.shadowsockses : null; + default: return null; + } + } + contacts: admin@thfree.ru |
