システムプロキシと TUN だけでは足りない理由

GUI ブラウザは OS のプロキシ設定を追従しやすい一方、多くの CLI は 環境変数か独自設定を読みます。Docker はさらに層が分かれ、デーモンがレジストリへ行く通信と、コンテナ内の RUN が行う通信で経路が異なります。ここを混同すると「ホストのシェルでは通るのに docker build だけ詰まる」といった症状が残ります。

TUN モードは仮想インターフェース側からトラフィックをコアへ寄せる強力な手段ですが、ルート競合や権限、他 VPN との兼ね合いで採用できない/したくないケースもあります。Linux での長期運用は Ubuntu+systemd の整理 が参考になりますが、本稿は 影響範囲を環境変数と Docker 設定に閉じる方針に絞ります。クライアント選びの比較軸は クライアントの選び方 を参照してください。

要点:mixed-port は「同一待受で HTTP と SOCKS を扱う」イメージに近いです。実際のキー名や既定値はコア版と GUI によりますが、本稿では ローカル待受のポート番号を一つ決め、そこへ CLI と Docker を向ける手順を優先します。

mixed-port の確認と YAML の考え方

まず Clash/Mihomo が起動し、GUI または設定ファイルで mixed-port(例として 7890)が有効か確認します。ポートは環境ごとに異なるため、以降の例の 7890 はすべて実際の値へ置き換えてください。待受が 127.0.0.1 に限定されているか、LAN 全体に開いていないかも合わせて見ます。

YAML reference (adjust to your core version)
mixed-port: 7890
bind-address: '127.0.0.1'

ルール側で意図したポリシーへ流れることは、ルール分流のベストプラクティス のとおり rules: の順序と DNS の整合が前提です。端末からの HTTP(S) はプロキシ経由でも、名前解決が先にズレると挙動だけが不自然になる点に注意してください。

ターミナル:HTTP_PROXY と ALL_PROXY

代表的な変数は HTTP_PROXYHTTPS_PROXY、そして多くのツールが参照する ALL_PROXY です。小文字の http_proxy 系を併記しておくと、実装差による取りこぼしを減らせます。

Shell export example (zsh / bash)
export HTTP_PROXY="http://127.0.0.1:7890"
export HTTPS_PROXY="http://127.0.0.1:7890"
export ALL_PROXY="socks5h://127.0.0.1:7890"
export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"

socks5h:// は名前解決をプロキシ側へ委ねる指定です。社内 DNS や split DNS と衝突する場合は http://127.0.0.1:7890 に寄せ、NO_PROXY で除外を厚くする方が安定することがあります。検証中は新しいシェルセッションだけに export し、別ターミナルは無設定のまま A/B するのが早いです。

NO_PROXY でローカルと社内を除外

NO_PROXY(および no_proxy)はカンマ区切りでホストやサフィックスを列挙します。localhost127.0.0.1::1 に加え、.local や社内ドメインのサフィックスを入れるのが一般的です。

NO_PROXY example
export NO_PROXY="localhost,127.0.0.1,::1,.local,.corp.example,192.168.0.0/16"
export no_proxy="$NO_PROXY"

Docker ブリッジのサブネットを入れるかは環境差が大きいです。コンテナからホストのプロキシへ向ける経路を組む段階で、意図せずプロキシを迂回/直結させたい帯域を足し引きしてください。ワイルドカードの解釈はツール依存のため、確実性を取るなら列挙を厚くします。

git と curl の切り分け

git の HTTPS リモートは HTTP_PROXY 系を参照しやすいですが、SSH リモート[email protected]:...)は別経路です。プロキシ越しに統一したいなら HTTPS リモートへ寄せるか、SSH の ProxyCommand を別途用意します。サブモジュールや認証ヘルパーがあると隠れた HTTP 要求が増えるため、NO_PROXY は早めに設計しておく価値があります。

curl で検証する場合は -v を付け、接続先とプロキシの選択をログで確認します。TLS エラーが続くときは中間証明書や SNI、あるいはプロキシループ(上流が自分自身を指す)を疑ってください。DNS や timeout の層別の考え方は よくある質問 の接続まわりとも整合させると読みやすくなります。

Docker デーモン(pull)と build/RUN の違い

デーモン側の pull/push

イメージの取得は Docker デーモンが行うため、ホストのシェルに export しただけでは効かないことがあります。Docker Desktop(macOS)では GUI のプロキシ設定や daemon.jsonproxies、Linux では docker.serviceEnvironment= など、プラットフォームごとの定石に従います。

