まずは「通信の入口」と「プロキシルール」を区別

ブラウザーは使えるのにターミナルでは接続がタイムアウトする場合、すぐにノードを変えるのではなく、通信がクライアントに届いているかを確認しましょう。システムプロキシとTUNは通信を取り込む入口、ルールモードとグローバルモードはカーネルに届いた通信の出口を決める設定です。それぞれ解決する問題が異なります。

システムプロキシは、macOSのネットワーク設定にローカルプロキシのアドレスを登録します。アプリがこの設定を参照してはじめて、リクエストがプロキシに送られます。一方、TUNは仮想ネットワークインターフェースを作成し、ルーティングによって対象範囲のIPパケットをカーネルに送ります。mihomoはClashの設定エコシステムに対応するプロキシカーネルで、クライアントは画面表示、設定管理、権限管理サービスを担います。

比較項目システムプロキシTUNモード
通信を取り込む仕組みアプリがプロキシ設定を参照し、ローカルポートへ接続仮想ネットワークインターフェースとルート経由でIPパケットをカーネルに転送
主な対象システム設定に従うブラウザーやデスクトップアプリシステムプロキシを参照しないプログラム、一部のUDPアプリ
ターミナルのコマンド通常はプロキシ引数または環境変数が必要ルートで通信が捕捉されていれば、通常は個別設定不要
必要な権限通常、TUN用の補助サービスは不要通常、インターフェースやルートの設定に補助サービスの許可が必要
DNSの処理アプリやプロキシプロトコルによって異なるDNSの横取りやカーネルDNSと連携可能。ただし対象範囲には限界あり

システムプロキシ:設定とローカルポートを確認

macOSにプロキシ設定が反映されているか確認

macOS 13以降の設定画面を例に説明します。「システム設定」→「ネットワーク」→「Wi-Fi」→「詳細」→「プロキシ」を開きます。有線接続の場合は、現在使用中のEthernetサービスを確認してください。クライアントでシステムプロキシを有効にしたら、Webプロキシ、安全なWebプロキシ、またはSOCKSプロキシのアドレスとポートを確認します。どの項目に設定されるかはクライアントによって異なります。

アドレスは通常 127.0.0.1 で、このMac自身を表します。ポートはクライアントが現在待ち受けているポートと一致している必要があります。この記事では、HTTPとSOCKSで共用する混合ポートの例として 7890 を使います。すべてのクライアントで初期値が同じとは限りません。まずクライアントのポート設定を確認してから、コマンドを実行してください。

# macOSで現在のプロキシ設定をまとめて確認
scutil --proxy

# サンプルポートをTCPで待ち受けているプロセスを確認
lsof -nP -iTCP:7890 -sTCP:LISTEN
  • scutil --proxy で HTTPEnable、HTTPSEnable、または SOCKSEnable を確認し、対応するポートも照合します。
  • lsof で何も表示されない場合は、まずポート番号の間違い、カーネルが起動していないこと、または別のポート番号に変更されていることを確認してください。
  • 待ち受けているプロセスが現在使用中のクライアントでない場合は、ポートの競合を確認してください。同じアドレスを複数のクライアントが同時に使用しないようにします。

システムプロキシを有効にしても、すべてのアプリがすぐに切り替わるわけではありません。アプリ独自のネットワークスタックや既存の長時間接続、個別のプロキシ設定が影響することがあります。設定を変更したら新しいリクエストを発行し、必要に応じて対象アプリを再起動してから、クライアントの接続ログを確認しましょう。メニューバーのスイッチだけで判断しないでください。

ターミナルのコマンド:プロキシを明示して接続を確認

コマンドラインツールがmacOSのシステムプロキシを参照するかどうかは、ツールの実装によります。一般的な curl の使い方ではプロキシ環境変数が参照されますが、システム設定パネルの内容が自動的に適用されるとは限りません。まずプロキシを引数で明示してテストすれば、「プロキシの入口」と「接続先サイト」の問題を切り分けられます。

まずHTTPプロキシを指定し、次にSOCKSをテスト

# ローカルHTTPプロキシ経由でHTTPSリクエストを送信し、最大15秒待機
curl --proxy http://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 15 -I https://example.com

# SOCKS5を使用し、接続先ドメインの名前解決をプロキシに任せる
curl --proxy socks5h://127.0.0.1:7890 \
  --connect-timeout 10 --max-time 15 -I https://example.com

2つ目のコマンドは、そのポートがSOCKSに対応している場合のみ使えます。socks5h の h は、接続先のホスト名をプロキシ経由で名前解決することを示します。socks5 の場合、curlは通常、先にローカルで名前解決します。この違いはDNSの切り分け結果に直接影響します。

