通信の入口と転送モードを分けて考える

システムプロキシとTUNモードは「通信をどのようにクライアントへ取り込むか」を決める設定です。一方、ルール・グローバル・DIRECTは「取り込んだ通信をどう転送するか」を決めます。この2つは別の層にあります。TUNを有効にしても、すべての通信がリモートノード経由になるわけではありません。また、グローバルモードを選んでも、すべてのアプリの通信が自動的にクライアントへ入るわけではありません。

接続の流れは、次の順に考えるとわかりやすくなります。プロキシグループの選択や、サブスクリプション内のノードが利用可能かどうかは、通信が取り込まれた後に決まります。そもそも通信がコアに届いていない場合、ノードを何度切り替えても結果は変わらないことがあります。

アプリが接続を開始
  → システムプロキシのポート、またはTUN仮想インターフェース
  → Clash / mihomoコア
  → 転送モードとルールによる判定
  → DIRECT、プロキシノード、またはREJECT

システムプロキシ:アプリがローカルポートへ接続

システムプロキシは、アプリが参照するネットワーク設定です。たとえばクライアントがローカルで混合ポート 127.0.0.1:7890 を待ち受け、そのアドレスをシステムプロキシに設定します。この設定に対応したアプリはローカルポートへ接続し、コアがその先の宛先へ通信します。7890 はあくまで例です。実際のポート番号はクライアントの設定を確認してください。

HTTP・HTTPS・SOCKSの接続方式の違い

  • HTTPプロキシ:アプリがHTTPリクエストをプロキシサーバーに渡して処理します。
  • HTTPSをHTTPプロキシ経由で接続:通常はまずCONNECTリクエストでトンネルを確立し、その中でTLSハンドシェイクを行います。クライアントがHTTPSの内容を復号するという意味ではありません。
  • SOCKS5:アプリがSOCKSで宛先アドレスを指定します。ドメイン名の名前解決をプロキシ側に任せるかどうかは、アプリと接続方式によって異なります。
  • 混合ポート:1つの待ち受けポートでHTTPプロキシとSOCKSの接続を受け付けます。ただし、システムがすべてのアプリにこのポートの利用を強制するわけではありません。

macOSでの確認方法

macOS 13以降では、「システム設定」→「ネットワーク」→現在のネットワークサービス(「Wi-Fi」など)→「詳細」→「プロキシ」を開き、Webプロキシ、安全なWebプロキシ、SOCKSプロキシのサーバーとポートを確認します。OSのバージョンによって項目名が多少異なる場合があります。Wi-Fi、Ethernetなどネットワークサービスを切り替えた場合は、以前使っていたサービスではなく、現在のサービスを確認してください。

ブラウザー、ターミナル、デスクトップアプリが同じプロキシ設定を使うとは限りません。システム設定を参照するアプリもあれば、独自のプロキシ設定を使うアプリもあります。コマンドラインツールでは、HTTP_PROXY、HTTPS_PROXY、ALL_PROXY、NO_PROXYなどの環境変数が使われることもあります。そのため、「ブラウザーはつながるのにターミナルはつながらない」という状況は、まず通信の入口の違いを疑う手がかりです。ノードの障害を示すとは限りません。

TUNモード:仮想インターフェースとルートでIP通信を取り込む

TUNは仮想的なレイヤー3ネットワークインターフェースを提供します。アプリは通常どおり接続し、OSがルート設定に従って対象のIPパケットを仮想インターフェースへ送ります。その後、コアがパケットを処理します。アプリ側でHTTPやSOCKSプロキシに対応する必要がないため、システムプロキシ設定を参照しないアプリにも使われます。

macOSでは、仮想インターフェースは通常 utun 系のデバイスとして表示されます。ただし、システムVPNやほかのネットワークサービスでも同様のインターフェースが作成されるため、utun が表示されただけではクライアントによる通信の取り込みが成功したとは判断できません。クライアントのログ、ルート、接続記録もあわせて確認してください。

