旁路閘道拓撲:主路由不變、誰當預設閘道

所謂旁路網關,在本文語境裡指:主路由器仍負責撥接/對外 WAN、也仍可以是區網裡的 DHCP 伺服器;你只是把「要出網的下一跳」改成一台常駐的 Linux 小主機。這台機器與其他裝置位於同一 L2 網段(例如 192.168.1.0/24),靠單網路埠就能扮演閘道角色。相對於整機刷成軟路由,這種做法的好處是回滾成本低:客戶端把閘道改回主路由 IP,旁路方案就立即下線。若你想先對照「路由器上跑 Clash」的另一條路線,可讀 OpenWrt OpenClash 橋接閘道與 DNS 分流,再把本文當成「純 Linux 硬體」版本。

在開始貼指令前,請先在紙上寫清楚四個數字:主路由 LAN IP旁路 Linux 的固定 IP區網遮罩、以及要給客戶端用的 DNS(可先用主路由、或改指旁路機,後文會說明取捨)。少了這張小地圖,你很容易在 nft 與路由表之間迷路。若你同時需要釐清「只開代理埠給手機連」與「整台機器當閘道」的差異,也可交叉閱讀 區網共享與綁定位址排查,兩者症狀有時很像,但根因不同。

名詞對齊:下文以 eth0 表示面向區網的介面名稱;請以 ip -br link 或 NetworkManager 實際名稱替換(常見為 enp1s0eno1 等)。TUN 裝置名稱則依 Clash 設定檔 tun.device 為準,預設常見為 Meta 或自訂字串。

DHCP 與客戶端:如何把閘道指到 Linux 小主機

全屋裝置要「自動」把閘道指到旁路機,實務上有兩條路:在主路由的 DHCP 選項裡改預設閘道(最省事),或只在特定裝置上手動設靜態 IP(最可控)。前者依廠牌而異,但概念都是在 DHCP Offer 裡把 option 3(router) 從主路由 IP 改成旁路 Linux IP;後者則在 Windows、macOS、Android/iOS 的 Wi‑Fi 詳細資訊裡填寫閘道與 DNS。若你只想先驗證單一筆電,建議先用靜態閘道,確認 nft 與 Clash 都穩了,再動全屋 DHCP,避免全家一起斷網。

DNS 要指哪?常見做法是:要嘛讓客戶端仍用主路由當 DNS(最少意外),要嘛把 DNS 指到旁路機上由 Clash 的 dns 區段接聽(策略較一致,但要同步處理 allow-lan 與防火牆放行)。Fake-IP 與分流規則若寫得過激,會讓「只有瀏覽器壞掉」這類假陽性變多;這時請回到 Clash Meta DNS:nameserver、fallback 與 fake-ip-filter,先把解析鏈對齊,再懷疑節點。

核心轉發:sysctl 與介面命名前置

當客戶端把閘道設成旁路 Linux,對外封包會以「轉送(forward)」形式進入你的機器。第一件事是開啟 IPv4 轉發,否則核心會直接丟棄非目的地為本機的封包。建議用設定檔持久化,而不是只跑一次性命令。

/etc/sysctl.d/99-ipforward.conf
net.ipv4.ip_forward=1

套用後以 sysctl net.ipv4.ip_forward 應顯示為 1。若你同時啟用 IPv6,還要另外處理 net.ipv6.conf.all.forwarding 與對應的 nft 族;本文先專注在 IPv4 主幹,降低變因。接著確認預設 FORWARD 政策:許多桌面預設偏保守,搭配 nft 時建議以明確規則放行「區網介面 ↔ 上游」的轉送,而不是先全開再忘記收斂。

旁路機本機跑 Clash 並啟用 TUN 的細節(權限、systemd、工作目錄)請直接對照 Ubuntu TUN 與 systemd 自啟實測;本文不再重複二進位安裝,只補「閘道轉送」這一層。

nftables:FORWARD 放行與 SNAT/MASQUERADE

同一網段內,客戶端把閘道指到旁路機時,出網封包的來源 IP 仍是客戶端自己的位址;旁路機若要再把封包轉給主路由,通常需要來源位址轉換(SNAT/MASQUERADE),讓回程封包先回到旁路機,再由它轉回客戶端。否則主路由可能以「不是我家子網該處理的流程」而丟棄或走錯誤路徑。以下 nft 骨架以「單埠接區網、上游仍是同一台主路由」為模型:轉送鏈允許已建立連線與相關封包,並在離開區網介面往上游時做 masquerade。

nftables 骨架(請替換介面名與網段)
flush ruleset

