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"
/>
+
+
+
+
+
+
+
+
+
+
+
+
TLS (optional)
@@ -1443,6 +1473,13 @@ function QuicParamsForm({ base, form }: { base: (string | number)[]; form: FormI
+
+
+
>
)}
@@ -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() {
+
+
+