開発中だけ通信が失敗する理由

開発環境で起きる通信障害は、ブラウザが普通に表示できるため発見が遅れがちです。Git clone は途中で止まるのに Web ページは開く、npm install はメタデータを取得できてもパッケージ本体のダウンロードで ETIMEDOUT になる、docker pull はログインできるのにイメージのレイヤー取得だけが失敗する——このような症状は、アプリケーションのバグではなく、各ツールが異なるホストや接続方式を使っていることから起こります。

特に開発ツールは、ブラウザのように OS のシステムプロキシ設定を必ずしも継承しません。Git は独自の HTTP/HTTPS プロキシ設定、npm は環境変数や npm 固有の設定、Docker CLI は Docker Engine またはデーモン側の設定を参照します。そのため、ブラウザだけプロキシ経由で動いていても、ターミナルやバックグラウンドサービスは直接接続を試みている場合があります。

この差をアプリごとに埋めようとすると、設定ファイル、環境変数、Docker Desktop の項目を別々に管理することになり、ノート PC と CI 用マシンの状態もすぐに食い違います。そこで有効なのが、Clash の TUN モードです。仮想ネットワークインターフェースを通して端末の通信を Clash に集約すれば、明示的なプロキシ対応が弱い CLI や補助プロセスも、同じ分流ルールと接続ログで確認できます。

TUN の役割:TUN は通信を自動的に高速化する機能ではありません。アプリごとに異なるプロキシ設定を減らし、DNS、ルーティング、ルール選択を端末側で一元管理するための仕組みです。利用するネットワークの規約と、開発データの取り扱い方針を確認したうえで設定してください。

Git・npm・Docker が接続する先を把握する

最初から大きなルールセットを追加するより、どの段階でどのホストへ接続しているかを確認する方が安全です。同じ「GitHub を使う」処理でも、Git のリポジトリ取得、Release のバイナリ、npm パッケージの tarball、Docker Hub の認証とレイヤー CDN では接続先が異なります。Clash の接続画面を開いた状態で、同じ操作を一度だけ再現し、ホスト名、ポート、選択されたプロキシグループ、接続が終了した時刻を記録します。

  • Git:github.comapi.github.com、GitHub の raw コンテンツ配信先、企業内 Git サーバーなど。SSH を使う場合は通常 22 番ポート、HTTPS の場合は 443 番ポートです。
  • npm:registry.npmjs.org からメタデータを取得した後、パッケージの tarball が別 CDN やスコープ専用レジストリから配信されることがあります。
  • Docker:registry-1.docker.ioauth.docker.io、イメージのマニフェストやレイヤーを配信する CDN など、複数のホストを順番に利用します。
  • 補助サービス:GitHub Actions、コンテナ署名、パッケージ監査、社内 SSO などが追加の認証先を呼び出す場合があります。

Clash のログに対象ホストがまったく出ない場合は、ルールの問題と決めつけないでください。TUN が有効になっていない、Docker Engine が別の仮想環境で動いている、VPN やセキュリティソフトが先に通信を捕捉している、あるいは DNS 解決だけが Clash の外側で行われている可能性があります。逆にログへ接続が現れているなら、次はルールとプロキシグループの選択を調べます。

TUN を有効にする前の準備

利用する GUI は、Clash Verge Rev、Mihomo Party、Clash Nyanpasu など、Mihomo コアを扱える現行クライアントを選ぶと設定の再現性を保ちやすくなります。画面上の名称は版によって「TUN」「サービスモード」「システムトンネル」など少し異なりますが、確認すべき本質は共通しています。管理者権限またはシステム拡張の許可が済み、Mihomo コアが起動し、プロファイルが正常に読み込まれていることです。

  1. バックアップを作成:現在の YAML、プロキシグループ、DNS 設定を保存します。TUN の検証中に DNS やルート設定を変更するため、元へ戻せる状態にしておきます。
  2. クライアントを更新:配布元とリリース情報を確認し、OS に合うビルドをインストールします。古いコアでは auto-route や DNS の挙動が現在の GUI と一致しないことがあります。
  3. 権限を許可:Windows ではサービスや管理者権限、macOS ではネットワーク拡張や VPN 構成の許可を確認します。許可を拒否したまま TUN をオンにしても、仮想インターフェースは正常に作成されません。
  4. 安全なテスト対象を決める:最初は公開リポジトリの軽い git ls-remote、小さな npm パッケージの取得、公開イメージのメタデータ確認など、失敗しても作業データを壊さない操作を使います。

