From 3af6497577b7da4149a6432ea83ae4f229da6e45 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 1 Feb 2026 02:34:23 +0100 Subject: [PATCH] inbound : finalmask --- web/assets/js/model/inbound.js | 92 ++++++++++++++++++---- web/assets/js/model/outbound.js | 16 +--- web/html/form/outbound.html | 51 ++++++------ web/html/form/stream/stream_finalmask.html | 70 ++++++++++++++++ web/html/form/stream/stream_kcp.html | 46 ++++------- web/html/form/stream/stream_settings.html | 12 ++- 6 files changed, 201 insertions(+), 86 deletions(-) create mode 100644 web/html/form/stream/stream_finalmask.html diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js index 9077ea53..6d65a11c 100644 --- a/web/assets/js/model/inbound.js +++ b/web/assets/js/model/inbound.js @@ -319,14 +319,12 @@ TcpStreamSettings.TcpResponse = class extends XrayCommonClass { class KcpStreamSettings extends XrayCommonClass { constructor( mtu = 1350, - tti = 50, + tti = 20, uplinkCapacity = 5, downlinkCapacity = 20, congestion = false, - readBufferSize = 2, - writeBufferSize = 2, - type = 'none', - seed = RandomUtil.randomSeq(10), + readBufferSize = 1, + writeBufferSize = 1, ) { super(); this.mtu = mtu; @@ -336,8 +334,6 @@ class KcpStreamSettings extends XrayCommonClass { this.congestion = congestion; this.readBuffer = readBufferSize; this.writeBuffer = writeBufferSize; - this.type = type; - this.seed = seed; } static fromJson(json = {}) { @@ -349,8 +345,6 @@ class KcpStreamSettings extends XrayCommonClass { json.congestion, json.readBufferSize, json.writeBufferSize, - ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type, - json.seed, ); } @@ -363,10 +357,6 @@ class KcpStreamSettings extends XrayCommonClass { congestion: this.congestion, readBufferSize: this.readBuffer, writeBufferSize: this.writeBuffer, - header: { - type: this.type, - }, - seed: this.seed, }; } } @@ -929,6 +919,51 @@ class SockoptStreamSettings extends XrayCommonClass { } } +class FinalMask extends XrayCommonClass { + constructor(type = 'salamander', settings = {}) { + super(); + this.type = type; + this.settings = this._getDefaultSettings(type, settings); + } + + _getDefaultSettings(type, settings = {}) { + switch (type) { + case 'salamander': + case 'mkcp-aes128gcm': + return { password: settings.password || '' }; + case 'header-dns': + case 'xdns': + return { domain: settings.domain || '' }; + case 'mkcp-original': + case 'header-dtls': + case 'header-srtp': + case 'header-utp': + case 'header-wechat': + case 'header-wireguard': + return {}; + default: + return settings; + } + } + + static fromJson(json = {}) { + return new FinalMask( + json.type || 'salamander', + json.settings || {} + ); + } + + toJson() { + const result = { + type: this.type + }; + if (this.settings && Object.keys(this.settings).length > 0) { + result.settings = this.settings; + } + return result; + } +} + class StreamSettings extends XrayCommonClass { constructor(network = 'tcp', security = 'none', @@ -941,6 +976,7 @@ class StreamSettings extends XrayCommonClass { grpcSettings = new GrpcStreamSettings(), httpupgradeSettings = new HTTPUpgradeStreamSettings(), xhttpSettings = new xHTTPStreamSettings(), + finalmask = { udp: [] }, sockopt = undefined, ) { super(); @@ -955,9 +991,23 @@ class StreamSettings extends XrayCommonClass { this.grpc = grpcSettings; this.httpupgrade = httpupgradeSettings; this.xhttp = xhttpSettings; + this.finalmask = finalmask; this.sockopt = sockopt; } + addUdpMask(type = 'salamander') { + if (!this.finalmask.udp) { + this.finalmask.udp = []; + } + this.finalmask.udp.push(new FinalMask(type)); + } + + delUdpMask(index) { + if (this.finalmask.udp) { + this.finalmask.udp.splice(index, 1); + } + } + get isTls() { return this.security === "tls"; } @@ -992,6 +1042,14 @@ class StreamSettings extends XrayCommonClass { } static fromJson(json = {}) { + let finalmask = { udp: [] }; + if (json.finalmask) { + if (Array.isArray(json.finalmask)) { + finalmask.udp = json.finalmask.map(mask => FinalMask.fromJson(mask)); + } else if (json.finalmask.udp) { + finalmask.udp = json.finalmask.udp.map(mask => FinalMask.fromJson(mask)); + } + } return new StreamSettings( json.network, json.security, @@ -1004,6 +1062,7 @@ class StreamSettings extends XrayCommonClass { GrpcStreamSettings.fromJson(json.grpcSettings), HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings), xHTTPStreamSettings.fromJson(json.xhttpSettings), + finalmask, SockoptStreamSettings.fromJson(json.sockopt), ); } @@ -1022,6 +1081,9 @@ class StreamSettings extends XrayCommonClass { grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined, + finalmask: (this.finalmask.udp && this.finalmask.udp.length > 0) ? { + udp: this.finalmask.udp.map(mask => mask.toJson()) + } : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, }; } @@ -1947,7 +2009,9 @@ Inbound.VLESSSettings = class extends Inbound.Settings { json.selectedAuth = this.selectedAuth; } - if (this.testseed && this.testseed.length >= 4) { + // Only include testseed if at least one client has a flow set + const hasFlow = this.vlesses && this.vlesses.some(vless => vless.flow && vless.flow !== ''); + if (hasFlow && this.testseed && this.testseed.length >= 4) { json.testseed = this.testseed; } diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 3e5374e3..bac886d3 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -166,14 +166,12 @@ class TcpStreamSettings extends CommonClass { class KcpStreamSettings extends CommonClass { constructor( mtu = 1350, - tti = 50, + tti = 20, uplinkCapacity = 5, downlinkCapacity = 20, congestion = false, - readBufferSize = 2, - writeBufferSize = 2, - type = 'none', - seed = '', + readBufferSize = 1, + writeBufferSize = 1, ) { super(); this.mtu = mtu; @@ -183,8 +181,6 @@ class KcpStreamSettings extends CommonClass { this.congestion = congestion; this.readBuffer = readBufferSize; this.writeBuffer = writeBufferSize; - this.type = type; - this.seed = seed; } static fromJson(json = {}) { @@ -196,8 +192,6 @@ class KcpStreamSettings extends CommonClass { json.congestion, json.readBufferSize, json.writeBufferSize, - ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type, - json.seed, ); } @@ -210,10 +204,6 @@ class KcpStreamSettings extends CommonClass { congestion: this.congestion, readBufferSize: this.readBuffer, writeBufferSize: this.writeBuffer, - header: { - type: this.type, - }, - seed: this.seed, }; } } diff --git a/web/html/form/outbound.html b/web/html/form/outbound.html index 074137f7..9ca0eab6 100644 --- a/web/html/form/outbound.html +++ b/web/html/form/outbound.html @@ -407,21 +407,6 @@