続けて使う場合は、一時的な環境変数を設定

# 現在のターミナルセッションと、そこから起動する子プロセスのみに適用
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890

# テスト後に削除し、意図しない利用を防ぐ
unset http_proxy https_proxy

https_proxy の値が http:// でも矛盾ではありません。これはローカルプロキシへの接続方式を表しており、HTTPSサイトへは通常HTTP CONNECTトンネルで接続します。接続先とのTLS暗号化が自動的に無効になるわけではありません。

TUNモード:権限、ルーティング、ルールによる振り分け

TUNはIPパケットを処理するレイヤー3の仮想ネットワークインターフェースです。macOSでは通常、クライアントが特権付きの補助サービスを通じてインターフェースを作成・管理し、ルートを設定します。有効にする前に有効な設定を選び、カーネルが正常に起動することを確認してください。その後、クライアントの案内に従って補助サービスをインストールし、システムの許可を与えます。サブスクリプションページや設定ファイルにMacのログインパスワードを入力しないでください。

最小構成で押さえておきたい項目

以下はmihomoの設定例です。よく使われる項目の説明を目的としており、サブスクリプション全体を示すものではありません。クライアントによっては画面からこれらの項目を生成したり、サブスクリプション内の値を上書きしたりします。変更前に設定をバックアップし、最終的に適用される設定を確認してください。サブスクリプション全体をそのまま置き換えないでください。

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

dns:
  enable: true
  enhanced-mode: fake-ip
  • enable はTUNを有効にします。十分なシステム権限があり、カーネルが正常に起動することも必要です。
  • stack はプロトコルスタックの実装を選びます。例では mixed を使用していますが、すべてのMacやネットワーク環境で他の選択肢より優れているという意味ではありません。
  • auto-route はルートの自動設定を要求し、auto-detect-interface は送信インターフェースの自動検出に使います。Wi-Fi、有線LAN、テザリングを切り替えた後は、出口を改めて確認してください。
  • dns-hijack は横取りする対象を指定します。any:53 の対象は、該当する処理経路に入った従来型の53番ポートのDNSリクエストです。暗号化DNSをすべて横取りするものではありません。

この設定だけでは、ノード、プロキシグループ、ルール、適切な上流DNSなどが不足しています。まずクライアントがサポートする設定方法を使ってください。カーネルが項目エラーを出した場合は、実際のカーネルの種類とバージョンを確認し、対応するドキュメントに沿って修正します。

TUNの有効化とグローバルモードを区別する

TUNを有効にすると通信はmihomoに入りますが、ルールモードではドメイン、IPアドレスなどの条件に応じてルールを適用できます。DIRECTルールに一致すれば直接接続され、プロキシグループに一致すればグループ内で選択された出口を使います。グローバルモードでは通常、通信がグローバルポリシーグループに送られますが、入口の対象範囲やルートからの除外の影響は受けます。通信を取り込む範囲を広げたいならTUNを有効にし、出口の選択を変えたいならルールとポリシーグループを確認しましょう。

DNS:Webが使えても名前解決経路が同じとは限らない

DNSはドメイン名をIPアドレスに変換します。システムプロキシはアプリからプロキシへの接続方法を変えるだけで、すべてのアプリの名前解決を一元管理するわけではありません。ブラウザーはドメイン名をプロキシ経由で送る場合もあれば、独自のセキュアDNSを使う場合もあります。他のプログラムは先にシステムDNSで問い合わせ、その結果のIPアドレスへ接続することがあります。

TUNはカーネルDNSと連携し、より多くの名前解決リクエストを処理できます。fake-ipを有効にすると、カーネルがドメイン名に対応する仮想アドレスを割り当て、接続時に実際の接続先と関連付けます。198.18.0.0/15 の範囲のアドレスが表示されても、必ずしも異常ではありません。ただし、実際に設定されているfake-ipのアドレス範囲を確認してください。

名前解決の問題は3段階で確認

  1. システム側の入口を確認。 scutil --dns を実行して、現在のリゾルバーを確認します。表示されるのはシステム設定であり、すべてのアプリが同じリゾルバーを使っている証拠にはなりません。
  2. カーネルのログを確認。クライアントの接続画面とログ画面を開き、同じドメインに再度アクセスして、DNSリクエスト、適用されたルール、出口の選択を確認します。
  3. アプリ独自の設定を確認。ブラウザーのセキュアDNS、アプリ内プロキシ、暗号化DNSの設定を確認してください。DoHはHTTPSで通信し、DoTは通常853番ポートを使用します。53番ポートの横取りだけでは対象になりません。