プロファイルを編集できる場合は、次のような基本構成を出発点にします。実際のキー名や利用可能な値はクライアントと Mihomo のバージョンによって異なるため、読み込みエラーが出た場合はその版の公式仕様を優先してください。

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

dns:
  enable: true
  enhanced-mode: fake-ip
  respect-rules: true

strict-route は、すべての経路を厳格に TUN へ寄せたい環境では有効ですが、社内 LAN、仮想マシン、Docker のブリッジネットワークと衝突することがあります。最初の検証では無理に厳格化せず、LAN アドレスや Docker ネットワークが正常に動くことを確認してから段階的に変更する方が切り戻しやすいでしょう。

実際に開発ツールを TUN 経由で確認する

TUN をオンにしただけで「開発ツールが直った」と判断せず、Git、npm、Docker を分けて検証します。各コマンドの前後で Clash の接続一覧を確認し、想定したホストが同じプロキシグループへ送られているかを見ます。ルールを変更するたびに複数の操作をまとめて実行すると、どの変更が効いたのか分からなくなるため、一つずつ再現してください。

  1. Git の経路を確認:git ls-remote https://github.com/example/project.git を実行し、認証情報を変更せずに接続だけを確認します。GitHub が Clash の接続一覧に現れ、ブラウザと同じ安定したグループへ入れば第一段階は完了です。
  2. npm の取得を確認:テスト用ディレクトリで npm view lodash version を実行した後、必要なら npm pack lodash を試します。レジストリだけでなく tarball の接続先も記録してください。
  3. Docker の認証を確認:docker login を行い、続けて小さな公開イメージを docker pull alpine:latest で取得します。認証は成功するのにレイヤーだけ失敗する場合、Docker Hub の CDN 側を見落としている可能性があります。
  4. 通常の開発操作を再現:実際のリポジトリで git fetch、依存関係のインストール、イメージの pull を順番に行い、タイムアウト、再試行、途中のノード切り替えがないかをログで確認します。

Git の HTTPS 接続が安定しても SSH 接続は別経路です。SSH を使うプロジェクトでは、TUN が TCP 接続を捕捉できているか、ポート 22 がネットワーク側で制限されていないかを切り分けます。必要に応じて GitHub の SSH over HTTPS など、組織の方針に合った方式へ変更します。秘密鍵を無理にプロキシ設定へ書き込む必要はありません。

npm では、次のような設定が残っていると TUN と二重プロキシになることがあります。

npm config get proxy
npm config get https-proxy
npm config get registry

不要な古い値が表示された場合は、現在の運用方針に合わせて整理します。TUN に端末の経路を任せるなら、npm のプロキシ設定を重ねない方が原因を追いやすい場合があります。ただし社内レジストリなど明示的なプロキシを必須とする環境では、管理者の指定を優先してください。

分流ルールと DNS を開発向けに整える

開発用の分流では、広いルールを先に置きすぎないことが重要です。たとえば全トラフィックを一つの遠いグループへ送ると、社内 Git、ローカルの Docker レジストリ、プライベート npm レジストリまで外部経路へ流れてしまいます。まずローカルと社内ドメインを DIRECT または組織指定の経路へ置き、その後に GitHub、npm、Docker のような外部サービスを個別に整理します。

  • ローカルを先に分ける:127.0.0.1localhost、RFC1918 の LAN、Docker のブリッジネットワークを不用意に外部プロキシへ送らないようにします。
  • ホスト名ベースを優先:変動する CDN の IP アドレスを直接登録するより、確認できたドメインやドメインサフィックスをルール化します。
  • サービス別グループを作る:Git、npm、Docker を同じ自動選択グループに入れるのではなく、長時間接続や大きなレイヤー転送に向く経路を個別に選べるようにします。
  • 最後の MATCH を確認:どのルールにも一致しない接続が意図せず DIRECT へ落ちると、TUN が動いていても症状は変わりません。

DNS は、ルール判定と経路選択の土台です。DNS が OS や別 VPN によって先に解決されると、偽 IP を利用する構成と矛盾したり、地域判定の異なるアドレスが返ったりします。Clash の DNS ログで名前解決が行われていること、Fake-IP の除外リストに社内ドメインや Docker 関連の名前が適切に含まれていることを確認してください。名前解決が不安定な場合は、TUN のルートを変更する前に DNS のみを一時的に見直すと原因を絞れます。

