TUN 模式與系統代理的運作機制對比:流量到底在哪一層被接管

比較系統代理需應用程式主動讀取代理設定,以及 TUN 透過虛擬網卡接管所有 IP 流量的差異,說明命令列工具、遊戲與 UDP 應用在兩種模式下的表現為何不同,以及各自適用的情境。

先把結論擺在前面

系統代理和 TUN 模式不在同一層。系統代理是應用層約定:作業系統把代理位址寫進設定,應用程式主動來讀,讀了才走代理。TUN 模式是網路層接管:mihomo 建立一張虛擬網卡,核心把符合條件的 IP 封包全部送進網卡,應用程式不知道代理存在,也無法繞過。

一句話:系統代理靠應用程式配合,TUN 模式靠核心路由。兩者在命令列、遊戲、UDP 情境下表現完全不同,根源就在這裡。

系統代理:應用程式主動讀取,代理才生效

開啟系統代理後,Windows 在「設定」→「網路和網際網路」→「代理」寫入位址,macOS 在「系統設定」→「網路」→「代理」寫入同一份資訊。mihomo 預設在 127.0.0.1:7890 監聽混合連接埠,同時接受 HTTP 與 SOCKS5 連線。

關鍵在第二步:應用程式必須主動向系統查詢代理設定,並真正用這個位址建立連線。於是出現四類分化:

  • 瀏覽器與多數 Electron 應用程式走系統網路 API,會讀取,系統代理對它們有效。
  • 遊戲引擎常直接建立 socket,不查系統代理,直接裸連。
  • curlwgetgit 在 Windows 與 macOS 上預設不讀系統代理,只認 http_proxy / https_proxy 環境變數。
  • 所有 UDP 流量:HTTP 代理只承載 TCP;SOCKS5 雖有 UDP ASSOCIATE 擴充,絕大多數應用程式並不實作。

所以「開了代理,終端機裡 curl 還是直連」不是設定壞了,是系統代理的機制邊界。對照如下:

流量類型系統代理TUN 模式
瀏覽器 HTTP/HTTPS接管接管
命令列 curl / git / brew不接管(需環境變數)接管
遊戲與語音 UDP不接管接管
QUIC / HTTP/3不接管(瀏覽器降級 TCP)接管
區域網路裝置存取不受影響需排除內網網段

TUN 模式:虛擬網卡接管 IP 層

TUN 是核心提供的虛擬網路裝置。mihomo 開啟 TUN 後建立虛擬網卡——Windows 用 wintun 驅動,macOS 用 utun,Linux 用 tun——再修改路由表,把非本機位址的 IP 封包指向這張網卡。

流量路徑因此改變:

  1. 應用程式把資料交給核心;
  2. 核心依路由表送入虛擬網卡;
  3. mihomo 在使用者態讀取完整 IP 封包;
  4. 解出 TCP 或 UDP,依規則比對;
  5. 經節點轉發出去。

接管層級是網路層(L3),不是應用層(L7)。mihomo 不關心應用程式怎麼送資料,只看到一個個 IP 封包。三個直接結果:應用程式完全不知道自己在被代理;TCP 與 UDP 一視同仁;無論行程用什麼語言、什麼網路函式庫,都逃不出路由表。

代價同樣明確:建立虛擬網卡需要管理員或 root 權限;路由表被改動,內網與區域網路存取需要額外放行。

DNS 是 TUN 模式容易忽略的另一半。TUN 設定裡的 dns-hijack 把所有送往 53 連接埠的查詢劫持到本機解析,搭配 enhanced-mode: fake-ip,網域名稱解析也走代理鏈路,避免 DNS 洩漏。以 Clash Verge 預設設定為例:

tun:
  enable: true
  stack: mixed
  dns-hijack:
    - any:53

dns:
  enable: true
  enhanced-mode: fake-ip
  nameserver:
    - https://doh.pub/dns-query

開啟後,解析無法直連的網域名稱回傳的是 198.18.0.0/16 網段的 Fake-IP,真實解析由遠端 DoH 完成——這是判斷 TUN 是否真正生效的直觀訊號。

命令列、遊戲與 UDP:兩種模式的分水嶺

命令列工具

git clonecurlbrewnpmgo install 在系統代理模式下全部直連。只想開系統代理就覆蓋它們,需要手動匯出環境變數:

export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890

7890 是混合連接埠,HTTP 與 SOCKS5 共用,上面三行讓 git、curl、npm 走同一個入口。TUN 模式下不需要這一步,殘留的環境變數反而會造成重複代理,建議清掉。

遊戲與 UDP

遊戲配對、語音、狀態同步大量使用 UDP。系統代理在協定層面就不承載 UDP;即便開啟 SOCKS5,遊戲客戶端也不會去實作 UDP ASSOCIATE。於是常見「能登入、配對不到人」「語音時斷時續」的半通狀態。TUN 把 UDP 封包原樣收進虛擬網卡再依規則轉發,表現接近直連。

QUIC 與 HTTP/3

Chrome、Safari 對支援 HTTP/3 的網站優先嘗試 QUIC(UDP/443)。系統代理下瀏覽器偵測到代理不支援 UDP,自動降級回 TCP;TUN 下 QUIC 流量直接被接管,不降級。

情境對照:什麼時候用哪個

情境推薦模式理由
日常瀏覽網頁系統代理無需管理員權限,資源佔用低
開發與命令列TUN 模式一次覆蓋 git / npm / curl
遊戲、語音、視訊通話TUN 模式UDP 必須由網路層接管
公司內網與代理並存系統代理 + 規則內網網段不接管,策略更可控
不允許程式申請管理員權限系統代理TUN 建立網卡需要提權
全域抓封包、全量測試TUN 模式所有行程統一途徑

切換前的檢查清單

  • 連通性:用 curl -I https://www.gstatic.com/generate_204 驗證,別用 ping——ICMP 是否被接管取決於節點與堆疊,不能作為代理生效的依據。
  • DNS:解析一個無法直連的網域名稱,回傳 198.18.x.x 表示 Fake-IP 生效;回傳真實 IP 則檢查 dns-hijackenhanced-mode
  • 區域網路:印表機、NAS、路由器後台在 TUN 下可能被截走,在 tun 區段加 route-exclude-address: 192.168.0.0/16,或用規則直連。
  • Windows 相容性:遊戲或 P2P 連不上時,依序切換 stack: systemgvisormixed 再測。
  • 殘留環境變數:系統代理模式下,終端機執行 env | grep -i proxy,有殘留就 unset,否則命令列會繼續走舊代理。

常見誤區:開 TUN 後又開系統代理。兩者不會疊加,瀏覽器流量只是多繞一步進 7890 再出來。TUN 模式下把系統代理開關關掉,路徑最短,排查問題也更乾淨。

下載 Clash Verge