diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf332fb3..2ed816c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,7 +89,7 @@ jobs: cd x-ui/bin # Download dependencies - Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.1.31/" + Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.2.2/" if [ "${{ matrix.platform }}" == "amd64" ]; then wget -q ${Xray_URL}Xray-linux-64.zip unzip Xray-linux-64.zip @@ -187,7 +187,7 @@ jobs: cd x-ui\bin # Download Xray for Windows - $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.1.31/" + $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.2.2/" Invoke-WebRequest -Uri "${Xray_URL}Xray-windows-64.zip" -OutFile "Xray-windows-64.zip" Expand-Archive -Path "Xray-windows-64.zip" -DestinationPath . Remove-Item "Xray-windows-64.zip" diff --git a/DockerInit.sh b/DockerInit.sh index d8acad77..6f153efe 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -27,7 +27,7 @@ case $1 in esac mkdir -p build/bin cd build/bin -curl -sfLRO "https://github.com/XTLS/Xray-core/releases/download/v26.1.31/Xray-linux-${ARCH}.zip" +curl -sfLRO "https://github.com/XTLS/Xray-core/releases/download/v26.2.2/Xray-linux-${ARCH}.zip" unzip "Xray-linux-${ARCH}.zip" rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat mv xray "xray-linux-${FNAME}" diff --git a/go.mod b/go.mod index 4f031534..98f44d28 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/valyala/fasthttp v1.69.0 github.com/xlzd/gotp v0.1.0 - github.com/xtls/xray-core v1.260131.0 + github.com/xtls/xray-core v1.260202.0 go.uber.org/atomic v1.11.0 golang.org/x/crypto v0.47.0 golang.org/x/sys v0.40.0 @@ -40,7 +40,7 @@ require ( github.com/cloudflare/circl v1.6.3 // indirect github.com/cloudwego/base64x v0.1.6 // indirect github.com/ebitengine/purego v0.9.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.12 // indirect + github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gin-contrib/sse v1.1.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-ole/go-ole v1.3.0 // indirect diff --git a/go.sum b/go.sum index 59e6c7f3..247ac90d 100644 --- a/go.sum +++ b/go.sum @@ -23,8 +23,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= -github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= +github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/gin-contrib/gzip v1.2.5 h1:fIZs0S+l17pIu1P5XRJOo/YNqfIuPCrZZ3TWB7pjckI= @@ -195,8 +195,8 @@ github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= github.com/xtls/reality v0.0.0-20251116175510-cd53f7d50237 h1:UXjrmniKlY+ZbIqpN91lejB3pszQQQRVu1vqH/p/aGM= github.com/xtls/reality v0.0.0-20251116175510-cd53f7d50237/go.mod h1:vbHCV/3VWUvy1oKvTxxWJRPEWSeR1sYgQHIh6u/JiZQ= -github.com/xtls/xray-core v1.260131.0 h1:gPBykLhUvRZ8sfubNerkwWqV3c15UtmSYQG2cgKqrV4= -github.com/xtls/xray-core v1.260131.0/go.mod h1:cxzYFZrxu1B1NtPjHsqv4UzgDvRA71mV4rXYH4KtO7Q= +github.com/xtls/xray-core v1.260202.0 h1:dYduYxGlkn/krSQJbmksbTtCdRe8OFb3YwpuXXEJG5c= +github.com/xtls/xray-core v1.260202.0/go.mod h1:cxzYFZrxu1B1NtPjHsqv4UzgDvRA71mV4rXYH4KtO7Q= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= diff --git a/web/assets/js/model/inbound.js b/web/assets/js/model/inbound.js index 3f3f8831..9bc93c30 100644 --- a/web/assets/js/model/inbound.js +++ b/web/assets/js/model/inbound.js @@ -967,7 +967,7 @@ class SockoptStreamSettings extends XrayCommonClass { } } -class FinalMask extends XrayCommonClass { +class UdpMask extends XrayCommonClass { constructor(type = 'salamander', settings = {}) { super(); this.type = type; @@ -982,6 +982,8 @@ class FinalMask extends XrayCommonClass { case 'header-dns': case 'xdns': return { domain: settings.domain || '' }; + case 'xicmp': + return { ip: settings.ip || '', id: settings.id ?? 0 }; case 'mkcp-original': case 'header-dtls': case 'header-srtp': @@ -995,20 +997,35 @@ class FinalMask extends XrayCommonClass { } static fromJson(json = {}) { - return new FinalMask( + return new UdpMask( json.type || 'salamander', json.settings || {} ); } toJson() { - const result = { - type: this.type + return { + type: this.type, + settings: (this.settings && Object.keys(this.settings).length > 0) ? this.settings : undefined }; - if (this.settings && Object.keys(this.settings).length > 0) { - result.settings = this.settings; - } - return result; + } +} + +class FinalMaskStreamSettings extends XrayCommonClass { + constructor(udp = []) { + super(); + this.udp = Array.isArray(udp) ? udp.map(u => new UdpMask(u.type, u.settings)) : [new UdpMask(udp.type, udp.settings)]; + } + + static fromJson(json = {}) { + return new FinalMaskStreamSettings(json.udp || []); + } + + toJson() { + return { + udp: this.udp.map(udp => udp.toJson()) + }; + } } @@ -1024,7 +1041,7 @@ class StreamSettings extends XrayCommonClass { grpcSettings = new GrpcStreamSettings(), httpupgradeSettings = new HTTPUpgradeStreamSettings(), xhttpSettings = new xHTTPStreamSettings(), - finalmask = { udp: [] }, + finalmask = new FinalMaskStreamSettings(), sockopt = undefined, ) { super(); @@ -1044,10 +1061,7 @@ class StreamSettings extends XrayCommonClass { } addUdpMask(type = 'salamander') { - if (!this.finalmask.udp) { - this.finalmask.udp = []; - } - this.finalmask.udp.push(new FinalMask(type)); + this.finalmask.udp.push(new UdpMask(type)); } delUdpMask(index) { @@ -1056,6 +1070,10 @@ class StreamSettings extends XrayCommonClass { } } + get hasFinalMask() { + return this.finalmask.udp && this.finalmask.udp.length > 0; + } + get isTls() { return this.security === "tls"; } @@ -1090,14 +1108,6 @@ 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, @@ -1110,7 +1120,7 @@ class StreamSettings extends XrayCommonClass { GrpcStreamSettings.fromJson(json.grpcSettings), HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings), xHTTPStreamSettings.fromJson(json.xhttpSettings), - finalmask, + FinalMaskStreamSettings.fromJson(json.finalmask), SockoptStreamSettings.fromJson(json.sockopt), ); } @@ -1129,9 +1139,7 @@ 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, + finalmask: this.hasFinalMask ? this.finalmask.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, }; } @@ -1302,14 +1310,6 @@ class Inbound extends XrayCommonClass { return null; } - get kcpType() { - return this.stream.kcp.type; - } - - get kcpSeed() { - return this.stream.kcp.seed; - } - get serviceName() { return this.stream.grpc.serviceName; } @@ -1386,8 +1386,6 @@ class Inbound extends XrayCommonClass { } } else if (network === 'kcp') { const kcp = this.stream.kcp; - obj.type = kcp.type; - obj.path = kcp.seed; } else if (network === 'ws') { const ws = this.stream.ws; obj.path = ws.path; @@ -1450,8 +1448,6 @@ class Inbound extends XrayCommonClass { break; case "kcp": const kcp = this.stream.kcp; - params.set("headerType", kcp.type); - params.set("seed", kcp.seed); break; case "ws": const ws = this.stream.ws; @@ -1555,8 +1551,6 @@ class Inbound extends XrayCommonClass { break; case "kcp": const kcp = this.stream.kcp; - params.set("headerType", kcp.type); - params.set("seed", kcp.seed); break; case "ws": const ws = this.stream.ws; @@ -1636,8 +1630,6 @@ class Inbound extends XrayCommonClass { break; case "kcp": const kcp = this.stream.kcp; - params.set("headerType", kcp.type); - params.set("seed", kcp.seed); break; case "ws": const ws = this.stream.ws; diff --git a/web/assets/js/model/outbound.js b/web/assets/js/model/outbound.js index 3e0dd0d4..fc110b4e 100644 --- a/web/assets/js/model/outbound.js +++ b/web/assets/js/model/outbound.js @@ -568,7 +568,7 @@ class SockoptStreamSettings extends CommonClass { } } -class FinalMask extends CommonClass { +class UdpMask extends CommonClass { constructor(type = 'salamander', settings = {}) { super(); this.type = type; @@ -596,21 +596,35 @@ class FinalMask extends CommonClass { } static fromJson(json = {}) { - return new FinalMask( + return new UdpMask( json.type || 'salamander', json.settings || {} ); } toJson() { - const result = { - type: this.type + return { + type: this.type, + settings: (this.settings && Object.keys(this.settings).length > 0) ? this.settings : undefined }; - // Only include settings if they exist and are not empty - if (this.settings && Object.keys(this.settings).length > 0) { - result.settings = this.settings; - } - return result; + } +} + +class FinalMaskStreamSettings extends CommonClass { + constructor(udp = []) { + super(); + this.udp = Array.isArray(udp) ? udp.map(u => new UdpMask(u.type, u.settings)) : [new UdpMask(udp.type, udp.settings)]; + } + + static fromJson(json = {}) { + return new FinalMaskStreamSettings(json.udp || []); + } + + toJson() { + return { + udp: this.udp.map(udp => udp.toJson()) + }; + } } @@ -627,7 +641,7 @@ class StreamSettings extends CommonClass { httpupgradeSettings = new HttpUpgradeStreamSettings(), xhttpSettings = new xHTTPStreamSettings(), hysteriaSettings = new HysteriaStreamSettings(), - finalmask = { udp: [] }, + finalmask = new FinalMaskStreamSettings(), sockopt = undefined, ) { super(); @@ -647,10 +661,7 @@ class StreamSettings extends CommonClass { } addUdpMask(type = 'salamander') { - if (!this.finalmask.udp) { - this.finalmask.udp = []; - } - this.finalmask.udp.push(new FinalMask(type)); + this.finalmask.udp.push(new UdpMask(type)); } delUdpMask(index) { @@ -659,6 +670,10 @@ class StreamSettings extends CommonClass { } } + get hasFinalMask() { + return this.finalmask.udp && this.finalmask.udp.length > 0; + } + get isTls() { return this.security === 'tls'; } @@ -676,16 +691,6 @@ class StreamSettings extends CommonClass { } static fromJson(json = {}) { - let finalmask = { udp: [] }; - if (json.finalmask) { - if (Array.isArray(json.finalmask)) { - // Legacy format: direct array (backward compatibility) - finalmask.udp = json.finalmask.map(mask => FinalMask.fromJson(mask)); - } else if (json.finalmask.udp) { - // New format: object with udp array - finalmask.udp = json.finalmask.udp.map(mask => FinalMask.fromJson(mask)); - } - } return new StreamSettings( json.network, json.security, @@ -698,7 +703,7 @@ class StreamSettings extends CommonClass { HttpUpgradeStreamSettings.fromJson(json.httpupgradeSettings), xHTTPStreamSettings.fromJson(json.xhttpSettings), HysteriaStreamSettings.fromJson(json.hysteriaSettings), - finalmask, + FinalMaskStreamSettings.fromJson(json.finalmask), SockoptStreamSettings.fromJson(json.sockopt), ); } @@ -717,9 +722,7 @@ class StreamSettings extends CommonClass { httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined, hysteriaSettings: network === 'hysteria' ? this.hysteria.toJson() : undefined, - finalmask: (this.finalmask.udp && this.finalmask.udp.length > 0) ? { - udp: this.finalmask.udp.map(mask => mask.toJson()) - } : undefined, + finalmask: this.hasFinalMask ? this.finalmask.toJson() : undefined, sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined, }; } diff --git a/web/html/form/stream/stream_finalmask.html b/web/html/form/stream/stream_finalmask.html index 4ed7d6a1..35962dfa 100644 --- a/web/html/form/stream/stream_finalmask.html +++ b/web/html/form/stream/stream_finalmask.html @@ -45,6 +45,9 @@ mKCP Original + + xICMP (Experimental) + + + + + + + diff --git a/web/html/modals/inbound_info_modal.html b/web/html/modals/inbound_info_modal.html index 72023e75..1ab187ee 100644 --- a/web/html/modals/inbound_info_modal.html +++ b/web/html/modals/inbound_info_modal.html @@ -1,5 +1,8 @@ {{define "modals/inboundInfoModal"}} - + @@ -26,7 +29,8 @@
-