feat(tun): auto-redirect GUI support for linux (#5565)

* feat(tun): auto-redirect GUI support for linux

* refactor(tun-viewer): unify Linux-only auto-redirect row layout
This commit is contained in:
Sline
2025-11-22 18:58:57 +08:00
committed by GitHub
parent 45020fceda
commit 4ff186497c
17 changed files with 110 additions and 30 deletions

View File

@@ -13,6 +13,7 @@ import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useClash } from "@/hooks/use-clash";
import { enhanceProfiles } from "@/services/cmds";
import { showNotice } from "@/services/noticeService";
@@ -32,6 +33,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
stack: "mixed",
device: OS === "macos" ? "utun1024" : "Mihomo",
autoRoute: true,
autoRedirect: OS === "linux",
autoDetectInterface: true,
dnsHijack: ["any:53"],
strictRoute: false,
@@ -41,10 +43,15 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
useImperativeHandle(ref, () => ({
open: () => {
setOpen(true);
const nextAutoRoute = clash?.tun["auto-route"] ?? true;
const rawAutoRedirect = clash?.tun["auto-redirect"] ?? true;
const computedAutoRedirect =
OS === "linux" ? (nextAutoRoute ? rawAutoRedirect : false) : false;
setValues({
stack: clash?.tun.stack ?? "gvisor",
device: clash?.tun.device ?? (OS === "macos" ? "utun1024" : "Mihomo"),
autoRoute: clash?.tun["auto-route"] ?? true,
autoRoute: nextAutoRoute,
autoRedirect: computedAutoRedirect,
autoDetectInterface: clash?.tun["auto-detect-interface"] ?? true,
dnsHijack: clash?.tun["dns-hijack"] ?? ["any:53"],
strictRoute: clash?.tun["strict-route"] ?? false,
@@ -56,7 +63,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
const onSave = useLockFn(async () => {
try {
const tun = {
const tun: IConfigData["tun"] = {
stack: values.stack,
device:
values.device === ""
@@ -65,6 +72,11 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
: "Mihomo"
: values.device,
"auto-route": values.autoRoute,
...(OS === "linux"
? {
"auto-redirect": values.autoRedirect,
}
: {}),
"auto-detect-interface": values.autoDetectInterface,
"dns-hijack": values.dnsHijack[0] === "" ? [] : values.dnsHijack,
"strict-route": values.strictRoute,
@@ -100,10 +112,15 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
variant="outlined"
size="small"
onClick={async () => {
const tun = {
const tun: IConfigData["tun"] = {
stack: "gvisor",
device: OS === "macos" ? "utun1024" : "Mihomo",
"auto-route": true,
...(OS === "linux"
? {
"auto-redirect": true,
}
: {}),
"auto-detect-interface": true,
"dns-hijack": ["any:53"],
"strict-route": false,
@@ -113,6 +130,7 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
stack: "gvisor",
device: OS === "macos" ? "utun1024" : "Mihomo",
autoRoute: true,
autoRedirect: OS === "linux" ? true : false,
autoDetectInterface: true,
dnsHijack: ["any:53"],
strictRoute: false,
@@ -175,10 +193,41 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
<Switch
edge="end"
checked={values.autoRoute}
onChange={(_, c) => setValues((v) => ({ ...v, autoRoute: c }))}
onChange={(_, c) =>
setValues((v) => ({
...v,
autoRoute: c,
autoRedirect: c ? v.autoRedirect : false,
}))
}
/>
</ListItem>
{OS === "linux" && (
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText
primary={t("settings.modals.tun.fields.autoRedirect")}
sx={{ maxWidth: "fit-content" }}
/>
<TooltipIcon
title={t("settings.modals.tun.tooltips.autoRedirect")}
sx={{ opacity: values.autoRoute ? 0.7 : 0.3 }}
/>
<Switch
edge="end"
checked={values.autoRedirect}
onChange={(_, c) =>
setValues((v) => ({
...v,
autoRedirect: v.autoRoute ? c : v.autoRedirect,
}))
}
disabled={!values.autoRoute}
sx={{ marginLeft: "auto" }}
/>
</ListItem>
)}
<ListItem sx={{ padding: "5px 2px" }}>
<ListItemText primary={t("settings.modals.tun.fields.strictRoute")} />
<Switch

View File

@@ -427,10 +427,12 @@
"strictRoute": "توجيه صارم",
"autoDetectInterface": "الكشف التلقائي عن الواجهة",
"dnsHijack": "اختطاف DNS",
"mtu": "وحدة الإرسال القصوى"
"mtu": "وحدة الإرسال القصوى",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "تم تطبيق الإعدادات"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Strenges Routing",
"autoDetectInterface": "Netzwerkschnittstelle automatisch auswählen",
"dnsHijack": "DNS-Hijacking",
"mtu": "Maximale Übertragungseinheit"
"mtu": "Maximale Übertragungseinheit",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Einstellungen angewendet"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Strict Route",
"autoDetectInterface": "Auto Detect Interface",
"dnsHijack": "DNS Hijack",
"mtu": "Max Transmission Unit"
"mtu": "Max Transmission Unit",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Settings Applied"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Enrutamiento estricto",
"autoDetectInterface": "Detectar automáticamente la interfaz de salida del tráfico",
"dnsHijack": "Secuestro de DNS",
"mtu": "Unidad máxima de transmisión"
"mtu": "Unidad máxima de transmisión",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Ajustes aplicados"

View File

@@ -427,10 +427,12 @@
"strictRoute": "مسیر دقیق",
"autoDetectInterface": "تشخیص خودکار رابط",
"dnsHijack": "ربایش DNS",
"mtu": "واحد حداکثر انتقال"
"mtu": "واحد حداکثر انتقال",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "تنظیمات اعمال شد"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Rute Ketat",
"autoDetectInterface": "Deteksi Antarmuka Otomatis",
"dnsHijack": "Pembajakan DNS",
"mtu": "Unit Transmisi Maksimum"
"mtu": "Unit Transmisi Maksimum",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Pengaturan Diterapkan"

View File

@@ -427,10 +427,12 @@
"strictRoute": "厳格なルート",
"autoDetectInterface": "トラフィックの出口インターフェースを自動選択",
"dnsHijack": "DNSハイジャック",
"mtu": "最大転送単位"
"mtu": "最大転送単位",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "設定が適用されました。"

View File

@@ -427,10 +427,12 @@
"strictRoute": "엄격 라우팅",
"autoDetectInterface": "인터페이스 자동 감지",
"dnsHijack": "DNS 하이재킹",
"mtu": "MTU"
"mtu": "MTU",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "여러 DNS 서버는 쉼표(,)로 구분하세요"
"dnsHijack": "여러 DNS 서버는 쉼표(,)로 구분하세요",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "설정이 적용되었습니다"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Строгая маршрутизация",
"autoDetectInterface": "Автоопределение интерфейса",
"dnsHijack": "DNS-перехват",
"mtu": "MTU"
"mtu": "MTU",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Настройки применены"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Katı Yönlendirme",
"autoDetectInterface": "Arayüzü Otomatik Algıla",
"dnsHijack": "DNS Ele Geçirme",
"mtu": "Maksimum İletim Birimi"
"mtu": "Maksimum İletim Birimi",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Ayarlar Uygulandı"

View File

@@ -427,10 +427,12 @@
"strictRoute": "Катгый маршрутлау",
"autoDetectInterface": "Интерфейсны автоматик ачыклау",
"dnsHijack": "DNS'ны үзгәртеп тоту (hijack)",
"mtu": "MTU (макс. тапшыру берәмлеге)"
"mtu": "MTU (макс. тапшыру берәмлеге)",
"autoRedirect": "Auto Redirect"
},
"tooltips": {
"dnsHijack": "Please use , to separate multiple DNS servers"
"dnsHijack": "Please use , to separate multiple DNS servers",
"autoRedirect": "Automatically configures nftables/iptables TCP redirects"
},
"messages": {
"applied": "Көйләүләр кулланылды"

View File

@@ -427,10 +427,12 @@
"strictRoute": "严格路由",
"autoDetectInterface": "自动选择流量出口接口",
"dnsHijack": "DNS 劫持",
"mtu": "最大传输单元"
"mtu": "最大传输单元",
"autoRedirect": "自动重定向"
},
"tooltips": {
"dnsHijack": "多个 DNS 服务器请使用 , 分隔"
"dnsHijack": "多个 DNS 服务器请使用 , 分隔",
"autoRedirect": "自动配置 nftables/iptables 的 TCP 重定向"
},
"messages": {
"applied": "设置已应用"

View File

@@ -427,10 +427,12 @@
"strictRoute": "嚴格路由",
"autoDetectInterface": "自動偵測流量輸出介面",
"dnsHijack": "DNS 綁架",
"mtu": "最大傳輸單位"
"mtu": "最大傳輸單位",
"autoRedirect": "自動重導"
},
"tooltips": {
"dnsHijack": "請用半形逗號來區隔多個 DNS 伺服器"
"dnsHijack": "請用半形逗號來區隔多個 DNS 伺服器",
"autoRedirect": "自動配置 nftables/iptables 的 TCP 重導"
},
"messages": {
"applied": "設定已套用"

View File

@@ -558,7 +558,9 @@ export const translationKeys = [
"settings.modals.tun.fields.autoDetectInterface",
"settings.modals.tun.fields.dnsHijack",
"settings.modals.tun.fields.mtu",
"settings.modals.tun.fields.autoRedirect",
"settings.modals.tun.tooltips.dnsHijack",
"settings.modals.tun.tooltips.autoRedirect",
"settings.modals.tun.messages.applied",
"settings.modals.dns.dialog.title",
"settings.modals.dns.dialog.warning",

View File

@@ -989,6 +989,7 @@ export interface TranslationResources {
tun: {
fields: {
autoDetectInterface: string;
autoRedirect: string;
autoRoute: string;
device: string;
dnsHijack: string;
@@ -1001,6 +1002,7 @@ export interface TranslationResources {
};
title: string;
tooltips: {
autoRedirect: string;
dnsHijack: string;
};
};

View File

@@ -41,6 +41,7 @@ interface IConfigData {
stack: string;
device: string;
"auto-route": boolean;
"auto-redirect"?: boolean;
"auto-detect-interface": boolean;
"dns-hijack": string[];
"strict-route": boolean;