有効化に必要な条件と機能上の制約

  • 権限:インターフェースの作成やルート設定には、通常、管理者の認証またはクライアントのサービスコンポーネントが必要です。認証に成功しても、その後のルート設定が正しいとは限りません。
  • コア:TUNを利用できるか、どのネットワークスタックやフィールドに対応するかは、実際に使われているコアによって異なります。クライアントの外観がClashだからといって、mihomoが使われているとは限りません。
  • UDP:TUN経由でコアに取り込めるのは、条件に合うUDP通信です。リモートノードとプロトコルもUDP転送に対応している必要があります。スイッチを有効にしても、ノードの機能が追加されるわけではありません。
  • 対象範囲:IPv6、LAN、除外ルート、ほかのVPNなどが通信の取り込み範囲に影響することがあります。TUNですべてのレイヤー2ブロードキャスト通信を取り込めるわけでもありません。

mihomoの auto-route は関連ルートを自動設定し、auto-detect-interface は出力インターフェースを自動検出します。一般的なネットワーク環境での設定に役立ちますが、社内VPN、仮想マシンのネットワーク、複数ネットワークインターフェースの構成との完全な互換性を保証するものではありません。

システムプロキシとTUNの主な違い

比較項目システムプロキシTUNモード
通信の取り込み方法アプリがローカルのプロキシポートへ接続ルート設定によりIPパケットを仮想インターフェースへ転送
アプリ側の対応アプリがシステム設定を参照するか、プロキシを手動設定する必要がある通常、アプリにプロキシ設定がなくても利用可能
UDPの利用条件アプリとプロキシプロトコルによる。一般的なHTTPプロキシだけでは対応範囲を説明できないルート、コア、ノードのUDP対応状況による
権限と影響範囲主にネットワークサービスのプロキシ設定を変更仮想インターフェース、ルート、DNSの取り込みに関わる
主な確認箇所ポートの待ち受け、アプリのプロキシ設定、除外リスト認証状態、ルート、DNS、IPv6、VPNとの競合

どちらが速いかに決まった順位はありません。同じリクエストが最終的に同じノードを使うなら、通信品質はノードの負荷、回線の状態、接続先サービスの影響をより大きく受けます。TUNでは通信処理が1段階増えますが、それだけで必ず遅くなるとは言えません。システムプロキシの経路がより直接的でも、アプリが想定どおりに利用するとは限りません。

DNS:名前解決の場所でドメインルールに渡る情報が変わる

システムプロキシを使う場合、アプリによってはドメイン名をプロキシに渡しますが、先にローカルで名前解決する場合もあります。たとえばcurlでは、socks5://は通常ローカルで宛先ドメインを解決し、socks5h://は宛先ドメインをSOCKSプロキシに渡します。同じポートを使っていても、名前解決の経路は異なることがあります。

TUNが受け取るのは主にIPパケットです。アプリがドメイン名を実際のIPアドレスに解決済みの場合、コアが元のドメイン名を自動的に把握できるとは限りません。DNSの取り込み、Fake-IPによる対応付け、通信のスニッフィングはドメインルールに情報を渡せますが、それぞれ役割が異なります。

  • DNSの取り込み:対象となるDNSリクエストをコアのDNSモジュールに渡します。一般的なポート53の通信を取り込んでも、アプリ内蔵のDoHやDoTを直接復号できるわけではありません。
  • Fake-IP:コアが対応付け用のアドレスを返し、ドメイン名とアドレスの対応関係を保持します。よく使われるアドレス範囲は 198.18.0.0/16 です。このアドレスはリモートノードのアドレスではありません。
  • スニッフィング:一部のTLS ClientHelloに含まれるSNIなど、確認可能なプロトコル情報から宛先ドメイン名を特定しようとします。HTTPSを復号する機能ではなく、暗号化されたClientHelloなどには対応できない場合があります。

mihomo設定の確認方法

以下は関連するフィールドのみを示したもので、完全な設定ではありません。使用前に、クライアントが該当フィールドに対応したmihomoを実行していることを確認し、既存設定のDNS上流、プロキシノード、ルールを残してください。クライアントのGUIから設定を生成する場合は、その設定画面を優先して使いましょう。手動変更はサブスクリプション更新時に上書きされることがあります。

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16

複数の設定を同時に変えず、入口ごとに確認する

手順1:ローカルのプロキシポートだけを確認する

まずTUNを無効にし、コアは起動したまま、プロキシを明示したコマンドでテストします。以下では混合ポートを 7890 としています。クライアントに別のポートが表示されている場合は、その値に合わせてください。コマンドには15秒のタイムアウトを設定し、接続時の情報を出力するため、ポート拒否、TLSエラー、接続先のタイムアウトを区別しやすくなります。