dig を一度実行しただけで、システム全体のDNS経路を判断しないでください。macOSのドメイン別名前解決、VPNのリゾルバー、アプリのキャッシュなどにより結果は異なることがあります。また、dig の問い合わせ経路は、アプリがシステムの名前解決サービスを呼び出す経路と完全には一致しません。切り分けでは、対象ドメイン、日時、使用したツールを記録し、異なるテスト結果を混同しないようにしましょう。

ゲームとUDP:通信を取り込めてもノードの確認が必要

ゲームではTCPとUDPの両方が使われることがよくあります。従来型のHTTPシステムプロキシでは、ゲームが直接送信するUDPパケットを扱えないのが一般的です。SOCKSプロトコルにはUDP転送の仕組みがありますが、アプリ側もそれをサポートし、利用する必要があります。TUNはこうした通信をより広くカーネルへ送れるため、システムプロキシを利用しないゲームの接続を調べるのに適しています。

ただし、仮想ネットワークインターフェースがリモートノードにUDP対応を追加するわけではありません。ノードのプロトコル、サーバー設定、選択したプロキシグループの出口、ローカルネットワークなどによってUDPが制限されることがあります。まずクライアントの接続一覧にゲームの通信が表示されるか確認し、DIRECTとプロキシグループのどちらに一致したかを調べます。最後に、選択したノードが必要な通信に対応しているか確認してください。

  • ログインは成功するのに、対戦に入れない:ログイン時のTCPリクエストと対戦時のUDP接続を分けて確認してください。ログインページのテストだけで判断しないようにしましょう。
  • 接続できるが遅延が大きい:同じリージョン、同じ時間帯で、ゲーム内の遅延とパケットロスを比較します。ノード一覧のHTTP速度テストはゲームの遅延を示すものではありません。
  • LAN対戦やデバイス検出に問題がある:ローカルネットワークを迂回する設定を確認してください。ブロードキャスト、マルチキャスト、デバイス検出プロトコルを、一般的な外部向けユニキャスト接続と同じように扱うべきではありません。

アプリが特定のネットワークインターフェース、アンチチートコンポーネント、特殊な通信方式に依存している場合、TUNでも互換性が保証されるわけではありません。元のネットワーク設定と復旧方法を残し、一度に変更する項目を一つにすれば、原因が通信の取り込み方式、ルール、出口のどれかを特定しやすくなります。

Macでの選び方とトラブル時の復旧手順

アプリの要件に合わせて入口を選ぶ

  • 主にブラウザーやシステムプロキシに従うアプリを使う:まずシステムプロキシを有効にしましょう。設定がわかりやすく、ローカルポートも確認しやすくなります。
  • ターミナルをたまに使う:コマンドに --proxy を指定するか、現在のセッションに環境変数を設定し、影響範囲を明確にしましょう。
  • 複数のプログラムがプロキシを無視する、またはUDPを扱いたい:TUNを検討し、補助サービス、DNS、ルーティングも確認しましょう。
  • 会社のVPNに接続中:まず組織のネットワークルールに従ってください。どちらのツールもルートやDNSを変更する可能性があります。直接併用せず、それぞれ個別にテストしましょう。

TUNを有効にしてネットにつながらない場合は、まず元に戻してから原因を調べる

  1. TUNを無効にし、クライアントは起動したまま通常のネットワーク接続が復旧するか確認します。異なるサブスクリプションを何度もインポートするのは避けてください。
  2. システムプロキシを無効にし、テストに使ったターミナルのプロキシ環境変数を削除して、直接接続できるか確認します。all_proxy や大文字の環境変数を設定していた場合は、該当する項目も削除してください。
  3. scutil --proxy でプロキシ設定が残っていないか確認し、route -n get default でデフォルトルートを確認します。TUNはより具体的な振り分けルートを使う場合があるため、デフォルトルートだけでは通信全体の取り込み状況はわかりません。
  4. netstat -rn -f inet でIPv4ルートを確認します。IPv6も確認する場合は netstat -rn -f inet6 を実行してください。utun インターフェースが表示されても、現在のクライアントが作成したものとは限りません。他のVPNが使用している場合もあります。
  5. 接続が復旧したら、入口を一つだけ有効にして再テストします。TUNだけが失敗する場合は、サービスの権限、ルートの競合、DNSログを確認してください。

システムプロキシとTUNに、常に当てはまる優劣はありません。システムプロキシは自らプロキシを利用するアプリに向き、TUNは通信を取り込む範囲を広げる一方で、ルーティング、権限、DNSの確認項目が増えます。すべての設定を一度に有効にするより、まず必要最小限の設定で目的を満たし、必要に応じて対象範囲を広げるほうが管理しやすくなります。