跳到主要內容

首頁 / 部落格 / DNS 與網路

TUN 模式底層:虛擬網路卡、路由表與 DNS 劫持是怎麼配合的

DNS 與網路2026-06-261968 字約 5 分鐘
TUN 模式底層:虛擬網路卡、路由表與 DNS 劫持是怎麼配合的

打開 TUN 開關的一瞬間,系統裡發生了三件事:多了一塊網路卡、路由表被改寫、53 連接埠被劫持。

理解這三件事,TUN 相關的所有疑難問題就都有了排查方向。

一、創建虛擬網路卡

TUN 是作業系統提供的一種虛擬網路設備。它在系統看來是一塊正常網路卡,但另一端不是物理線纜,而是一個使用者態程式——這裡就是 Mihomo 核心。

封包的旅程應用程式發出 IP 包系統路由決定從哪塊網路卡出去TUN 虛擬網路卡包被交給核心程式Mihomo 處理按規則決定直連或轉發
對應用來說完全透明,它以為自己在正常聯網

各平台的實現:

平台實現需要的權限
Windowswintun 驅動管理員(安裝驅動 + 系統服務)
macOSutun 核心擴充root(特權助手)
Linux/dev/net/tunCAP_NET_ADMIN

Clash Verge 的「服務模式」就是為了避免每次都要提權——裝一次系統服務,之後由服務代為執行特權操作。

二、改寫路由表

光有網路卡不夠,還要讓系統把流量往這塊網路卡上送。這靠修改路由表實現。

auto-route: true 時,核心會添加類似這樣的路由:

0.0.0.0/1    → TUN 网卡
128.0.0.0/1  → TUN 网卡

為什麼是兩條 /1 而不是一條 0.0.0.0/0?

因為路由匹配遵循「最長前綴優先」。系統原有的預設路由是 0.0.0.0/0,如果 TUN 也寫 0.0.0.0/0,兩條同等長度的路由會產生歧義。拆成兩條 /1 後,前綴更長,穩定壓過原預設路由,同時又不需要刪除原路由——這樣核心自己的出站流量還能通過原路由正常出去。

路由優先級(從高到低)1具體主機路由 322TUN 的兩條 13原預設路由 0
節點伺服器的 IP 必須走物理網路卡,否則流量會繞回 TUN 形成死循環

auto-detect-interface: true 讓核心自動識別真實出口網路卡(Wi-Fi 還是有線),這樣切換網路時能自動跟隨。

strict-route 的作用

tun:
  strict-route: true

開啟後會加更嚴格的路由規則和防火牆策略,確保沒有流量能繞過 TUN。副作用是與其他 VPN 軟體的衝突概率上升。

有 VPN 共存需求時關掉它。

排除特定網路卡

和企業 VPN 共存時:

tun:
  exclude-interface: ["ppp0", "Cisco AnyConnect"]

三、DNS 劫持

tun:
  dns-hijack:
    - any:53

含義:任何發往 53 連接埠的 DNS 查詢,無論目標是哪個伺服器,都截下來交給核心自己的 DNS 處理。

為什麼必須劫持:有些程式會硬編碼 DNS 伺服器(比如直接查 8.8.8.8),繞過系統 DNS 設定。不劫持的話,這些查詢會走原路徑出去,導致:

  • 解析結果不准(可能被污染)
  • 網域資訊丟失,核心只能拿 IP 做規則匹配
  • DNS 泄漏——ISP 能看到你查了哪些網域
有無 DNS 劫持的差別程式硬編碼查 8.8.8.8發出 UDP 53 包無劫持包經 TUN 轉發到 8.8.8.8有劫持包被核心截下自己回答結果前者可能被污染且泄漏,後者可控
TUN 模式下 dns-hijack 基本是必開項

四、協議棧:gvisor / system / mixed

TUN 拿到的是原始 IP 包,需要一個 TCP/IP 協議棧來還原成連接。三種實現:

