diff --git a/frontend/src/pages/inbounds/form/protocols/tun.tsx b/frontend/src/pages/inbounds/form/protocols/tun.tsx
index 2a92b3971..81b0281de 100644
--- a/frontend/src/pages/inbounds/form/protocols/tun.tsx
+++ b/frontend/src/pages/inbounds/form/protocols/tun.tsx
@@ -1,6 +1,6 @@
import type { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
-import { Button, Form, Input, InputNumber, Space, Tooltip } from 'antd';
+import { Button, Form, Input, InputNumber, Select, Space, Switch, Tooltip } from 'antd';
import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
import { useFieldArray, useFormContext } from 'react-hook-form';
@@ -35,6 +35,12 @@ function StringList({ name, label, placeholder }: StringListProps) {
);
}
+// xray-core 26.9.30 accepts exactly these autoSystemWfpBlockLeak values.
+const WFP_BLOCK_LEAK_OPTIONS = [
+ { value: 'dns', label: 'dns' },
+ { value: 'misconfigtun', label: 'misconfigtun' },
+];
+
export default function TunFields() {
const { t } = useTranslation();
return (
@@ -42,6 +48,13 @@ export default function TunFields() {
+
+
+
@@ -77,6 +90,26 @@ export default function TunFields() {
>
+
+
+
+
+
+
>
);
}
diff --git a/frontend/src/schemas/protocols/inbound/tun.ts b/frontend/src/schemas/protocols/inbound/tun.ts
index 580437e51..f9d421c30 100644
--- a/frontend/src/schemas/protocols/inbound/tun.ts
+++ b/frontend/src/schemas/protocols/inbound/tun.ts
@@ -2,6 +2,8 @@ import { z } from 'zod';
export const TunInboundSettingsSchema = z.object({
name: z.string().default('xray0'),
+ // Windows: the tunnel type a new Wintun adapter is created with (core default Wintun).
+ desc: z.string().optional(),
mtu: z.number().int().min(0).default(1500),
gateway: z.array(z.string()).default([]),
dns: z.array(z.string()).default([]),
diff --git a/frontend/src/test/inbound-form-modal.test.tsx b/frontend/src/test/inbound-form-modal.test.tsx
index 8aa5bb547..1592133d5 100644
--- a/frontend/src/test/inbound-form-modal.test.tsx
+++ b/frontend/src/test/inbound-form-modal.test.tsx
@@ -467,6 +467,49 @@ describe('InboundFormModal', () => {
expect(JSON.stringify(finalmask.udp ?? [])).not.toContain('udphop');
});
+ // xray-core 26.9: the Wintun adapter type (desc) and the TUN auto-system leak guards.
+ it('saves the TUN adapter type and auto-system options set in the form', async () => {
+ const post = vi.mocked(HttpUtil.post);
+ post.mockClear();
+ const tun = new DBInbound({
+ id: 44,
+ port: 0,
+ listen: '',
+ protocol: 'tun',
+ remark: 'tun',
+ enable: true,
+ settings: {
+ name: 'xray0',
+ mtu: 1500,
+ gateway: ['10.0.0.1/16'],
+ dns: ['1.1.1.1'],
+ userLevel: 0,
+ autoSystemRoutingTable: ['0.0.0.0/0'],
+ autoOutboundsInterface: 'auto',
+ },
+ streamSettings: {},
+ sniffing: { enabled: false },
+ nodeId: null,
+ shareAddrStrategy: 'listen',
+ shareAddr: '',
+ });
+ renderCloneLikeEdit(tun);
+
+ fireEvent.change(document.getElementById('tun-desc')!, { target: { value: 'MyTun' } });
+ fireEvent.click(document.getElementById('tun-auto-dns-gateway')!);
+ chooseSelectOption('tun-wfp-block-leak', 'dns');
+ fireEvent.click(primaryButton());
+
+ const isUpdate = ([url]: unknown[]) => url === '/panel/api/inbounds/update/44';
+ await waitFor(() => expect(post.mock.calls.some(isUpdate)).toBe(true));
+ const payload = post.mock.calls.find(isUpdate)![1] as { settings: string };
+ expect(JSON.parse(payload.settings)).toMatchObject({
+ desc: 'MyTun',
+ autoSystemDnsToGateway: true,
+ autoSystemWfpBlockLeak: ['dns'],
+ });
+ });
+
// Clients and enable change through their own endpoints; the server keeps the
// stored ones, so the edit form must neither send nor validate its stale copy.
it('edit save neither sends nor validates the clients it loaded', async () => {
diff --git a/frontend/src/test/inbound-from-db.test.ts b/frontend/src/test/inbound-from-db.test.ts
index 51aedbb08..759a92fe0 100644
--- a/frontend/src/test/inbound-from-db.test.ts
+++ b/frontend/src/test/inbound-from-db.test.ts
@@ -60,12 +60,13 @@ describe('inboundFromDb', () => {
// The settings parse strips keys the schema does not list, so a TUN option xray-core
// 26.9.30 added and an admin entered as JSON would vanish on the next form save.
- it('keeps the TUN options xray-core 26.9.30 added', () => {
+ it('keeps the TUN options xray-core 26.9 added', () => {
const inbound = inboundFromDb({
...BASE_DB_FIELDS,
protocol: 'tun',
settings: {
name: 'xray0',
+ desc: 'MyTun',
gateway: ['10.0.0.1/16'],
autoSystemDnsToGateway: true,
autoSystemWfpBlockLeak: ['dns', 'misconfigtun'],
@@ -73,6 +74,7 @@ describe('inboundFromDb', () => {
streamSettings: '',
});
expect(inbound.settings).toMatchObject({
+ desc: 'MyTun',
autoSystemDnsToGateway: true,
autoSystemWfpBlockLeak: ['dns', 'misconfigtun'],
});
diff --git a/internal/web/translation/ar-EG.json b/internal/web/translation/ar-EG.json
index e9911cd0f..ccf5c6c28 100644
--- a/internal/web/translation/ar-EG.json
+++ b/internal/web/translation/ar-EG.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "مجمّع العناوين",
"addressPoolDesc": "تُخصَّص عناوين النفق من هذه البادئات — بحد أقصى IPv4 واحد و IPv6 واحد."
- }
+ },
+ "tunDesc": "نوع المحوّل",
+ "tunDescTooltip": "على ويندوز بس: نوع النفق اللي بيتعمل بيه محوّل Wintun جديد. لو فاضي يبقى Wintun.",
+ "autoSystemDnsToGateway": "DNS النظام إلى البوابة",
+ "autoSystemDnsToGatewayTooltip": "على لينكس بس: بيوجّه systemd-resolved لبوابة TUN عشان استعلامات النظام تعدّي من Xray. محتاج بوابة، والـTUN مش هيشتغل لو ده فشل.",
+ "autoSystemWfpBlockLeak": "منع التسريب (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "على ويندوز بس، مع Auto system routes: dns بيخلّي DNS جوّه الـTUN (محتاج سيرفرات DNS)، وmisconfigtun بيمنع نسخة IP مفيش مسار بيوديها للـTUN."
},
"info": {
"mode": "الوضع",
diff --git a/internal/web/translation/en-US.json b/internal/web/translation/en-US.json
index 3cfb13769..1e36a4f10 100644
--- a/internal/web/translation/en-US.json
+++ b/internal/web/translation/en-US.json
@@ -723,7 +723,13 @@
"masque": {
"addressPool": "Address pool",
"addressPoolDesc": "Tunnel addresses are leased from these prefixes — at most one IPv4 and one IPv6."
- }
+ },
+ "tunDesc": "Adapter type",
+ "tunDescTooltip": "Windows only: the tunnel type a new Wintun adapter is created with. Empty means Wintun.",
+ "autoSystemDnsToGateway": "System DNS to gateway",
+ "autoSystemDnsToGatewayTooltip": "Linux only: points systemd-resolved at the TUN gateway so system lookups go through Xray. Needs a gateway, and the TUN does not start if this fails.",
+ "autoSystemWfpBlockLeak": "Block leaks (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Windows only, with Auto system routes: dns keeps DNS inside the TUN (needs DNS servers), misconfigtun blocks an IP version that no route sends into the TUN."
},
"info": {
"mode": "Mode",
diff --git a/internal/web/translation/es-ES.json b/internal/web/translation/es-ES.json
index 2c1a764ae..a7ecf7081 100644
--- a/internal/web/translation/es-ES.json
+++ b/internal/web/translation/es-ES.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "Pool de direcciones",
"addressPoolDesc": "Las direcciones del túnel se asignan de estos prefijos: como máximo uno IPv4 y uno IPv6."
- }
+ },
+ "tunDesc": "Tipo de adaptador",
+ "tunDescTooltip": "Solo Windows: el tipo de túnel con el que se crea un adaptador Wintun nuevo. Vacío equivale a Wintun.",
+ "autoSystemDnsToGateway": "DNS del sistema a la puerta de enlace",
+ "autoSystemDnsToGatewayTooltip": "Solo Linux: apunta systemd-resolved a la puerta de enlace del TUN para que las consultas del sistema pasen por Xray. Necesita una puerta de enlace y el TUN no arranca si esto falla.",
+ "autoSystemWfpBlockLeak": "Bloquear fugas (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Solo Windows, con Auto system routes: dns mantiene el DNS dentro del TUN (necesita servidores DNS) y misconfigtun bloquea una versión de IP que ninguna ruta envía al TUN."
},
"info": {
"mode": "Modo",
diff --git a/internal/web/translation/fa-IR.json b/internal/web/translation/fa-IR.json
index d20f9741e..da42d9691 100644
--- a/internal/web/translation/fa-IR.json
+++ b/internal/web/translation/fa-IR.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "مخزن آدرس",
"addressPoolDesc": "آدرسهای تونل از این پیشوندها تخصیص داده میشوند — حداکثر یک IPv4 و یک IPv6."
- }
+ },
+ "tunDesc": "نوع آداپتور",
+ "tunDescTooltip": "فقط ویندوز: نوع تونلی که آداپتور Wintun جدید با آن ساخته میشود. خالی یعنی Wintun.",
+ "autoSystemDnsToGateway": "DNS سیستم به گیتوی",
+ "autoSystemDnsToGatewayTooltip": "فقط لینوکس: systemd-resolved را به گیتوی TUN میبرد تا کوئریهای سیستم از Xray عبور کنند. به گیتوی نیاز دارد و اگر این کار شکست بخورد TUN اجرا نمیشود.",
+ "autoSystemWfpBlockLeak": "جلوگیری از نشت (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "فقط ویندوز، همراه با مسیریابی خودکار سیستم: dns ترافیک DNS را داخل TUN نگه میدارد (به سرور DNS نیاز دارد) و misconfigtun نسخهای از IP را که هیچ مسیری به TUN نمیفرستد مسدود میکند."
},
"info": {
"mode": "حالت",
diff --git a/internal/web/translation/id-ID.json b/internal/web/translation/id-ID.json
index 0cb4d7e1a..024054197 100644
--- a/internal/web/translation/id-ID.json
+++ b/internal/web/translation/id-ID.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "Kumpulan alamat",
"addressPoolDesc": "Alamat terowongan diberikan dari prefiks ini — maksimal satu IPv4 dan satu IPv6."
- }
+ },
+ "tunDesc": "Jenis adaptor",
+ "tunDescTooltip": "Khusus Windows: jenis tunnel untuk adaptor Wintun baru. Kosong berarti Wintun.",
+ "autoSystemDnsToGateway": "DNS sistem ke gateway",
+ "autoSystemDnsToGatewayTooltip": "Khusus Linux: mengarahkan systemd-resolved ke gateway TUN agar lookup sistem lewat Xray. Butuh gateway, dan TUN tidak berjalan jika ini gagal.",
+ "autoSystemWfpBlockLeak": "Blokir kebocoran (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Khusus Windows, bersama Auto system routes: dns menjaga DNS tetap di dalam TUN (butuh server DNS), misconfigtun memblokir versi IP yang tidak dikirim rute mana pun ke TUN."
},
"info": {
"mode": "Mode",
diff --git a/internal/web/translation/ja-JP.json b/internal/web/translation/ja-JP.json
index 442025a20..2ad0a2f8c 100644
--- a/internal/web/translation/ja-JP.json
+++ b/internal/web/translation/ja-JP.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "アドレスプール",
"addressPoolDesc": "トンネルのアドレスはこれらのプレフィックスから割り当てられます(IPv4 と IPv6 をそれぞれ最大 1 つ)。"
- }
+ },
+ "tunDesc": "アダプターの種類",
+ "tunDescTooltip": "Windows のみ:新しく作成する Wintun アダプターのトンネル種別。空欄の場合は Wintun。",
+ "autoSystemDnsToGateway": "システム DNS をゲートウェイへ",
+ "autoSystemDnsToGatewayTooltip": "Linux のみ:systemd-resolved を TUN のゲートウェイに向け、システムの名前解決を Xray 経由にします。ゲートウェイが必要で、失敗すると TUN は起動しません。",
+ "autoSystemWfpBlockLeak": "リーク遮断 (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Windows のみ(自動システムルートと併用):dns は DNS を TUN 内に留め(DNS サーバーが必要)、misconfigtun は TUN へのルートがない IP バージョンを遮断します。"
},
"info": {
"mode": "モード",
diff --git a/internal/web/translation/pt-BR.json b/internal/web/translation/pt-BR.json
index bbba2b6a4..e62c85309 100644
--- a/internal/web/translation/pt-BR.json
+++ b/internal/web/translation/pt-BR.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "Pool de endereços",
"addressPoolDesc": "Os endereços do túnel são atribuídos a partir destes prefixos — no máximo um IPv4 e um IPv6."
- }
+ },
+ "tunDesc": "Tipo de adaptador",
+ "tunDescTooltip": "Somente Windows: o tipo de túnel com que um novo adaptador Wintun é criado. Vazio significa Wintun.",
+ "autoSystemDnsToGateway": "DNS do sistema para o gateway",
+ "autoSystemDnsToGatewayTooltip": "Somente Linux: aponta o systemd-resolved para o gateway do TUN para que as consultas do sistema passem pelo Xray. Precisa de um gateway, e o TUN não inicia se isso falhar.",
+ "autoSystemWfpBlockLeak": "Bloquear vazamentos (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Somente Windows, com Auto system routes: dns mantém o DNS dentro do TUN (precisa de servidores DNS) e misconfigtun bloqueia uma versão de IP que nenhuma rota envia ao TUN."
},
"info": {
"mode": "Modo",
diff --git a/internal/web/translation/ru-RU.json b/internal/web/translation/ru-RU.json
index 188fb3a6c..b8b4029bc 100644
--- a/internal/web/translation/ru-RU.json
+++ b/internal/web/translation/ru-RU.json
@@ -723,7 +723,13 @@
"masque": {
"addressPool": "Пул адресов",
"addressPoolDesc": "Адреса туннелей выдаются из этих префиксов — не более одного IPv4 и одного IPv6."
- }
+ },
+ "tunDesc": "Тип адаптера",
+ "tunDescTooltip": "Только Windows: тип туннеля, с которым создаётся новый адаптер Wintun. Пусто — Wintun.",
+ "autoSystemDnsToGateway": "Системный DNS на шлюз",
+ "autoSystemDnsToGatewayTooltip": "Только Linux: направляет systemd-resolved на шлюз TUN, чтобы системные запросы шли через Xray. Нужен шлюз; при ошибке TUN не запустится.",
+ "autoSystemWfpBlockLeak": "Блокировка утечек (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Только Windows, вместе с авто-маршрутами системы: dns удерживает DNS внутри TUN (нужны DNS-серверы), misconfigtun блокирует версию IP, которую ни один маршрут не ведёт в TUN."
},
"info": {
"mode": "Режим",
diff --git a/internal/web/translation/tr-TR.json b/internal/web/translation/tr-TR.json
index bd26b91c9..1d487bcb7 100644
--- a/internal/web/translation/tr-TR.json
+++ b/internal/web/translation/tr-TR.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "Adres havuzu",
"addressPoolDesc": "Tünel adresleri bu öneklerden atanır — en fazla bir IPv4 ve bir IPv6."
- }
+ },
+ "tunDesc": "Bağdaştırıcı türü",
+ "tunDescTooltip": "Yalnızca Windows: yeni bir Wintun bağdaştırıcısının oluşturulduğu tünel türü. Boş bırakılırsa Wintun.",
+ "autoSystemDnsToGateway": "Sistem DNS'ini ağ geçidine yönlendir",
+ "autoSystemDnsToGatewayTooltip": "Yalnızca Linux: sistem sorguları Xray üzerinden gitsin diye systemd-resolved'ı TUN ağ geçidine yönlendirir. Ağ geçidi gerekir ve bu başarısız olursa TUN başlamaz.",
+ "autoSystemWfpBlockLeak": "Sızıntıları engelle (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Yalnızca Windows, Auto system routes ile: dns, DNS'i TUN içinde tutar (DNS sunucuları gerekir); misconfigtun, hiçbir rotanın TUN'a göndermediği IP sürümünü engeller."
},
"info": {
"mode": "Mod",
diff --git a/internal/web/translation/uk-UA.json b/internal/web/translation/uk-UA.json
index d88d1a8bc..991e112b5 100644
--- a/internal/web/translation/uk-UA.json
+++ b/internal/web/translation/uk-UA.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "Пул адрес",
"addressPoolDesc": "Адреси тунелів видаються з цих префіксів — не більше одного IPv4 та одного IPv6."
- }
+ },
+ "tunDesc": "Тип адаптера",
+ "tunDescTooltip": "Лише Windows: тип тунелю, з яким створюється новий адаптер Wintun. Порожньо — Wintun.",
+ "autoSystemDnsToGateway": "Системний DNS на шлюз",
+ "autoSystemDnsToGatewayTooltip": "Лише Linux: спрямовує systemd-resolved на шлюз TUN, щоб системні запити йшли через Xray. Потрібен шлюз; у разі помилки TUN не запуститься.",
+ "autoSystemWfpBlockLeak": "Блокування витоків (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Лише Windows, разом з авто-маршрутами системи: dns утримує DNS усередині TUN (потрібні DNS-сервери), misconfigtun блокує версію IP, яку жоден маршрут не веде в TUN."
},
"info": {
"mode": "Режим",
diff --git a/internal/web/translation/vi-VN.json b/internal/web/translation/vi-VN.json
index 8482698b5..6df8d3ac7 100644
--- a/internal/web/translation/vi-VN.json
+++ b/internal/web/translation/vi-VN.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "Dải địa chỉ",
"addressPoolDesc": "Địa chỉ đường hầm được cấp từ các tiền tố này — tối đa một IPv4 và một IPv6."
- }
+ },
+ "tunDesc": "Loại adapter",
+ "tunDescTooltip": "Chỉ Windows: loại tunnel dùng khi tạo adapter Wintun mới. Để trống nghĩa là Wintun.",
+ "autoSystemDnsToGateway": "DNS hệ thống tới gateway",
+ "autoSystemDnsToGatewayTooltip": "Chỉ Linux: trỏ systemd-resolved tới gateway của TUN để truy vấn của hệ thống đi qua Xray. Cần có gateway, và TUN sẽ không khởi động nếu việc này thất bại.",
+ "autoSystemWfpBlockLeak": "Chặn rò rỉ (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "Chỉ Windows, cùng với Auto system routes: dns giữ DNS bên trong TUN (cần máy chủ DNS), misconfigtun chặn phiên bản IP mà không tuyến nào đưa vào TUN."
},
"info": {
"mode": "Chế độ",
diff --git a/internal/web/translation/zh-CN.json b/internal/web/translation/zh-CN.json
index 3ed919c00..a083b48bb 100644
--- a/internal/web/translation/zh-CN.json
+++ b/internal/web/translation/zh-CN.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "地址池",
"addressPoolDesc": "隧道地址从这些前缀中分配——最多一个 IPv4 和一个 IPv6。"
- }
+ },
+ "tunDesc": "适配器类型",
+ "tunDescTooltip": "仅限 Windows:新建 Wintun 适配器时使用的隧道类型,留空即为 Wintun。",
+ "autoSystemDnsToGateway": "系统 DNS 指向网关",
+ "autoSystemDnsToGatewayTooltip": "仅限 Linux:将 systemd-resolved 指向 TUN 网关,使系统解析经过 Xray。需要设置网关,失败时 TUN 不会启动。",
+ "autoSystemWfpBlockLeak": "阻止泄漏 (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "仅限 Windows,需配合自动系统路由:dns 让 DNS 只走 TUN(需设置 DNS 服务器),misconfigtun 阻止没有任何路由指向 TUN 的 IP 版本。"
},
"info": {
"mode": "模式",
diff --git a/internal/web/translation/zh-TW.json b/internal/web/translation/zh-TW.json
index 718e052c0..7a22cbca5 100644
--- a/internal/web/translation/zh-TW.json
+++ b/internal/web/translation/zh-TW.json
@@ -722,7 +722,13 @@
"masque": {
"addressPool": "位址池",
"addressPoolDesc": "通道位址從這些前綴中分配——最多一個 IPv4 與一個 IPv6。"
- }
+ },
+ "tunDesc": "介面卡類型",
+ "tunDescTooltip": "僅限 Windows:新建 Wintun 介面卡時使用的通道類型,留空即為 Wintun。",
+ "autoSystemDnsToGateway": "系統 DNS 指向閘道",
+ "autoSystemDnsToGatewayTooltip": "僅限 Linux:將 systemd-resolved 指向 TUN 閘道,使系統解析經過 Xray。需要設定閘道,失敗時 TUN 不會啟動。",
+ "autoSystemWfpBlockLeak": "阻止洩漏 (WFP)",
+ "autoSystemWfpBlockLeakTooltip": "僅限 Windows,需搭配自動系統路由:dns 讓 DNS 只走 TUN(需設定 DNS 伺服器),misconfigtun 阻止沒有任何路由指向 TUN 的 IP 版本。"
},
"info": {
"mode": "模式",