OpenWrt サイドルーターで mihomo:透明ゲートウェイと DNS リダイレクトの実践手順

なぜ「サイドゲートウェイ」と mihomo なのか

インターネット出口を一本化しつつ、既存のメインルータ(ISP 付属機やメッシュの親機など)はそのまま残したい、という要件は家庭でも小規模オフィスでもよく出ます。そのとき現実的なのが、LAN に OpenWrt 機器をサイドルーター(旁路ゲートウェイ)として置き、クライアントの既定ゲートウェイDNS サーバーだけをそちらに向ける構成です。プロキシ設定を端末ごとに打ち込む負担が消え、ゲーム機やスマート家電のような「HTTP プロキシ欄がない」機器も同じルールで扱えます。

コアには mihomo(旧称 Clash Meta 系の実装)を置くのが自然です。ルール分流、プロバイダー、DNS まわりの表現力が高く、透過プロキシと fake-ip などの DNS モードを組み合わせたときの挙動もドキュメントやコミュニティ知見が蓄積されています。本稿は特定パネル名に依存しないよう、LuCI と UCI、シェル上の nft/iptables、および mihomo の設定 YAMLというレイヤーに分けて説明します。GUI プラグインを使う場合も、最終的に効いているのは同じ「ルーティング」「NAT/redirect」「DNS の委譲」です。

クライアント側の入口:Windows や macOS で手元だけを扱う場合は、GUI クライアントの導入が早いです。端末別の手順は ダウンロードページから各 OS 向けビルドを選べます。本記事はあくまでルータ/ゲートウェイに寄せる全屋向けの話です。

ネットワーク構成の前提

典型例として、メインルータの LAN が 192.168.1.0/24、サイド OpenWrt の WAN 口がそのセグメントに DHCP でぶら下がり、OpenWrt 自身の LAN ブリッジを 192.168.2.1/24 にする、という二段構成を想定します。クライアントを物理的に OpenWrt の LAN ポート配下に置かなくても、メインルータの DHCP で「デフォルトゲートウェイ=192.168.1.x(OpenWrt の WAN アドレス)」「DNS=同じく OpenWrt の WAN アドレス」のようにオプションを配れば、同じ Ethernet/Wi-Fi 上の端末からサイド機を経由させられます。メイン側に静的 DHCP やオプション編集が無い場合は、クライアント側でゲートウェイと DNS を手入力する運用になりますが、原理は同じです。

サイド構成では二重 NATになりがちです。オンラインゲームの開放ポートや P2P、IPv6 などでは別途配慮が必要ですが、一般的な HTTP/HTTPS と多くの QUIC トラフィックは、このままでも問題なく流れることが多いです。詰まったら「メインで UPnP」「IPv6 は一旦オフで切り分け」など、変数を減らしてください。

OpenWrt 側の土台:WAN とファイアウォール

まず OpenWrt がメイン LAN からアドレスを取得できていること、ping で外向きに出られることを確認します。サイド機の WAN ゾーンから LAN ゾーンへの転送が必要になるケースと、WAN 上のクライアントから OpenWrt 本体のプロキシ/DNS ポートに届く許可が必要になるケースを混同しないことが重要です。nftables のルールセットはディストリビューションや OpenWrt バージョンで表記が変わるため、LuCI のファイアウォール画面で「どのゾーンからどのポートを開けたか」をメモしながら進めると安全です。

SSH で uci show networkuci show firewall を眺め、WAN インタフェース名(waneth0.2 など)とゾーンの対応を把握しておくと、その後の 透明プロキシ用のチェーンを足すときに迷いません。

mihomo の配置と起動

実装手段は大きく三つに分かれます。(1)公式またはサードパーティの OpenWrt パッケージ、(2)リリースページから取得した 静的バイナリ/usr/bin/ などに置き、init.d または procd で常駐させる、(3)既存の GUI フロントエンド経由でコアだけ mihomo に差し替える、です。いずれも重要なのは、設定ディレクトリのパスログの見方アップデート手順を運用メモとして残すことです。ルータ内部はディスクも CPU も限られるため、巨大なルールセットや過剰な GeoIP 更新間隔は負荷とメモリ枯渇の原因になります。

初回は mixed-port にブラウザから接続し、外部コントローラや REST で「コアが生きているか」を確認してから透過化に進むと切り分けが楽です。mihomo の YAML では、プロキシ、プロキシグループ、ルール、dns セクションの依存関係が一本線になります。分流がおかしいときはプロキシより先に DNS の応答がどこで返っているかを疑うと早いです。ルール設計の考え方は チュートリアル・ドキュメントの説明と併せて読むと整理しやすいです。

透明プロキシ:redirect と TUN の選択

全屋からの TCP をサイド機上の mihomo に流す古典的手法は、PREROUTING での redirect です。例として、LAN ブリッジ br-lan 上のプライベート宛トラフィックのうち、既知のプロキシポート以外の TCP を mihomo の redir-port に送る、というイメージです。実際のポート番号やインタフェース名は環境に合わせて読み替えてください。

# Example nftables fragment — adjust iface, ports, and jump target for your build
table inet clash_transparent {
  chain prerouting {
    type nat hook prerouting priority -100;
    iifname "br-lan" tcp dport { 80, 443 } redirect to 7892
  }
}

