まず失敗した段階を確認し、次にログレベルを見る
Clashのログは「接続がカーネルに届いたか → どのルールに一致したか → どのポリシーを使ったか → どの段階で失敗したか」の順に確認します。warningはイベントのレベルを示すもので、クライアント全体が使えないという意味ではありません。i/o timeoutが一度出ただけで、ノードの障害とも断定できません。同じリクエストの時刻、接続先、ポリシー、エラーをまとめて確認し、ローカルポート、DNS、プロキシサーバーのどこを調べるべきか判断しましょう。
# 現在有効な設定のトップレベルに統合し、同じフィールドを重複して追加しない
log-level: info
この記事では、一般的なClashの設定とClash Meta(mihomo)カーネルを取り上げます。カーネルやクライアントによってログの形式、フィールド名、日本語の表示内容は異なります。以下の例はフィールドの関係を説明するもので、すべてのバージョンで同じ文言が出力されるわけではありません。調査を始める前に、クライアントのバージョン、カーネル名、カーネルのバージョンを記録してください。デスクトップアプリのバージョンだけでは不十分です。
log-levelの選び方
log-levelはYAMLのトップレベルフィールドです。dnsやproxy-groupsの中には置けません。一般的な値はsilent、error、warning、info、debugです。設定値はwarnではなくwarningです。ログに表示されるWARNは出力ラベルであり、設定にも同じ表記を使えるという意味ではありません。
| 設定値 | 出力範囲 | 用途 |
|---|---|---|
silent | 通常のカーネルログを出力しない | 接続障害の調査には不向き。クライアント独自のメッセージは出力される場合があります |
error | エラーイベント | 出力が少なく、接続に関する有用な警告を見落とすことがあります |
warning | 警告およびエラーイベント | 接続異常の確認向け。通常の通信経路の追跡には不向き |
info | 通常の動作情報と、それより重大なイベント | ルールの一致結果、ポリシーの選択、基本的な接続状況の確認 |
debug | デバッグ情報を追加 | 名前解決、接続、内部処理の詳細を短時間追跡 |
変更してもログが増えないのはなぜ?
- 変更したのが現在有効なProfileであり、まだ切り替えていない別の設定ではないことを確認します。
- クライアントの実行時設定やオーバーライド機能によって、
log-levelが別の値に戻されていないか確認してください。サブスクリプションの元データより、最終的に適用された設定のほうが判断材料になります。 - クライアントの手順に従って設定を再読み込みします。実行中の設定変更に対応している場合は、その設定機能を使えば、何度もシステムを再起動する必要はありません。
- ログビューアーのキーワードやレベルの絞り込みを解除して、新しいリクエストを送ります。
debugに切り替えても、過去のログに情報が追加されることはありません。
設定を読み込めない場合は、起動ログまたはクライアントのカーネル出力を確認します。このときログ一覧が空なのは、カーネルがまだ起動していないためかもしれません。プロキシルールの調査を続ける前に、起動状況を確認してください。
接続ログで確認するフィールド
まず接続経路を確認し、次に末尾のエラーを読みます。以下は構造を説明するための例です。送信元はローカルの一時ポート、接続先はWebサイトのHTTPSポートで、Proxyはポリシーグループ名です。
[TCP] 127.0.0.1:53124 --> www.example.com:443
match DomainSuffix(example.com) using Proxy[ノードA]
[TCP] dial Proxy (match DomainSuffix/example.com)
127.0.0.1:53124 --> www.example.com:443
error: dial tcp 192.0.2.10:443: i/o timeout
ここでの192.0.2.10は説明用のアドレスで、利用できるノードではありません。実際のログにある接続先アドレスは、プロキシサーバーの場合もあれば、直接接続先やDNSリゾルバーの場合もあります。最後に表示されたIPアドレスだけを見て、Webサイトが停止していると判断しないでください。カーネルがどこに接続しようとしているのか、現在のアウトバウンドポリシーとエラーの前後を合わせて確認します。
- 時刻:手動テストと一致するか、バックグラウンドアプリが以前に行った接続かを確認します。
- ネットワークの種類:
TCPとUDPは別の通信方式です。Webページが表示できても、ゲームなどUDPを使うアプリが正常とは限りません。 - 接続先:ドメイン名かIPアドレスか、ポートが想定どおりかを確認します。HTTPSでは
443が一般的です。 - ルールとアウトバウンド:一致したルール、振り分け先のグループ、グループ内で最終的に選択されたノード、
DIRECT、REJECTを確認します。 - エラーが発生した段階:名前解決、TCP接続、プロキシのハンドシェイク、その後の読み書きのどこで発生したかを確認します。
dial tcpとi/o timeoutが示すもの
dial tcpはTCP接続を開始していることを示す表現で、それ自体がエラーの原因ではありません。後続のi/o timeout、connection refused、network is unreachableが、失敗の手がかりになります。プロキシプロトコルのハンドシェイク、TLSネゴシエーション、アプリケーションのリクエストはそれぞれ別の段階です。TCP接続が一度成功しただけで、通信全体が正常とは判断できません。
| エラーの例 | 読み取れること | 次に確認すること |
|---|---|---|
dial tcp … i/o timeout | 指定したアドレスへのTCP接続が制限時間内に完了しなかった | アドレスとポートを確認し、ネットワーク経路、サービスへの到達性、ファイアウォールを調べる |
i/o timeout | 何らかのネットワーク読み書きがタイムアウトした。これだけでは発生段階を特定できない | 前後のログを確認し、接続やハンドシェイクが始まっていたかを確かめる |
connection refused | 接続拒否の応答を受信したか、ネットワーク機器に拒否された | 待ち受けポートとサービスの状態を確認する。まずDNSモードを変更する必要はありません |
network is unreachable | 現在のネットワークスタックで利用可能な経路が見つからない | ルーティング、ネットワークインターフェース、IPv4/IPv6の到達性を確認する |
connection reset by peer | 接続先、または経路上の機器によって接続がリセットされた | プロトコル、サーバー側のログ、発生時刻を確認する。この情報だけで原因の所在は特定できない |
EOF | 読み取り中に接続が終了した | ハンドシェイク中かどうかを踏まえてプロトコル設定を確認する。正常に終了しただけの場合もある |
すべてのノードでのタイムアウトと、特定の接続先だけのタイムアウトは分けて考える
複数の異なるサーバーへの接続が同時にタイムアウトする場合は、まずローカルネットワーク、ルーター、ファイアウォール、サブスクリプションURLの有効性を確認します。失敗するノードが1つだけなら、そのノードのサーバーアドレス、ポート、サービス状態を優先して調べます。同じノードで他のWebサイトには接続でき、特定のドメインだけ失敗する場合は、接続先のWebサイト、名前解決、ルールによる振り分けを確認します。遅延テストは通常、特定のテスト用アドレスに接続します。テストに成功しても、すべてのWebサイトにアクセスできるとは限りません。
DNS・TLS・ポートのエラーを見分ける
名前解決の失敗:ノードのドメインと接続先のドメインを区別する
lookup … no such hostはドメイン名の解決に失敗したことを示し、DNS … timeoutはDNSリクエストが時間内に完了しなかったことを示します。解決できなかったのがノードのサーバー、サブスクリプションサーバー、アクセス先のWebサイトのどれかを確認してください。ノードのドメインを解決できない場合、プロキシ接続自体がまだ確立していない可能性があります。Webサイトのルールをむやみに変更しても解決しません。
システムのnslookupの結果が、mihomo内部のDNSの結果と一致するとは限りません。Fake-IP、DNSハイジャック、分流による名前解決が有効な場合は特に注意が必要です。システムの名前解決結果は比較用に使えますが、現在有効なdns設定もあわせて確認してください。mihomoのproxy-server-nameserverはプロキシノードのドメイン名解決に使われます。使用中のバージョンで対応しているかと、実際の設定を確認し、未対応の古いカーネルにそのまま適用しないでください。
TLSエラー:証明書、時刻、プロトコル設定を確認する
x509関連のエラーは、証明書の信頼性、有効期限、名前の不一致に関係することがあります。まずシステムの日付を確認し、次にノードのTLS設定、サーバー名、サーバー側の要件を確認してください。tls handshake timeoutはTLSハンドシェイクが時間内に完了しなかったことを示しますが、証明書エラーとは限りません。リクエストがまだハンドシェイク中なら、WebサイトがHTTPエラーを返したとは判断できません。
リッスンに失敗したら、まずローカルの接続口を復旧する
bind: address already in useは通常、ローカルの待ち受けアドレスとポートがすでに使用中であることを示します。たとえばHTTPとSOCKSを7890でまとめて待ち受ける設定でも、別のクライアントが同じポートを使っていると、カーネルの接続口を正常に作成できないことがあります。競合しているプロセスを停止するか、ポートを変更し、システムプロキシ、ブラウザー、ターミナルの設定も合わせて更新してください。
# ローカル接続口の設定例。7890はサンプルのポートで、すべてのクライアントのデフォルト値ではありません
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
これはフィールドの一部を示す例であり、ノードや完全なルールは含まれていません。変更前に元の設定にmixed-portが存在するか確認し、同じキーを重複させないようにしてください。ローカルからのアクセスだけでよい場合はallow-lan: falseのままにします。ローカルポートの競合を解決するために、LANからの接続を許可する必要はありません。
ルール未一致:順序、モード、最終ポリシーを確認する
「ルール未一致」は通常、調査状況を説明する言葉であり、バージョンを問わず共通のエラーメッセージではありません。接続がフォールバックルールに一致した、想定外のポリシーに振り分けられた、あるいはカーネルに届いていない状態を、まとめてこのように呼ぶことがあります。ルールはrulesの上から順に評価されるため、先にある広範なルールが接続を捕捉している可能性があります。
# 設定例:ドメインルールを先に置き、フォールバックルールを後に置く
# Proxyには、完全な設定内に存在するポリシーグループ名またはプロキシ名を指定する
mode: rule
rules:
- DOMAIN-SUFFIX,example.com,Proxy
- MATCH,DIRECT
- まずモードを確認:
globalはグローバルポリシー、directは直接接続を使います。これらのモードでは、ruleモードのルール順を検証できません。 - 次に接続先を確認:アプリがIPアドレスに直接接続する場合があります。ドメイン名を特定できるかどうかは、DNSマッピング、スニッフィング、実際の通信内容によります。IPアドレスへの接続がすべてドメインルールに一致するとは限りません。
- フォールバックルールを確認:
MATCH,DIRECTに一致するのはルールが正常に動作した結果ですが、期待した動作とは限りません。前にある個別のルールを修正してください。 - グループ内の選択を確認:ログに
Proxyと表示されても、必ずプロキシ経由とは限りません。そのグループでDIRECTが選択されていれば、最終的には直接接続されます。 - 更新による上書きを確認:サブスクリプションの更新で、手動編集した内容が置き換えられる場合があります。長期的に適用するルールには、クライアントが対応するマージやオーバーライド機能を使い、生成後の設定を確認してください。
該当するログがまったくない場合は、まず接続口を調べてください。システムプロキシの設定が適用されるのは、その設定に従うアプリだけです。ターミナル、ゲーム、独自のプロキシ設定を使うブラウザーは、別の経路を通ることがあります。TUNを使うと、より多くのIP通信を受け取れますが、権限、ルーティング、除外設定、DNS設定の影響は受けます。TUNを有効にしただけでは、すべての通信がカーネルに届いている証明にはなりません。各フィールドの意味は設定項目の解説もご覧ください。
再現可能なリクエストでログから原因を調べる手順
有効なトラブルシューティングでは、変更のたびに新しい証拠を確認します。以下ではローカルのHTTPプロキシ入口127.0.0.1:7890を例にします。設定で別のポートを使っている場合は、コマンドのポートも合わせて変更してください。
- 現在のProfile、カーネルのバージョン、プロキシモード、選択中のノード、ローカルの待ち受けポートを記録し、ログレベルを
infoに設定します。 - 関係のないダウンロードや速度測定を止め、現在時刻を記録します。バックグラウンドの接続をテスト結果と混同しないよう、接続先は1つに絞ってください。
- 以下の明示的なプロキシ指定コマンドでテストし、システムプロキシ設定に依存しないようにします。Windows PowerShellでは
curl.exeを使うと、古い環境で同名のエイリアスが使われる問題を避けられます。 - 同じ時間帯の接続ログを見つけ、ルールとアウトバウンドを確認してから、末尾のエラーを読みます。ログが見つからない場合は、待ち受け口とビューアーの絞り込みを先に確認してください。
- 情報が足りない場合は
debugに切り替え、同じリクエストを再実行します。各回で変更する条件は1つにしてください。たとえばノードだけを切り替え、DNS、ルール、TUNを同時に変更しないようにします。 - 復旧を確認したら
infoに戻し、原因と最終的に適用されたフィールドを記録します。大量のデバッグログを長期間出力したままにしないでください。
curl --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 15 --verbose https://example.com/ --output /dev/null
Windowsでcurl.exeを使う場合、出力先の/dev/nullはNULに置き換えられます。ここで指定する10秒はcurlの接続段階の上限、15秒はリクエスト全体の上限です。カーネル内部のタイムアウト設定が変わるわけではありません。コマンドの--verboseはプロキシ接続とTLSの過程を表示します。HTTPSをHTTPプロキシ経由で接続する場合、CONNECTの成功はトンネルが確立したことを示すだけなので、その後のハンドシェイクと応答も確認してください。
ログを共有するときに残す情報・隠す情報
質問するときは、障害の発生時刻、クライアントとカーネルのバージョン、関連するモード、接続先のポート、ルールの判定結果、1回のリクエスト前後の連続したログを提示してください。timeoutの最後の一文だけを画像で共有するより、再現前後の約10~30行を残すほうが原因を特定しやすくなります。設定の一部を共有する場合は、階層とフィールド名を保ちつつ、サービスへのアクセスに使える認証情報を削除してください。
- サブスクリプションURL全体とクエリパラメーター、ノードのパスワード、UUID、アクセストークン、コントロールインターフェースの
secretは伏せてください。 - 必要に応じて実際のドメイン名、LAN内のアドレス、ノードのアドレスを伏せます。ただし、同じ対象には一貫した別名を付け、対応関係がわからなくならないようにしてください。
- エラーの種類、接続先ポート、TCP/UDPの別、ルールの順序は残してください。これらは原因の判断に直結します。
- 完全なサブスクリプションファイルを、質問時に最初から添付しないでください。ノードが多くても、再現手順の不足は補えません。
最終的な判断は、具体的な段階に分類できる形にします。リクエストがローカルの接続口に届いていない、ルールの選択が想定と違う、ノードへの接続に失敗した、プロトコルのハンドシェイクに失敗した、または接続先から異常な応答が返った、のいずれかです。まず原因を分類してから変更するほうが、クライアントの再インストールや設定全体の一括リセットを繰り返すより、手がかりを保ちやすくなります。