curl -I -v --max-time 15 \
  --proxy http://127.0.0.1:7890 \
  https://example.com/

curl -I -v --max-time 15 \
  --proxy socks5h://127.0.0.1:7890 \
  https://example.com/

127.0.0.1:7890への接続が拒否された場合は、まずコアが起動しているか、ポート番号が一致しているか、別のアプリがポートを使用していないか確認してください。プロキシへの接続後に宛先がタイムアウトする場合は、ノードと出力ルールを確認します。テスト先1つへの接続に成功しても、その経路が使えることを示すだけで、すべてのサイトが正常とは限りません。

手順2:アプリがシステムプロキシを使っているか確認する

システムプロキシを有効にし、macOSのターミナルで scutil --proxy を実行して現在のプロキシ設定を確認します。続けて、対象アプリ独自の設定と除外リストも確認してください。ターミナルでは env | grep -i proxy を実行すると、設定済みのプロキシ環境変数を確認できます。システムプロキシが正しく設定されていることと、アプリが実際にそれを使っていることは、別々に検証する必要があります。

手順3:TUNだけを確認する

システムプロキシを無効にしてTUNを有効にし、対象アプリで接続をやり直します。以下のコマンドでcurlに明示的なプロキシを使わせずにテストし、クライアントの接続画面で記録を確認してください。このコマンドが無効にするのはcurlのプロキシ利用だけで、TUNのルートを迂回するものではありません。

curl -I -v --max-time 15 --noproxy '*' https://example.com/

対応する接続記録がない場合は、TUNの起動ログ、除外ルート、IPv6の経路、ほかのVPNを確認します。記録がある場合は、マッチしたルールと最終的な出力先を確認してください。設定変更前に確立した長時間接続は、以前の経路を使い続けることがあります。必要に応じて対象アプリを終了し、再起動してください。

利用シーンに合わせる:まずシステムプロキシ、必要に応じてTUNを追加

  • 主にブラウザーを使う場合:システムプロキシなら、影響範囲を確認しやすいでしょう。まずブラウザーがシステム設定に従っているか確認してください。
  • ターミナルや開発ツールを使う場合:プロキシの引数や環境変数を明示的に設定する方法が使えます。プロキシ非対応の複数のアプリをまとめて処理したい場合は、TUNも検討してください。
  • ゲームなどUDPを使うアプリ:まずノードがUDPに対応していることを確認し、次にTUNのルートとアプリの接続記録を調べてください。システムのHTTPプロキシを有効にするだけでは、こうした通信を取り込めないことがほとんどです。
  • 社内VPNやイントラネットを使う場合:イントラネットのドメイン、プライベートIPアドレス範囲、DNSを個別に確認してください。必要に応じて除外ルートやDIRECTルールを調整し、会社指定のネットワーク設定をそのまま上書きしないようにしましょう。

システムプロキシとTUNは同時に有効にできますが、トラブルの切り分けではまず個別に確認するのがおすすめです。アプリがローカルのプロキシポートへ明示的に接続する場合は、明示的なプロキシ経由になることがあります。それ以外の通信はTUNに取り込まれる場合があります。2つのスイッチを有効にしたからといって、リモートプロキシを必ず2回経由するわけではありません。また、どの設定でもコアがすべてのルート競合を自動解決するとは限りません。

無効にした後もインターネットにつながらない場合の復旧方法

  1. まずクライアントでTUNとシステムプロキシを無効にし、クライアントを通常の手順で終了します。これにより、クライアントが設定したルートやプロキシを解除できる場合があります。
  2. 現在使っているネットワークサービスのプロキシ設定を確認し、待ち受けが停止したローカルポートを指す設定を削除します。組織によって管理されている設定は、管理者に相談してください。
  3. ターミナルのプロキシ環境変数、アプリ独自のプロキシ設定、ほかのVPNが引き続き有効になっていないか確認し、ネットワーク接続を再確立します。
  4. LANや名前解決に問題が残る場合は、ルートとDNSの状態を記録してから、使用中のクライアントに応じた復旧手順を実行してください。すべてのネットワークサービスをむやみに削除しないでください。

最終的な判断には、確認できる通信経路を使います。アプリの通信がコアに入っているか、ドメイン名がどのように解決されるか、どのルールにマッチして何が出力先になるかを確認してください。この3点を分けて調べると、システムプロキシとTUNのスイッチを何度も切り替えるより、問題を特定しやすくなります。