OpenWrt 旁路由執行 mihomo 核心:透明代理部署流程
整理在 OpenWrt 主路由或旁路由直接執行 mihomo 核心的部署流程,涵蓋核心檔案、設定目錄、透明代理轉送及區域網路裝置的閘道設定。
先釐清部署範圍:核心、閘道與透明代理是三回事
在 OpenWrt 上直接執行 mihomo,不代表安裝了有圖形介面的 Clash 用戶端。核心負責讀取設定、建立代理連線及執行規則;系統則負責將終端流量導入核心。啟動記錄正常,只能證明程序正在執行,無法證明區域網路裝置正在使用代理。
本文以 OpenWrt 23.05、24.10 常見的 firewall4 與 nftables 環境為基礎,採用 Linux TUN 搭配自動路由的部署方式。設定欄位是否可用,請以目前 mihomo 版本的設定檢查結果為準。舊版 firewall3、廠商客製化防火牆及既有代理外掛,不宜直接套用相同的流量接管規則。
- 主路由部署:OpenWrt 原本就是終端的預設閘道,重點在於核心接管流量、防火牆放行及 DNS 轉送。
- 旁路由部署:OpenWrt 與主路由位於同一個區域網路,還需要調整測試終端的閘道與 DNS。
- 明確指定代理測試:由應用程式連線至
7890混合連接埠,只用來初步確認節點與規則,不代表透明代理已設定完成。
規劃旁路由位址與終端閘道
先用一台終端進行驗證,不要立刻修改整個區域網路的 DHCP 發放設定。以下是一組完整的範例位址;實際部署時,應依照現有子網路一併調整,不要只修改其中一個位址。
| 裝置或參數 | 範例值 | 用途 |
|---|---|---|
| 區域網路子網路 | 192.168.10.0/24 | 主路由、旁路由與終端位於同一子網路 |
| 主路由 | 192.168.10.1 | 連線至網際網路,並繼續提供 DHCP |
| OpenWrt 旁路由 | 192.168.10.2 | 使用固定位址,避免與 DHCP 位址池衝突 |
| 旁路由預設閘道 | 192.168.10.1 | 核心連線至節點及直連目的地的上游閘道 |
| 測試終端 | 192.168.10.100 | 沿用原有子網路遮罩 |
| 終端閘道與 DNS | 192.168.10.2 | 將測試終端的流量與 DNS 查詢交由旁路由處理 |
先在 LuCI 檢查「網路」→「介面」→「LAN」→「編輯」中的固定位址、IPv4 閘道與 DNS 設定。單網路埠旁路由通常透過 br-lan 連線至主路由;雙網路埠主路由則可能經由 PPPoE 或其他 WAN 裝置連外,請勿只憑網路卡名稱猜測出口。
ip -4 addr show
ip -4 route show
ip route get 223.5.5.5
cat /etc/resolv.conf
旁路由本身的預設路由應指向主路由,而不是指向自己。初次部署時,旁路由系統 DNS 請先使用可直接連線的 DNS 服務,避免發生「核心啟動時需要解析節點網域名稱,但 DNS 解析又依賴尚未啟動的核心」這類迴圈。
主路由只需保留一個 DHCP 服務。旁路由不要在同一個廣播網域再發放另一組位址。IPv6 也必須另外規劃:即使手動修改終端的 IPv4 閘道,終端仍可能透過主路由發出的 IPv6 路由公告直接連外。
放置 mihomo 核心與設定目錄
確認架構、核心模組與儲存空間
先確認 CPU 架構與韌體資訊,再選擇相符的 Linux 執行檔。x86_64、aarch64 與不同 MIPS 變體不可混用;部分發行套件還會區分指令集等級。檔名看起來相近,不代表能在同一台裝置上執行。
uname -m
ubus call system board
df -h /overlay /tmp
opkg list-installed | grep -E 'kmod-tun|firewall4|nftables'
使用 opkg 的官方韌體可透過 opkg update 和 opkg install kmod-tun 安裝 TUN 模組。模組必須與目前韌體核心相符;若相依性不符,應修正韌體與套件來源的對應關係,不要強制安裝其他核心版本的模組。自動接管所需的 nftables 功能,也取決於韌體的編譯選項。
固定執行檔路徑與工作目錄
將已解壓縮且符合裝置架構的核心上傳至 /usr/bin/mihomo,並將設定檔放在 /etc/mihomo/config.yaml。設定檔可能包含訂閱憑證,請勿讓一般使用者讀取目錄或檔案。若裝置的持久儲存空間不足,應先規劃外接儲存裝置,不要長期將正式設定放在重新啟動後會清空的 /tmp。
mkdir -p /etc/mihomo
chmod 700 /etc/mihomo
chmod 755 /usr/bin/mihomo
chmod 600 /etc/mihomo/config.yaml
/usr/bin/mihomo -v
/usr/bin/mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml
-d 用來指定工作目錄,-f 用來指定設定檔,-t 則只會檢查設定。若設定引用 GeoIP、GeoSite、規則集或代理提供者檔案,也要檢查對應路徑、讀取權限及更新網路。初次排查時可先移除這些外部相依項目,避免將下載失敗誤判為 TUN 故障。
先驗證明確指定代理,再啟用 TUN 接管
建議分兩次啟動。第一次使用實際可用的節點設定,將 tun.enable 設為 false,再透過混合連接埠測試路由器本機連線。第二次確認節點可用後,再啟用 TUN 與自動路由。如此可分別排查節點問題與流量轉送問題。
以下提供最精簡的設定結構,用來檢查設定與直連基準。這份設定沒有代理節點,策略群組也只有 DIRECT,因此不會產生代理出口。正式使用時,請合併訂閱中的有效節點或 proxy-providers,並將實際節點加入策略群組;不要直接覆蓋既有的完整設定。
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
ipv6: false
tun:
enable: false
device: mihomo
stack: mixed
auto-route: true
auto-redirect: true
auto-detect-interface: true
dns-hijack:
- any:53
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
nameserver:
- 223.5.5.5
- 119.29.29.29
proxies: []
proxy-groups:
- name: 出口選擇
type: select
proxies:
- DIRECT
rules:
- IP-CIDR,192.168.10.0/24,DIRECT,no-resolve
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- MATCH,出口選擇
先在前景執行 /usr/bin/mihomo -d /etc/mihomo -f /etc/mihomo/config.yaml,並透過另一個 SSH 工作階段觀察連接埠。若韌體已安裝 curl,可執行下方的請求;這個指令只會測試路由器本機至混合連接埠的連線,不會檢查區域網路的透明轉送。
curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com/
匯入實際節點後,確認「出口選擇」不再停留在 DIRECT,並參考記錄中的匹配規則、策略群組與節點名稱判斷請求路徑。只看網頁能否開啟,無法分辨是直連成功還是代理成功。
串接 TUN、策略路由與 OpenWrt 防火牆
明確指定代理測試通過後,將 tun.enable 改為 true,重新檢查設定並啟動。auto-route 會建立接管流量所需的路由;Linux 下的 auto-redirect 則會使用 nftables 等機制協助重新導向流量。自動產生的路由表編號、規則優先順序與鏈名稱可能隨版本改變,不要將網路上的某組固定編號當成通用標準。
ip link show mihomo
ip rule show
ip route show table all
nft list ruleset
sysctl net.ipv4.ip_forward
確認三項系統條件
- TUN 裝置已建立:應能看到設定中指定的
mihomo裝置。若未出現,請先檢查/dev/net/tun、模組與啟動權限。 - 路由接管已生效:比較啟動前後的
ip rule、路由表與 nftables 規則。核心記錄不應持續出現建立介面或新增規則失敗的訊息。 - 轉送未遭防火牆封鎖:必須啟用 IPv4 轉送,並允許 LAN 至 TUN 的轉送路徑。看到 TUN 介面,不代表 firewall4 已允許轉送。
在 LuCI 的「網路」→「防火牆」→「一般設定」檢查區域與轉送設定。若使用獨立的 TUN 區域,可依實際介面將 mihomo 裝置加入該區域,並允許 LAN 轉送至該區域;區域的輸入權限與轉送權限是兩回事。請勿為了測試而直接將 WAN 輸入政策改為接受。
不同韌體對非受管理裝置的區域綁定方式、自動重新導向與 firewall4 的整合方式各有差異,因此必須依據目前的規則集判斷,不宜直接複製固定的 iptables 指令碼。尤其不要同時新增 REDIRECT、TPROXY 與自動 TUN 三套接管規則;本文採用的是 TUN 方案。
單網路埠旁路由還要留意同介面轉送、回程路徑與連線追蹤。部分直連流量可能從 br-lan 進入後,又經由同一介面轉送給主路由。若出現只能單向連線或連線時斷時續,請先擷取封包確認來源位址與回程路徑,再判斷是否需要針對性來源位址轉換;不要一開始就對整個 LAN 開啟偽裝。
初次排查時,建議在「網路」→「防火牆」暫時停用軟體流量卸載與硬體流量卸載。等連線穩定後,再逐項恢復並重新測試。若旁路由可以上網、終端卻無法上網,請優先檢查轉送路徑,不要先更換節點。
設定 DNS 轉送,避免解析迴圈與 IPv6 繞過
範例中的 DNS 流程如下:終端連線至旁路由的 53 連接埠,由 dnsmasq 轉送至本機 mihomo 的 1053 連接埠,再送往上游 DNS 解析器。分開使用連接埠後,dnsmasq 與 mihomo 就不會爭用同一個監聽位址。
在 LuCI 的「網路」→「DHCP/DNS」→「一般設定」中,將 DNS 轉送目標設為 127.0.0.1#1053;再到對應的進階設定,檢查「不使用上游提供的 DNS 伺服器」選項。介面標籤可能因 LuCI 版本而異,重點是不要讓 dnsmasq 同時將請求轉送至其他自動取得的上游 DNS。
# 請先備份,以下操作會修改第一個 dnsmasq 執行個體
cp /etc/config/dhcp /etc/config/dhcp.before-mihomo
uci set dhcp.@dnsmasq[0].noresolv='1'
uci -q delete dhcp.@dnsmasq[0].server
uci add_list dhcp.@dnsmasq[0].server='127.0.0.1#1053'
uci commit dhcp
/etc/init.d/dnsmasq restart
nslookup example.com 127.0.0.1
這組指令會取代該執行個體現有的 DNS 轉送清單。若原本設定了企業內部網域的條件式轉送,請先記錄並保留相關項目;若有多個 dnsmasq 執行個體,也不能直接假設第一個就是 LAN 使用的執行個體。還要確認終端的 DNS 位址確實是 192.168.10.2。
分辨一般 DNS、fake-ip 與加密 DNS
- fake-ip:使用此模式時,查詢結果可能是
198.18.0.0/16範圍內的位址。這是虛擬對應位址,不是目標網站的實際公網位址;後續連線仍須由核心接管。 - 一般 DNS 劫持:
any:53用來接管相應的一般 DNS 請求,不代表能辨識並重新導向所有 DNS 協定。 - DoH 與 DoT:瀏覽器的安全 DNS、應用程式內建的 DoH,以及使用 TCP 853 的 DoT,不會因為設定了一般 53 連接埠劫持,就自動改由 dnsmasq 處理。測試前請先確認應用程式實際使用的 DNS 路徑。
- 上游 DNS 選擇:範例使用一般 IP 位址作為上游,是為了縮短啟動時的相依流程,並未啟用加密 DNS。若改用網域名稱形式的 DoH 位址,請另外規劃引導解析與節點網域名稱解析。
ipv6: false 只會限制核心對應的行為,不會停用終端收到的 IPv6 預設路由。初次驗證時可暫時關閉測試終端的 IPv6,之後再規劃 IPv6 TUN、路由公告與防火牆設定。不要因為 IPv4 出口正確,就認定雙堆疊流量都已接管。
透過 procd 管理啟動與重新啟動
確認前景執行、DNS 與終端連線都正常後,再註冊開機服務。以下 procd 指令碼只負責監控程序,不包含訂閱更新或自訂防火牆邏輯。請儲存為 /etc/init.d/mihomo,並確認沒有同名的其他外掛服務同時存在。
#!/bin/sh /etc/rc.common
START=99
STOP=10
USE_PROCD=1
start_service() {
/usr/bin/mihomo -t -d /etc/mihomo \
-f /etc/mihomo/config.yaml || return 1
procd_open_instance
procd_set_param command /usr/bin/mihomo \
-d /etc/mihomo -f /etc/mihomo/config.yaml
procd_set_param respawn 3600 5 5
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param file /etc/mihomo/config.yaml
procd_close_instance
}
chmod 755 /etc/init.d/mihomo
/etc/init.d/mihomo enable
/etc/init.d/mihomo start
logread -e mihomo
啟動服務前,先結束原本在前景執行的核心,避免兩個執行個體爭用連接埠與 TUN 裝置。此指令碼預設以 root 身分執行,因為建立 TUN、設定路由與防火牆需要相應權限;因此也必須嚴格控管設定檔、訂閱來源與核心檔案。
修改設定後,先執行 mihomo -t,再執行 /etc/init.d/mihomo restart。指令碼中的檔案宣告不代表具備自動更新訂閱的功能;更新訂閱仍須另外安排下載、設定檢查與原子替換。設定含有憑證時,也不要將完整啟動記錄公開。
開機順序較晚,不代表網路已可使用。務必完整重新啟動一次,確認介面上線後能否解析節點網域名稱、建立連線並恢復終端連線。依賴遠端規則集的部署,也要考慮冷開機時外部檔案可能暫時無法取得。
依連線路徑逐步驗收,並保留回復方式
驗收應從路由器本機開始,再逐步測試單一終端,最後才擴大至 DHCP 發放設定。每次只變更一個項目,並記錄相應的系統記錄與閘道設定。測速結果只能反映當下的傳輸狀況,不能取代路由與 DNS 路徑檢查。
| 現象 | 優先檢查項目 | 判斷依據 |
|---|---|---|
| 核心無法啟動 | 架構、設定、連接埠、TUN 模組 | 查看設定檢查結果與啟動錯誤,先不要修改終端閘道 |
| 明確指定代理正常,終端連線失敗 | 終端閘道、TUN 接管、LAN 轉送 | 確認終端請求是否出現在核心記錄中 |
| IP 位址可連線,網域名稱無法存取 | dnsmasq、1053 監聽狀態、上游 DNS 解析 | 分別測試旁路由與終端的 DNS 查詢 |
| 部分應用程式仍然直連 | 規則、IPv6、應用程式內建 DNS | 核對實際套用的策略與雙堆疊出口 |
| 重新載入防火牆後連線中斷 | 確認自動產生的規則是否仍存在 | 比較重新載入前後的 nftables 與策略路由 |
| 重新啟動後無法恢復 | 服務啟用狀態、介面啟動時序、冷開機相依項目 | 從系統記錄找出第一個失敗點 |
單一終端測試通過後,再擴大部署
- 先讓終端連線至主路由與旁路由的管理位址,確認區域網路直連正常。
- 確認終端的 IPv4 預設閘道與 DNS 都指向旁路由,清除舊的 DNS 快取,再建立新的瀏覽器連線。
- 分別測試應直連與應走代理的請求,查看對應規則與節點,不要只看網頁是否載入。
- 確認 UDP 應用程式、IPv6 策略及防火牆重新載入後的狀況,再調整主 DHCP 服務發放的閘道與 DNS。
正常停止後,檢查 TUN 介面、策略路由及自動產生的防火牆規則是否已清除。若仍有殘留,請依據先前保存的基準設定還原;不要透過遠端指令清空整個 nftables 規則集。若需要清除執行狀態,可先還原持久設定,再安排重新啟動。
OpenWrt 旁路由部署的重點不只是將執行檔放進路由器,而是要把終端閘道、DNS、流量接管、規則出口與服務生命週期串成一條可驗證的路徑。依序完成檢查,日後更換訂閱、調整分流或升級核心時,才能明確找出問題所在的層級。