feat(tun-viewer): route-exclude-address GUI support (#6053)

This commit is contained in:
Sline
2026-01-10 10:50:44 +08:00
committed by GitHub
parent 35b2066d4c
commit a49000712d
17 changed files with 59 additions and 1 deletions

View File

@@ -12,7 +12,13 @@ import type { Ref } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch, TooltipIcon } from "@/components/base";
import {
BaseDialog,
BaseSplitChipEditor,
TooltipIcon,
DialogRef,
Switch,
} from "@/components/base";
import { useClash } from "@/hooks/use-clash";
import { enhanceProfiles } from "@/services/cmds";
import { showNotice } from "@/services/notice-service";
@@ -22,6 +28,12 @@ import { StackModeSwitch } from "./stack-mode-switch";
const OS = getSystem();
const splitRouteExcludeAddress = (value: string) =>
value
.split(/[,\n;\r]+/)
.map((item) => item.trim())
.filter(Boolean);
export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
const { t } = useTranslation();
@@ -32,6 +44,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
stack: "mixed",
device: OS === "macos" ? "utun1024" : "Mihomo",
autoRoute: true,
routeExcludeAddress: "",
autoRedirect: false,
autoDetectInterface: true,
dnsHijack: ["any:53"],
@@ -50,6 +63,9 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
stack: clash?.tun.stack ?? "gvisor",
device: clash?.tun.device ?? (OS === "macos" ? "utun1024" : "Mihomo"),
autoRoute: nextAutoRoute,
routeExcludeAddress: (clash?.tun["route-exclude-address"] ?? []).join(
",",
),
autoRedirect: computedAutoRedirect,
autoDetectInterface: clash?.tun["auto-detect-interface"] ?? true,
dnsHijack: clash?.tun["dns-hijack"] ?? ["any:53"],
@@ -62,6 +78,9 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
const onSave = useLockFn(async () => {
try {
const routeExcludeAddress = splitRouteExcludeAddress(
values.routeExcludeAddress,
);
const tun: IConfigData["tun"] = {
stack: values.stack,
device:
@@ -71,6 +90,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
: "Mihomo"
: values.device,
"auto-route": values.autoRoute,
"route-exclude-address": routeExcludeAddress,
...(OS === "linux"
? {
"auto-redirect": values.autoRedirect,
@@ -120,6 +140,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
: {}),
"auto-detect-interface": true,
"dns-hijack": ["any:53"],
"route-exclude-address": [],
"strict-route": false,
mtu: 1500,
};
@@ -127,6 +148,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
stack: "gvisor",
device: OS === "macos" ? "utun1024" : "Mihomo",
autoRoute: true,
routeExcludeAddress: "",
autoRedirect: false,
autoDetectInterface: true,
dnsHijack: ["any:53"],
@@ -284,6 +306,26 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
}
/>
</ListItem>
<BaseSplitChipEditor
value={values.routeExcludeAddress}
placeholder="192.168.0.0/16"
ariaLabel={t("settings.modals.tun.fields.routeExcludeAddress")}
disabled={!values.autoRoute}
onChange={(nextValue) =>
setValues((v) => ({ ...v, routeExcludeAddress: nextValue }))
}
renderHeader={(modeToggle) => (
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText
primary={t("settings.modals.tun.fields.routeExcludeAddress")}
/>
{modeToggle ? (
<Box sx={{ marginLeft: "auto" }}>{modeToggle}</Box>
) : null}
</ListItem>
)}
/>
</List>
</BaseDialog>
);

View File

@@ -444,6 +444,7 @@
"stack": "مكدس TUN",
"device": "Device Name",
"autoRoute": "توجيه تلقائي",
"routeExcludeAddress": "عناوين مستثناة من التوجيه",
"strictRoute": "توجيه صارم",
"autoDetectInterface": "الكشف التلقائي عن الواجهة",
"dnsHijack": "اختطاف DNS",

View File

@@ -444,6 +444,7 @@
"stack": "TUN-Modus-Stack",
"device": "Device Name",
"autoRoute": "Globale Routing automatisch einstellen",
"routeExcludeAddress": "Routen-Ausnahmeadressen",
"strictRoute": "Strenges Routing",
"autoDetectInterface": "Netzwerkschnittstelle automatisch auswählen",
"dnsHijack": "DNS-Hijacking",

View File

@@ -444,6 +444,7 @@
"stack": "Tun Stack",
"device": "Device Name",
"autoRoute": "Auto Route",
"routeExcludeAddress": "Route Exclude Address",
"strictRoute": "Strict Route",
"autoDetectInterface": "Auto Detect Interface",
"dnsHijack": "DNS Hijack",

View File

@@ -444,6 +444,7 @@
"stack": "Pila del modo TUN",
"device": "Device Name",
"autoRoute": "Configurar enrutamiento global automáticamente",
"routeExcludeAddress": "Direcciones excluidas de ruta",
"strictRoute": "Enrutamiento estricto",
"autoDetectInterface": "Detectar automáticamente la interfaz de salida del tráfico",
"dnsHijack": "Secuestro de DNS",

View File

@@ -444,6 +444,7 @@
"stack": "انباشته Tun",
"device": "Device Name",
"autoRoute": "مسیر خودکار",
"routeExcludeAddress": "نشانی‌های مستثنا از مسیردهی",
"strictRoute": "مسیر دقیق",
"autoDetectInterface": "تشخیص خودکار رابط",
"dnsHijack": "ربایش DNS",

View File

@@ -444,6 +444,7 @@
"stack": "Tumpukan Tun",
"device": "Device Name",
"autoRoute": "Rute Otomatis",
"routeExcludeAddress": "Alamat Pengecualian Rute",
"strictRoute": "Rute Ketat",
"autoDetectInterface": "Deteksi Antarmuka Otomatis",
"dnsHijack": "Pembajakan DNS",

View File

@@ -444,6 +444,7 @@
"stack": "TUNモードスタック",
"device": "Device Name",
"autoRoute": "グローバルルートを自動設定",
"routeExcludeAddress": "ルート除外アドレス",
"strictRoute": "厳格なルート",
"autoDetectInterface": "トラフィックの出口インターフェースを自動選択",
"dnsHijack": "DNSハイジャック",

View File

@@ -444,6 +444,7 @@
"stack": "스택",
"device": "장치 이름",
"autoRoute": "자동 라우팅",
"routeExcludeAddress": "라우트 제외 주소",
"strictRoute": "엄격 라우팅",
"autoDetectInterface": "인터페이스 자동 감지",
"dnsHijack": "DNS 하이재킹",

View File

@@ -444,6 +444,7 @@
"stack": "Стек",
"device": "Device Name",
"autoRoute": "Автоматическая маршрутизация",
"routeExcludeAddress": "Адреса исключения маршрута",
"strictRoute": "Строгая маршрутизация",
"autoDetectInterface": "Автоопределение интерфейса",
"dnsHijack": "DNS-перехват",

View File

@@ -444,6 +444,7 @@
"stack": "Tun Yığını",
"device": "Device Name",
"autoRoute": "Otomatik Yönlendirme",
"routeExcludeAddress": "Yönlendirme Hariç Adresler",
"strictRoute": "Katı Yönlendirme",
"autoDetectInterface": "Arayüzü Otomatik Algıla",
"dnsHijack": "DNS Ele Geçirme",

View File

@@ -444,6 +444,7 @@
"stack": "Стек",
"device": "Device Name",
"autoRoute": "Авто-маршрутлау",
"routeExcludeAddress": "Route Exclude Address",
"strictRoute": "Катгый маршрутлау",
"autoDetectInterface": "Интерфейсны автоматик ачыклау",
"dnsHijack": "DNS'ны үзгәртеп тоту (hijack)",

View File

@@ -444,6 +444,7 @@
"stack": "TUN 模式堆栈",
"device": "虚拟网卡名称",
"autoRoute": "自动设置全局路由",
"routeExcludeAddress": "排除自定义网段",
"strictRoute": "严格路由",
"autoDetectInterface": "自动选择流量出口接口",
"dnsHijack": "DNS 劫持",

View File

@@ -444,6 +444,7 @@
"stack": "虛擬網路介面卡模式堆疊",
"device": "Device Name",
"autoRoute": "自動設定全域路由",
"routeExcludeAddress": "排除自訂網段",
"strictRoute": "嚴格路由",
"autoDetectInterface": "自動偵測流量輸出介面",
"dnsHijack": "DNS 綁架",

View File

@@ -572,6 +572,7 @@ export const translationKeys = [
"settings.modals.tun.fields.stack",
"settings.modals.tun.fields.device",
"settings.modals.tun.fields.autoRoute",
"settings.modals.tun.fields.routeExcludeAddress",
"settings.modals.tun.fields.strictRoute",
"settings.modals.tun.fields.autoDetectInterface",
"settings.modals.tun.fields.dnsHijack",

View File

@@ -1015,6 +1015,7 @@ export interface TranslationResources {
device: string;
dnsHijack: string;
mtu: string;
routeExcludeAddress: string;
stack: string;
strictRoute: string;
};

View File

@@ -44,6 +44,7 @@ interface IConfigData {
"auto-redirect"?: boolean;
"auto-detect-interface": boolean;
"dns-hijack": string[];
"route-exclude-address"?: string[];
"strict-route": boolean;
mtu: number;
};