table ip filter {
  chain forward {
    type filter hook forward priority 0; policy drop;
    ct state established,related accept
    iif "eth0" oif "eth0" accept
  }
}

table ip nat {
  chain postrouting {
    type nat hook postrouting priority 100;
    oif "eth0" masquerade
  }
}

上面第二段同進同出(iifoif 皆為 eth0)是「單臂旁路」語意下的簡化示意:實務上請依你的路由表微調,並用 nft list rulesettcpdump 驗證封包真的離開旁路機前往主路由。若你已有 ufw 或其他管理工具,請避免雙重寫入造成規則互相覆蓋;要嘛統一交給 nft,要嘛先停用以利除錯。更進階的透明轉發(例如把特定埠轉到 Clash 的 redir/tproxy 埠)屬於另一條「純轉送層」設計,與 TUN auto-route 可並存也可衝突,務必分段驗證。

安全提醒:把一台機器變成全屋閘道,等同提高它的信任邊界;請保持系統更新、SSH 金鑰登入、nft 預設拒絕(policy drop)並只放行必要轉送。不要在公開介面上開著無密碼的管理 API。

Clash:TUN、allow-lan、DNS 與區網連線

Clash 端,你需要三件事同時成立:TUN 啟用(讓本機協定堆疊能按規則接管流量)、allow-lan(讓區網能連到監聽埠與 DNS,若你走埠+DNS 方案)、以及規則與 DNS 策略彼此不打架。TUN 相關欄位語意可讀 TUN 模式深度解析,理解 auto-routeauto-detect-interfacestrict-route 的取捨後,再回來調旁路機上的實際路由表。

實務上常見落差是:TUN 與自動路由對「本機產生的流量」很直覺,但對「從 FORWARD 進來的客戶端流量」是否同樣進入 Clash,會受核心版本、Meta 堆疊(systemgvisor)與路由策略影響。若你發現旁路機本機上網正常、客戶端卻不命中規則,不要先急著改訂閱,應先確認封包是否真的進入 Clash 期望的路徑;必要時可改採「閘道機 redir/tproxy 到 mixed-port」這類顯式轉送,或縮小測試面只驗證 TCP 80/443。

config.yaml 片段(示意,請依版本調整)
allow-lan: true
bind-address: "*"

tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  strict-route: false

規則面請維持「由上而下」的習慣,把區網直連、區域管理後台與內網服務放在前面,避免被過寬的代理規則吃掉;整體順序可對照 規則分流最佳實踐。若旁路機也會跑 Docker 或虛擬機,記得把橋接網段排除在強制代理之外,否則本機容器的第一跳就可能被導偏。

驗證順序:從 ping 閘道到外網策略命中

建議固定這個順序,能省下大量猜測時間:(1) 客戶端能否 ping 旁路 Linux IP;(2) 客戶端能否 ping 主路由 IP;(3) 旁路機上 tcpdump -i eth0 icmp 是否看得到雙向 echo;(4) 再測 DNS 與 HTTP。當 (1)(2) 都通但網頁不開,優先查 DNS 與 fake-ip,而不是先去改節點。若只有特定應用異常,可再對照 客戶端選型 思考「該裝置是否改走本機圖形客戶端更省維護成本」。

在旁路機上用 ip routeip rule 對照 Clash 啟動前後差異,並用核心日誌確認沒有反覆重啟;這與你在單機 Ubuntu 上排錯是同一套方法,只是多了一個「轉送客戶端」視角。當一切穩定後,再把 DHCP 的預設閘道從主路由切到旁路機,並保留一臺「不改閘道」的備援裝置,避免日後誤設定時全家無門可入。

結語

Clash 旁路網關的本質,是把「路由決策」從主路由挪到一台你可掌控的 Linux 上;nftables 負責把轉送與 NAT 變成可審計的規則,而 TUN 則讓 Clash 有機會在系統堆疊裡做策略分流。三者接縫處,正是最多人卡關的地方:請用固定 IP、可回滾的 DHCP、以及分段驗證保護全家上網路徑。相較於依賴單一黑箱腳本,把 sysctl、nft 與 Clash 日誌拆開看懂,長期維護會便宜得多。

若你希望桌面與旁路閘道共用同一套規則思維,挑一款能把訂閱、模式切換與日誌呈現都整理清楚的客戶端,會比到處複製片段 YAML 更穩;但在 Linux 閘道場景,上游核心搭配 systemd 仍然最透明。

立即免費下載 Clash,開啟流暢上網新體驗,把旁路閘道的路由、nft 與 TUN 都對齊後,把時間花在真正想連的服務與內容上。