Dockerコンテナの通信をホスト上のClash/Mihomoへまとめて通したい場合、コンテナごとにHTTPプロキシ環境変数を設定する方法だけでは対応しきれないことがあります。透過プロキシなら、アプリケーションの設定を変えずにDocker bridgeから出る通信をLinuxホストで捕捉し、宛先に応じてプロキシまたは直接接続へ振り分けられます。ただし、単にファイアウォールで転送するだけでは動きません。TPROXY、ポリシールーティング、転送許可、除外ルールを一組として設計する必要があります。この記事ではMihomoをLinuxゲートウェイとして動かす例を使い、設定の組み立て方と、接続失敗やループの切り分け方を説明します。

通信経路と事前確認

標準的なDocker bridgeネットワークでは、コンテナのパケットは仮想インターフェースを通ってホストへ入り、ホストのルーティングとファイアウォール処理を経て外部へ出ます。透過プロキシでは、このホストに入ったパケットをMihomoのTPROXYポートへ渡し、Mihomoが元の宛先を保ったままルール判定を行います。コンテナ内のアプリは通常の接続を行うだけなので、個別にプロキシ設定を入れる必要はありません。

作業前に、コンテナのサブネット、bridgeインターフェース、ホストの外向きインターフェース、Mihomoの待受ポートを確認します。以下では例としてDockerサブネットを172.20.0.0/16、bridgeをbr-abc123、TPROXYポートを7893、パケットマークを0x1とします。実環境では必ず読み替えてください。Dockerネットワークを再作成するとbridge名やサブネットが変わる場合があるため、固定したい場合はDocker側でネットワークを明示的に作成します。

  • MihomoがLinuxホスト上で稼働し、TPROXY対応のビルドであること。
  • ホストのファイアウォールがDockerの転送を妨げていないこと。
  • 必要なカーネル機能とツールが利用できること。環境によってはxt_TPROXY、xt_socket、iproute2が必要です。
  • DockerサブネットとLAN、VPN、他のコンテナネットワークのアドレス範囲が重複していないこと。
透過プロキシはホストのルーティングとファイアウォールを変更します。SSH接続中のリモートホストで作業する場合は、復旧用のコンソールを確保し、ルールを戻す手順を先に用意してください。最初は検証用コンテナと限定したサブネットだけを対象にします。

MihomoでTPROXYを有効にする

Mihomo側ではtproxy-portを有効にします。TPROXYは元の宛先情報を維持できるため、通常のHTTPプロキシ設定では扱いにくいTCP・UDP通信の捕捉にも利用できます。まずはTCPから動作確認し、UDPを追加する場合はDNSやアプリケーションの挙動を個別に確かめると切り分けやすくなります。

Mihomo の基本設定例
mixed-port: 7890
tproxy-port: 7893
allow-lan: true
mode: rule
log-level: info

# 外部コントローラーを使う場合は、管理ネットワークに限定する
external-controller: 127.0.0.1:9090

# ルール、proxy-groups、proxies は利用中の設定に合わせて追加

allow-lanはMihomoの他の待受ポートをLANへ公開する設定にも関係するため、必要な範囲だけをファイアウォールで許可してください。特に外部コントローラーを0.0.0.0へ公開するのは避け、管理が必要ならアクセス元を限定し、強力なシークレットを設定します。既存の設定にtproxy-portを追加した後は、設定の検証とログを確認してからファイアウォール側のルールを導入します。

ポリシールーティングとファイアウォール

TPROXYは、対象パケットを指定ポートへ送るだけでなく、パケットにマークを付けてローカル配送させる必要があります。次の例はIPv4のiptablesを使用する概念例です。Docker bridgeから入った通信だけを対象にし、ローカルネットワークやコンテナ同士の通信を先に除外します。アドレス範囲はネットワーク構成に合わせて追加・変更してください。

IPv4 TPROXY のルール例
# マーク付きパケットをローカルへ配送するルーティングテーブル
ip rule add fwmark 0x1/0x1 table 100
ip route add local 0.0.0.0/0 dev lo table 100