Docker Desktop と CI で起きる落とし穴

Docker は、ターミナルから実行する CLI と、バックグラウンドで動く Docker Engine が別プロセスである点に注意が必要です。端末の docker コマンドが TUN を通っていても、デーモンが別 VM や WSL2 内で動作していれば、実際のイメージ取得はその環境のネットワークから行われます。Clash の接続一覧に Docker の pull が出ない場合は、まず Engine の実行場所を確認してください。

Docker Desktop を利用する場合は、アプリのプロキシ設定、WSL2 のネットワーク、ホスト OS の TUN が互いに干渉していないかを確認します。すべてにプロキシを設定すると、ホスト側で一度変換された通信が VM 側でも再変換され、認証や TLS が不安定になることがあります。基本方針は、TUN を中心にするのか、Docker Engine 専用の HTTP プロキシを使うのかを決め、二重化を避けることです。

CI ではさらに、ローカル端末で成功した設定がそのまま再現されるとは限りません。GitHub Actions、社内 Runner、Docker コンテナ内のビルドでは、環境変数、DNS、証明書ストア、プロキシの許可範囲が異なります。外部サービスへ接続するビルド処理は、秘密情報をログへ出さないこと、固定した社内ミラーを使える場合はそちらを優先すること、失敗時に再試行だけを増やさないことを基本にします。

セキュリティ上の注意:Docker のプロキシ環境変数や npm の設定に、購読 URL や認証トークンを直接含めないでください。設定ファイル、CI ログ、プロセス一覧に秘密情報が残る可能性があります。必要な認証情報は各サービスの Secret 管理機能で扱い、共有プロファイルへ平文で保存しないようにします。

失敗したときの切り分け手順

TUN 有効後に通信が全面的に止まった場合は、ルールを大量に追加する前に構成を小さく戻します。TUN を一度オフにして通常のネットワークが復旧するか、Clash 自体がプロキシノードへ接続できているか、DNS が応答しているかを順番に確認します。TUN の問題に見えても、実際には期限切れの購読、壊れたプロキシグループ、システム VPN の競合が原因であることがあります。

症状 確認する場所 最初の対応
Git だけ直行する Clash 接続一覧、Git の SSH/HTTPS 方式 HTTPS と SSH を分けてログを取り、TUN の捕捉範囲を確認する
npm のメタデータだけ成功する tarball の実ホスト、npm レジストリ設定 インストール中の CDN 接続を記録し、同じルールへ追加する
Docker login は成功する 認証ホスト、レイヤー CDN、Docker Engine の実行場所 pull 中に現れる全ホストとデーモンの経路を確認する
TUN 後に LAN が使えない ルート表、Fake-IP 除外、strict-route LAN と Docker ネットワークを除外し、厳格なルートを一時的に緩める

エラーコードも手掛かりになります。ECONNRESET は接続途中の切断、ENOTFOUND は DNS 解決、407 Proxy Authentication Required はプロキシ認証、証明書エラーは TLS の終端や時刻、CA ストアの問題を示すことがあります。ただしコードだけで出口ノードの問題と断定せず、同じ時刻の Clash ログと照合してください。プロキシグループが接続中に自動切り替えされているなら、テスト中だけ固定ノードにして挙動を比べると、ネットワーク品質とルール設定を分離できます。

設定が安定した後は、開発者ごとに異なる YAML を配るのではなく、共通ルール、ローカル環境の差分、社内ドメイン、秘密情報を分離して管理します。プロファイル更新時には Git、npm、Docker の三つの代表操作を簡単なチェックリストとして再実行し、クライアント更新後に TUN の権限や DNS モードが変わっていないかも確認します。こうしておけば、問題が起きたときに「ノードが遅い」の一言で終わらず、どの層が変わったのかを追跡できます。

アプリごとにプロキシ設定を足していく方法は、短期的には手軽でも、Git の SSH、npm の CDN、Docker Engine のような例外が増えるほど保守が難しくなります。特に古い GUI や非公式ビルドでは TUN の権限表示が分かりにくく、設定名も統一されていません。Clash 公式サイト は、Mihomo 系クライアントの選び方、TUN の確認ポイント、開発ツール別の分流とログの読み方を同じ流れで整理できる点が実用的です。複雑な設定を一度に増やさず、この記事の手順を試せる環境を用意したいなら、まずダウンロードへ進むのが近道です。