From 2ec6c736130a9d38ef81a16b77f07a749aefd2f0 Mon Sep 17 00:00:00 2001 From: Sanaei Date: Tue, 8 Sep 2026 13:49:32 +0200 Subject: [PATCH] feat(xray): update xray-core to v26.9.8 and adapt panel Bump xtls/xray-core to 37ceb8b4b6 (v26.9.8) and the three binary pins (DockerInit.sh, release.yml Linux + Windows) in lockstep. No deleted symbols; the impact is entirely on the JSON config surface. Outbound "proxySettings" is now refused by the config loader (moved to streamSettings.sockopt.dialerProxy) and a freedom outbound rejects sockopt.addressPortStrategy. Either key in a stored template would keep the core from starting after the upgrade, so a new OutboundRemovedKeysFix seeder rewrites xrayTemplateConfig once: proxySettings.tag becomes sockopt.dialerProxy (an existing dialerProxy wins) and addressPortStrategy is dropped from freedom outbounds. Template saves and outbound subscriptions already run through the vendored loader, so the new refusals surface there with the core's own message. REALITY no longer applies a built-in minClientVer (26.3.27) when the field is empty. The form placeholder and the min/max hints in all 13 locales now say that empty means no minimum. New upstream keys the Zod schemas would otherwise strip, with form support where a sibling field already had it: - blackhole response type "custom" with base64 customResponseData - realm finalmask ipMode (dual/v4/v6) and portMapping (UPnP / NAT-PMP) - quicParams brutalDisableLossCompensation, disableChromeParrot, disableGSO, disableStatelessReset - hysteria masquerade proxy xForwarded - wireguard outbound remoteDNS - routing rule localOS freedom.domainStrategy is only deprecated upstream (auto-migrated to sockopt.domainStrategy with a warning) and is left untouched. --- .github/workflows/release.yml | 4 +- DockerInit.sh | 2 +- .../xray/forms/transport/FinalMaskForm.tsx | 54 ++++++++ .../src/lib/xray/outbound-form-adapter.ts | 25 +++- .../inbounds/form/protocols/hysteria.tsx | 7 ++ .../pages/inbounds/form/security/reality.tsx | 2 +- .../xray/outbounds/protocols/blackhole.tsx | 34 +++-- .../xray/outbounds/protocols/wireguard.tsx | 3 + .../xray/outbounds/transport/hysteria.tsx | 7 ++ frontend/src/schemas/forms/outbound-form.ts | 2 + .../schemas/protocols/outbound/blackhole.ts | 12 +- .../src/schemas/protocols/stream/finalmask.ts | 4 + .../src/schemas/protocols/stream/hysteria.ts | 1 + frontend/src/schemas/routing.ts | 1 + .../test/__snapshots__/finalmask.test.ts.snap | 17 +++ .../src/test/__snapshots__/rule.test.ts.snap | 11 ++ .../fixtures/finalmask/quic-params-flags.json | 12 ++ .../test/golden/fixtures/rule/local-os.json | 5 + .../src/test/outbound-form-adapter.test.ts | 48 +++++++ go.mod | 12 +- go.sum | 37 +++++- internal/database/db.go | 105 +++++++++++++++- .../outbound_removed_keys_migration_test.go | 117 ++++++++++++++++++ internal/web/translation/ar-EG.json | 7 +- internal/web/translation/en-US.json | 7 +- internal/web/translation/es-ES.json | 7 +- internal/web/translation/fa-IR.json | 7 +- internal/web/translation/id-ID.json | 7 +- internal/web/translation/ja-JP.json | 7 +- internal/web/translation/pt-BR.json | 7 +- internal/web/translation/ru-RU.json | 7 +- internal/web/translation/tr-TR.json | 9 +- internal/web/translation/uk-UA.json | 7 +- internal/web/translation/vi-VN.json | 7 +- internal/web/translation/zh-CN.json | 7 +- internal/web/translation/zh-TW.json | 7 +- 36 files changed, 554 insertions(+), 61 deletions(-) create mode 100644 frontend/src/test/golden/fixtures/finalmask/quic-params-flags.json create mode 100644 frontend/src/test/golden/fixtures/rule/local-os.json create mode 100644 internal/database/outbound_removed_keys_migration_test.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 48b5e5cb7..dde15ed28 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -124,7 +124,7 @@ jobs: cd x-ui/bin # Download dependencies - Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.7.28/" + Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v26.9.8/" if [ "${{ matrix.platform }}" == "amd64" ]; then fetch ${Xray_URL}Xray-linux-64.zip unzip Xray-linux-64.zip @@ -287,7 +287,7 @@ jobs: cd x-ui\bin # Download Xray for Windows - $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.7.28/" + $Xray_URL = "https://github.com/XTLS/Xray-core/releases/download/v26.9.8/" Invoke-WebRequest @retry -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 9c23fb55c..1d9b1861f 100755 --- a/DockerInit.sh +++ b/DockerInit.sh @@ -32,7 +32,7 @@ if [ -z "$MTG_MULTI_VER" ]; then fi mkdir -p build/bin cd build/bin -curl -sfLRO "https://github.com/XTLS/Xray-core/releases/download/v26.7.28/Xray-linux-${ARCH}.zip" +curl -sfLRO "https://github.com/XTLS/Xray-core/releases/download/v26.9.8/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/frontend/src/lib/xray/forms/transport/FinalMaskForm.tsx b/frontend/src/lib/xray/forms/transport/FinalMaskForm.tsx index a153a8818..d6ae08f1c 100644 --- a/frontend/src/lib/xray/forms/transport/FinalMaskForm.tsx +++ b/frontend/src/lib/xray/forms/transport/FinalMaskForm.tsx @@ -994,6 +994,36 @@ function UdpMaskItem({ placeholder="host:port" /> + + + + + )} @@ -1478,6 +1515,23 @@ function QuicParamsForm({ base, form }: { base: (string | number)[]; form: FormI > + + + + + + + + + diff --git a/frontend/src/lib/xray/outbound-form-adapter.ts b/frontend/src/lib/xray/outbound-form-adapter.ts index 5945f346e..7c727aff9 100644 --- a/frontend/src/lib/xray/outbound-form-adapter.ts +++ b/frontend/src/lib/xray/outbound-form-adapter.ts @@ -6,6 +6,7 @@ import type { Sniffing, SniffingDest } from '@/schemas/primitives'; import type { OutboundDomainStrategy } from '@/schemas/protocols/outbound'; import type { + BlackholeOutboundFormSettings, DnsOutboundFormSettings, DnsRuleForm, FreedomFinalRuleForm, @@ -243,6 +244,9 @@ function wireguardFromWire(raw: Raw): WireguardOutboundFormSettings { return (allowed.includes(s) ? s : '') as WireguardOutboundFormSettings['domainStrategy']; })(), reserved: reservedArr.join(','), + remoteDNS: asArray(raw.remoteDNS) + .map((x) => asString(x)) + .join(','), peers, noKernelTun: asBool(raw.noKernelTun), }; @@ -322,10 +326,13 @@ function freedomFromWire(raw: Raw): FreedomOutboundFormSettings { }; } -function blackholeFromWire(raw: Raw) { +function blackholeFromWire(raw: Raw): BlackholeOutboundFormSettings { const response = asObject(raw.response); const t = asString(response.type); - return { type: (t === 'none' || t === 'http' ? t : '') as '' | 'none' | 'http' }; + return { + type: t === 'none' || t === 'http' || t === 'custom' ? t : '', + customResponseData: asString(response.customResponseData), + }; } function dnsRuleFromWire(raw: unknown): DnsRuleForm { @@ -585,6 +592,12 @@ function wireguardToWire(s: WireguardOutboundFormSettings) { .map((x) => Number(x.trim())) .filter((n) => Number.isFinite(n)) : undefined, + remoteDNS: s.remoteDNS + ? s.remoteDNS + .split(',') + .map((x) => x.trim()) + .filter(Boolean) + : undefined, peers: s.peers.map((p) => ({ publicKey: p.publicKey, preSharedKey: p.psk.length > 0 ? p.psk : undefined, @@ -631,8 +644,12 @@ function freedomToWire(s: FreedomOutboundFormSettings) { }; } -function blackholeToWire(s: { type: '' | 'none' | 'http' }) { - return { response: s.type ? { type: s.type } : undefined }; +function blackholeToWire(s: BlackholeOutboundFormSettings) { + if (!s.type) return { response: undefined }; + if (s.type === 'custom') { + return { response: { type: s.type, customResponseData: s.customResponseData } }; + } + return { response: { type: s.type } }; } function dnsRuleToWire(r: DnsRuleForm) { diff --git a/frontend/src/pages/inbounds/form/protocols/hysteria.tsx b/frontend/src/pages/inbounds/form/protocols/hysteria.tsx index 68f3b7dc9..83f5aa951 100644 --- a/frontend/src/pages/inbounds/form/protocols/hysteria.tsx +++ b/frontend/src/pages/inbounds/form/protocols/hysteria.tsx @@ -78,6 +78,13 @@ export default function HysteriaFields() { > + + + - + - + + {type === 'custom' && ( + + + + )} + ); } diff --git a/frontend/src/pages/xray/outbounds/protocols/wireguard.tsx b/frontend/src/pages/xray/outbounds/protocols/wireguard.tsx index 1b20459c3..9382ae946 100644 --- a/frontend/src/pages/xray/outbounds/protocols/wireguard.tsx +++ b/frontend/src/pages/xray/outbounds/protocols/wireguard.tsx @@ -99,6 +99,9 @@ export default function WireguardFields() { + + +