打開 TUN 開關的一瞬間,系統裡發生了三件事:多了一塊網路卡、路由表被改寫、53 連接埠被劫持。
理解這三件事,TUN 相關的所有疑難問題就都有了排查方向。
一、創建虛擬網路卡
TUN 是作業系統提供的一種虛擬網路設備。它在系統看來是一塊正常網路卡,但另一端不是物理線纜,而是一個使用者態程式——這裡就是 Mihomo 核心。
各平台的實現:
| 平台 | 實現 | 需要的權限 |
|---|---|---|
| Windows | wintun 驅動 | 管理員(安裝驅動 + 系統服務) |
| macOS | utun 核心擴充 | root(特權助手) |
| Linux | /dev/net/tun | CAP_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 後,前綴更長,穩定壓過原預設路由,同時又不需要刪除原路由——這樣核心自己的出站流量還能通過原路由正常出去。
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 能看到你查了哪些網域
四、協議棧:gvisor / system / mixed
TUN 拿到的是原始 IP 包,需要一個 TCP/IP 協議棧來還原成連接。三種實現:
選擇建議:
| 情況 | 選 |
|---|---|
| 不確定 / 首次設定 | mixed |
| 出現奇怪的連接問題 | gvisor |
| 軟路由、追求吞吐 | system |
| macOS 上 UDP 有問題 | gvisor |
五、MTU 與分片
tun:
mtu: 1500MTU 是單個封包的最大字節數。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-ip | filter 加 "+.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應該能看到一塊名為 Mihomo 或 utunX 的網路卡。
看路由:
# Windows
route print -4# Linux
ip route show應該能看到兩條指向 TUN 網路卡的 /1 路由。
看流量是否真的經過:
打開 Clash Verge 的連接頁,用一個明確不讀系統代理的程式(比如命令列 curl 且沒設環境變數)訪問外網。如果連接頁出現了記錄,說明 TUN 生效了。
小結
TUN 的三件事:
- 虛擬網路卡——需要驅動和特權,靠服務模式解決
- 路由表——兩條
/1接管全局,節點 IP 單獨走物理網路卡 - DNS 劫持——防止硬編碼 DNS 繞過核心
出問題時按這三層排查:網路卡在不在 → 路由對不對 → DNS 通不通。
相關:DNS 與 fake-ip 詳解、分流實戰。
相關文件
講清楚 fake-ip 的工作原理、和 redir-host 的本質區別、nameserver 與 fallback 的分工、DNS 泄漏怎麼防,以及內網網域解析失敗的根因。
講清楚游戲流量的特殊性:為什麼 UDP 必須靠 TUN、NAT 類型是怎麼回事、丟包比延遲更致命,以及一份面向低延遲的設定調整清單。