# 専用チェーンを作成し、Docker bridgeからの通信を処理
iptables -t mangle -N CLASH_TPROXY
iptables -t mangle -A PREROUTING -i br-abc123 -s 172.20.0.0/16 -j CLASH_TPROXY

# ループバック、プライベートネットワーク、Docker内通信などを除外
iptables -t mangle -A CLASH_TPROXY -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A CLASH_TPROXY -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A CLASH_TPROXY -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A CLASH_TPROXY -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A CLASH_TPROXY -d 224.0.0.0/4 -j RETURN

# 例ではTCPを捕捉。UDPは動作確認後に同様のルールを追加
iptables -t mangle -A CLASH_TPROXY -p tcp \
  -j TPROXY --on-port 7893 --tproxy-mark 0x1/0x1

# 転送を許可する。既存のDocker・ホストファイアウォール方針に合わせる
iptables -I DOCKER-USER -i br-abc123 -s 172.20.0.0/16 -j ACCEPT

上記は構成を理解するための例であり、そのまま全環境へ適用する完成スクリプトではありません。DOCKER-USERは主に転送フィルター側の制御に使われ、TPROXYの捕捉ルールを置く場所とは役割が異なります。また、既存チェーンやディストリビューションのファイアウォール管理方式によって挿入位置が変わります。Dockerがiptables互換バックエンドを使っているか、nftablesを直接管理しているかも確認し、同じ通信に複数の管理ツールが異なるルールを適用しないようにしてください。

最初の段階では、TCPだけを捕捉し、コンテナからテスト用の宛先へ接続してMihomoの接続ログに表示されるかを確認します。成功したら必要なUDPを加えます。DNSのUDP/53を一般のUDPルールに含めると、コンテナのDNS設定とMihomoのDNS設定が競合する場合があります。DNSは後述のとおり、転送先と名前解決経路を決めてから別途扱うのが安全です。

サブネット除外とDNS設計

除外ルールは、意図しない経路変更やループを防ぐ要です。コンテナからホストのLAN機器へアクセスする通信、コンテナ間通信、プライベートアドレスへの通信まで一律にプロキシへ渡すと、サービス探索や管理画面が使えなくなることがあります。一方で、社内ネットワークの一部をプロキシしたいなど、プライベート範囲すべてを除外できない環境もあります。必要な宛先だけを許可・除外するルールに調整し、最終的にはMihomoのルール判定も確認してください。

  • Dockerネットワーク:同じbridge内のコンテナ通信は通常プロキシ対象から外します。
  • ホスト・LAN:ホストの管理用IP、ルーター、ローカルDNSなど、直接アクセスが必要な宛先を除外します。
  • 特殊アドレス:ループバック、リンクローカル、マルチキャスト、ブロードキャストを不用意に捕捉しません。
  • プロキシサーバー:ホスト自身から外部プロキシへ接続する通信を同じ捕捉ルールへ戻さないようにします。

DNSについては、コンテナがどのリゾルバーへ問い合わせ、その問い合わせがどの経路を通るかを先に整理します。Dockerの既定DNSはホスト上の転送機能を経由することがあり、コンテナの/etc/resolv.confに見えるアドレスと実際の上流DNSが異なる場合があります。MihomoのDNSを利用するなら、コンテナから到達可能なDNS待受アドレスを設ける方法、またはホスト側でDNSを明示的に転送する方法を選びます。公開ネットワークへ無制限にDNS待受を公開しないでください。

fake-ipを使う場合も、コンテナがMihomoのDNSへ問い合わせて初めて、その応答と後続の通信が一貫します。DNSだけを別経路へ送ると、名前解決は成功しても接続が失敗したり、ドメインベースのルールが期待どおりに適用されなかったりします。まずホスト上のDNS待受へコンテナから到達できることを確認し、次に名前解決結果、最後に接続ルールをログで追う順番が有効です。