上記はあくまで概念図に近い断片です。本番では「ルータ自身が発するトラフィック」「IPv6」「既にプロキシ内へ入ったパケットの再ループ」などを除外する条件が必要になります。OpenWrt では fw4 が生成するチェーンの前後にフックを足すスタイルや、iptables-translate で移行したルールを別ファイルに保持するスタイルなど、運用チームごとの作法があります。

よりモダンなのは TUN デバイスで一度カーネルに取り込み、mihomo 側でルーティングし直す方法です。ルール表現と整合しやすく、UDP や QUIC もまとめて扱いたい場合に有利ですが、カーネルモジュールや権限、MTU、オフロード(ハードウェア NAT)との相性といった論点が増えます。どちらを選んでも、「クライアントが見ている既定ゲートウェイがサイド機であること」が大前提です。ゲートウェイがメインルータのままだと、redirect ルールを書いても該当トラフィックがそもそもサイドを通りません。

DNS リダイレクトと fake-ip の整合

「接続はプロキシに乗っているのに、地域判定や CDN の出口だけおかしい」という相談の多くは、アプリケーションがキャッシュした DNS 結果か、端末がメインルータの DNS を直接叩いているケースです。サイド構成では、メイン DHCP が ISP の DNS を配っていると、クライアントがそれを優先してしまい分流と食い違います。

OpenWrt の dnsmasq を使う場合、よくあるパターンは次の二段です。第一に、LAN 向けの DNS クエリをループバック上で待つ mihomo(例:127.0.0.1#1053)へ転送する。第二に、mihomo の dns 設定で enhanced-mode や fake-ip を使うなら、国内直結ドメインは redir-host 相当で実 IP を返すなど、ルールとセットで設計する。fake-ip をオンにしたまま「実アドレスを前提にしたアプリだけ例外」といった運用は、ルール順と nameserver-policy の理解がないと破綻しやすいです。

# dnsmasq option style (illustrative) — exact UCI keys depend on OpenWrt version
# server=/#/127.0.0.1#1053
# rebind-protection may need tuning when chaining resolvers

IPv6 が有効な環境では、AAAA レコード経由で「意図せず v6 で迂回する」現象も起きます。切り分けの段階ではメイン/サイドのどちらかで一時的に v6 を抑え、挙動差を見る価値があります。

DHCP:デフォルトゲートウェイとオプション 3

OpenWrt が LAN 側の DHCP サーバになる構成なら、LuCI の DHCP and DNSルーターアドレス(オプション 3)DNS サーバー(オプション 6)を明示します。メインルータが DHCP の主役のままの場合は、メイン側の UI で「ゲートウェイ」「DNS」をカスタムにできるかどうかが鍵です。できない機種では、静的 DHCP で端末ごとに割り当てる、中継ブリッジではなくルーティングで寄せる、といった回避策が必要になります。

クライアント OS 側の「プライベート DNS」(Android の DoT など)がオンだと、意図せずルータの dnsmasq をすり抜けます。全屋で挙動を揃えたいなら、ドキュメントを読みながら端末グループごとにその設定をオフにするか、社内ポリシーに沿った別案を検討してください。

動作確認の順序

おすすめの確認順は次のとおりです。① サイド OpenWrt から ping 1.1.1.1 など L3 の疎通。② 同じく SSH 上で curl -I https://example.com の TLS 成立。③ mihomo のダッシュボードまたはログで、テストクライアントからのフローが期待グループに乗っているか。④ ブラウザで DNS リーク検査系のページを開き、応答がすべてサイド経由か。⑤ ストリーミングや銀行アプリなど、実 IP を要求するドメインをルールで外に出しているかの再確認。

どこかで止まったら、その層の設定だけを元に戻し、一つずつ戻すのが早道です。特に redirect と TUN を同時に有効にして二重処理になっていると、ログ上では「謎の RST」になりがちです。

典型トラブルと着眼点

一部アプリだけ直結する

ハードコードされた DNS、DoH、またはプロキシ非対応の binary protocol が典型です。分流ルールを増やす前に、そのアプリがどの名前解決経路を使っているかを tcpdump や mihomo のログレベル上げで確認します。

ルータ CPU が張り付く

巨大 GeoIP、短すぎる更新間隔、ログの verbose 化、あるいは redirect の再帰が原因のことがあります。ハードの性能に合わせて更新周期とルールの粒度を下げ、ログは必要時だけにします。

LAN 内通信までプロキシに吸われる

プライベート宛アドレスを redirect の対象外にする、ipset や nft のセットで社内サブネットを除外する、といったホワイトリスト設計が必要です。多段 VPN や社内 DNS を併用する環境では特に注意してください。

まとめ

OpenWrt をサイドゲートウェイに置き、mihomo で透過プロキシと DNS を束ねると、端末個別のプロキシ設定なしに全屋の出口ポリシーを近づけられます。成功の鍵は、メイン DHCP と端末 OS の DNS 設定を含めた名前解決の一本化と、redirect/TUN のどちらか一方に寄せた明確なパケット経路です。ルールや DNS の基礎は PC クライアントでも同じなので、まず手元で安定したプロファイルを作り、それをルータに移植する流れも現実的です。

同じ Clash 系エコシステムでも、デスクトップ GUI は導入が速く、ルータ常駐は一度構えれば家族端末まで含めて楽になります。用途に合わせてビルドを選び、各 OS の注意点を一覧できる ダウンロードページもあわせて活用してください。手元の環境でプロファイルを固めてからゲートウェイへ載せ替えると、夜中のトラブル回避につながります。→ Clash を無料でダウンロードし、快適な接続を試す