三種 stack 的取舍gvisor使用者態相容性最好效能略低預設推薦system交給作業效能最高對系統設定要求高、相容性差些追求極限效能mixedTCP折中大多數場景的最優解Mihomo 常用預設
出問題時優先切 gvisor,它最不容易出錯

選擇建議:

情況
不確定 / 首次設定mixed
出現奇怪的連接問題gvisor
軟路由、追求吞吐system
macOS 上 UDP 有問題gvisor

五、MTU 與分片

tun:
  mtu: 1500

MTU 是單個封包的最大字節數。TUN 網路卡的 MTU 如果設得比實际鏈路大,包會被分片,效能下降;設得太小,傳輸效率低。

1500 是以太網標準值,通常不用改。但如果你的節點走的是本身就有封裝開銷的鏈路(某些中轉、PPPoE 撥號),實际可用 MTU 會小於 1500,可能需要下調到 1400~1450。

六、完整的 TUN 設定

tun:
  enable: true
  stack: mixed
  device: Mihomo
  auto-route: true
  auto-detect-interface: true
  auto-redirect: false          # Linux 上的额外重定向
  strict-route: false
  mtu: 1500
  dns-hijack:
    - any:53
    - tcp://any:53
  # 排除某些網路卡,避免和 VPN 衝突
  # exclude-interface: ["ppp0"]
  # 排除某些行程(Mihomo 支援)
  # exclude-package: ["com.example.app"]   # Android

配合的 DNS 設定:

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
    - "+.pool.ntp.org"
    - "+.msftconnecttest.com"
    - "+.msftncsi.com"
  nameserver: [223.5.5.5, https://doh.pub/dns-query]

必須同時配好 DNS——TUN 接管了所有流量,如果 DNS 沒配好,什麼都解析不了。

常見問題的底層原因

現象底層原因處理
開 TUN 後全網斷路由改寫了但核心出站流量繞回自己確認 auto-detect-interface: true;重新啟動
關掉軟體後網路復原不了強殺行程導致路由未撤銷重新啟動 Clash Verge 後正常退出,或重新啟動系統
區域網路設備訪問不了內網 IP 段沒有直連規則IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
NAS / 列印機找不到mDNS 網域被 fake-ip 攔了fake-ip-filter"*.local""*.lan"
和公司 VPN 衝突兩者都改路由表strict-route,用 exclude-interface
系統提示「無 Internet 連接」連通性偵測網域被 fake-ipfilter 加 "+.msftconnecttest.com"
大檔案下載卡住MTU 過大導致分片丟失mtu 調到 1400
UDP 游戲連不上節點不支援 UDP,或 stack 不合適確認節點 udp: true,stack 換 gvisor
CPU 佔用高所有流量都過使用者態協議棧stack 換 system,或關 TUN 只用系統代理

怎麼驗證 TUN 真的在工作

看網路卡:

# Windows
Get-NetAdapter | Where-Object {$_.InterfaceDescription -like "*wintun*"}
# Linux / macOS
ip link show    # 或 ifconfig

應該能看到一塊名為 MihomoutunX 的網路卡。

看路由:

# Windows
route print -4
# Linux
ip route show

應該能看到兩條指向 TUN 網路卡的 /1 路由。

看流量是否真的經過:

打開 Clash Verge 的連接頁,用一個明確不讀系統代理的程式(比如命令列 curl 且沒設環境變數)訪問外網。如果連接頁出現了記錄,說明 TUN 生效了。

小結

TUN 的三件事:

  • 虛擬網路卡——需要驅動和特權,靠服務模式解決
  • 路由表——兩條 /1 接管全局,節點 IP 單獨走物理網路卡
  • DNS 劫持——防止硬編碼 DNS 繞過核心

出問題時按這三層排查:網路卡在不在 → 路由對不對 → DNS 通不通。

相關:DNS 與 fake-ip 詳解分流實戰


相關文件