daemon.json proxies (conceptual)
{
  "proxies": {
    "default": {
      "httpProxy": "http://127.0.0.1:7890",
      "httpsProxy": "http://127.0.0.1:7890",
      "noProxy": "localhost,127.0.0.1,::1"
    }
  }
}

docker build の RUN

ビルド中の aptpip はコンテナ内で動くため、docker build--build-argHTTP_PROXY 等を渡し、Dockerfile で ENV に流すパターンが一般的です。マルチステージビルドではステージごとに再宣言が必要になる点に注意してください。

Dockerfile pattern
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG ALL_PROXY
ARG NO_PROXY
ENV HTTP_PROXY=$HTTP_PROXY HTTPS_PROXY=$HTTPS_PROXY \
    ALL_PROXY=$ALL_PROXY NO_PROXY=$NO_PROXY

host.docker.internal と Linux の注意点

コンテナからホスト上の Clash へ向けるとき、コンテナ内の 127.0.0.1 はコンテナ自身です。macOS の Docker Desktop では host.docker.internal が用意されていることが多く、プロキシ URL は http://host.docker.internal:7890 のように書きます。

Linux では Docker 20.10+ の --add-host=host.docker.internal:host-gateway など、バージョンとランタイムに合わせた指定が必要な場合があります。チームで固定 IP を配る運用もありますが、再現性とドキュメント化を優先し、手元の compose や CI で同じ値に揃えてください。

SOCKS5 と HTTP:どちらを選ぶか

mixed-port は HTTP と SOCKS の両方を扱えるのが利点です。Go 製など現代的な CLI は http:// スキームと ALL_PROXY の組み合わせに強い一方、古いスタックは SOCKS を解釈しないことがあります。その場合は HTTP 側へ寄せるか、別途プロキシラッパーを検討します。

待受が生きているかは curl -x http://127.0.0.1:7890 https://example.com -I のように短い要求で確認し、Clash の接続ログと突き合わせます。ノードやルールの話に戻る場合は ルール分流 の順序意識がそのまま効きます。

セキュリティ・ループ・観測の要点

bind-address を LAN 全域に広げると、同一ネットワークからの悪用リスクが上がります。開発用途でも 127.0.0.1 に限定し、必要なら OS ファイアウォールで絞るのが無難です。認証付きプロキシでは、資格情報を平文の環境変数に載せない運用を推奨します。

チェックリスト:(1)mixed-port が LISTEN か。(2)そのシェルで export が有効か。(3)NO_PROXY に該当ホストがあるか。(4)Docker ならデーモンとビルドのどちらが詰まっているか。(5)プロキシループや DNS の取りこぼしがないか。

TUN の仕組み自体は TUN モードの詳解 が基礎になります。明示プロキシで片付かない層が残るときは、要件に合わせて TUN 側へ戻る判断もあります。

TUN/systemd 運用との役割分担

TUN は「アプリがプロキシを知らなくても経路に乗せる」強みがありますが、権限とルート競合の話が伴います。一方、本稿の 環境変数+ Docker 設定は影響範囲を明示的に限定しやすく、社内レポジトリやローカルレジストリとの共存を設計しやすいです。どちらが正解というより、チームのポリシーと再現性で選ぶとよいでしょう。

上流の Mihomo/Clash Meta は OSS として追跡しやすい一方、一般ユーザー向けのクライアント入手はサイトの ダウンロードページ を主にし、GitHub はソースや変更履歴の確認に回すと混乱が減ります。

まとめ

Clash mixed-port を軸に、ターミナルでは HTTP_PROXYHTTPS_PROXYALL_PROXY と小文字版を揃え、NO_PROXY でローカルと社内を除外する——このセットが「システムプロキシだけでは残る穴」を塞ぎやすいです。Docker はデーモンの pull と docker build 内の通信を分けて考え、ホスト到達には host.docker.internalhost-gateway などプラットフォームの定石を当てはめます。SOCKS5HTTP プロキシはツール特性に合わせて使い分け、詰まったらループと DNS を先に疑うと早いです。

同じ Mihomo 系でも GUI の見え方はクライアントで異なります。ログとルール編集が同じ文脈に乗るクライアントを選ぶと、今回のような切り分けがさらに速くなります。

Clash を無料ダウンロードし、mixed-port と環境変数を同じ画面文脈で扱えるクライアントから、端末とコンテナの経路整理を始めましょう。