段階的なテストとトラブルシューティング

一度に複数のルールを追加せず、通信経路を段階ごとに確認します。Docker側ではコンテナのIPとネットワークを確認し、ホスト側ではパケットカウンター、ルーティングルール、Mihomoの接続履歴を照合します。例えば、パケットカウンターが増えない場合はbridge名や送信元サブネット、チェーンへの接続を見直します。カウンターは増えるのにMihomoへ接続が現れない場合は、TPROXY対応状況、待受ポート、マークとポリシールートを調べます。

  1. コンテナからIPアドレス宛てにTCP接続し、DNS依存の問題を避けて捕捉を確認します。
  2. Mihomoの接続履歴で宛先、適用ルール、選択されたプロキシグループを確認します。
  3. ドメイン名で接続し、コンテナのDNS設定とMihomoのDNSログを照合します。
  4. 必要な場合だけUDPを追加し、アプリケーションごとに到達性を試します。
  5. 最後に再起動後もルールが正しい順序で復元されるよう、使用中のネットワーク管理方式に合わせて永続化します。

代表的な症状には、いくつかの原因候補があります。

  • 接続がタイムアウトする:ホストのIP転送、ファイアウォールの転送許可、TPROXYルート、戻り経路を確認します。
  • DNSだけ失敗する:コンテナのリゾルバー設定、ホストのDNS転送、UDP/53の除外・転送方針を確認します。
  • 同じ通信が繰り返される:ホスト発のプロキシサーバー接続が捕捉されていないか、入力インターフェースと対象サブネットが広すぎないかを確認します。
  • LAN宛てまでプロキシされる:除外ルールの順序、宛先範囲、使用しているDockerネットワークを見直します。
  • 再起動後に動かない:Docker起動前後のルール投入順、動的bridge名、重複した永続化設定を確認します。
切り分け時は、ホスト自身の通信とコンテナ発の通信を混同しないことが重要です。捕捉ルールをDocker bridgeから入るパケットに限定すると、Mihomo自身が外部プロキシへ接続する通信を再び捕捉するループを避けやすくなります。

よくある質問

コンテナごとにHTTP_PROXYを設定する必要がありますか?

TPROXYでDocker bridge上の通信を捕捉する構成なら、通常はアプリごとのHTTPプロキシ設定は不要です。ただし、透過プロキシを使わずにMihomoのHTTP/mixedポートへ明示的に接続する方式では、アプリごとの設定が必要です。両方式を混在させる場合は二重プロキシや例外通信に注意してください。

UDP通信も同じ設定で処理できますか?

MihomoのTPROXYポートとホストのファイアウォールがUDPを扱える環境なら、UDPの捕捉も構成できます。ただし、DNS、QUIC、ゲーム、音声通話では必要なポートや挙動が異なります。TCPで経路を検証してからUDPを追加し、使うアプリの接続ログと通信状況を確認してください。

nftables環境でも使えますか?

可能ですが、iptablesの例をそのままnftablesのルールとして実行することはできません。使用中のバックエンドとDockerのファイアウォール管理方法を確認し、TPROXY、マーク付け、ポリシールーティングに相当する処理を一貫して設定します。iptables-nft互換レイヤーを使う場合も、ルールがどの管理ツールから投入されているかを把握してください。

Dockerの透過プロキシは、対象をbridge通信に絞り、DNSと除外サブネットを明確にすれば安定して運用できます。まずTCP一種類の通信から小さく検証し、MihomoのログとLinux側のルーティング状態を突き合わせてから、UDPや対象ネットワークを広げましょう。Clash/Mihomoをこれから導入する場合は、利用環境に合ったクライアントと基本設定を確認してから段階的に組み立てると、問題の切り分けが容易になります。

はじめる

Clash でトラフィックを完全制御

Windows・macOS・Linux・Android・iOS 対応。柔軟なルール、すぐに使えます。

無料ダウンロード セットアップガイドを見る →