· トラブル対処 · 読了まで約12分

Clashの起動時にポートが使用中と表示される場合の対処法|使用中のプロセス特定とmixed-portの変更

Windows、macOS、Linuxでnetstat・lsof・ssを使い、7890などのポートを使用中のプロセスを特定。ポート変更後にシステムプロキシやブラウザーの設定を更新する方法も解説します。

まずログを確認:ポート・アドレス・エラーの種類を特定

ClashまたはClash Meta(現名称:mihomo)の起動時にポートのバインドに失敗したら、まずどのリスナーでエラーが発生したかを確認します。7890はローカルプロキシの入口としてよく使われますが、固定の必須ポートではなく、リモートノードのサービスポートでもありません。ローカルの入口を変更しても、通常はサブスクリプション内のノードアドレス、パスワード、プロキシルールを変更する必要はありません。

クライアントのログ画面でlisten、bind、address already in useなどを検索し、ローカルアドレスとポートを記録します。次のログは、TCPのIPv4ループバックアドレスへのバインドに失敗した例です。

listen tcp 127.0.0.1:7890: bind: address already in use

WindowsではOnly one usage of each socket addressと表示されることもあります。permission deniedまたはAn attempt was made to access a socket in a way forbidden by its access permissionsと表示された場合は、権限やセキュリティポリシー、システムの予約済みポートも確認してください。別のClashプロセスによる競合とは限りません。

設定項目用途バインド失敗時の影響
mixed-portHTTPとSOCKS5で共用する入口この入口を使うアプリがプロキシに接続できない
port / socks-portHTTP/SOCKS専用の入口該当プロトコルのプロキシ入口が利用できない
external-controllerコントロールAPI(例:9090)クライアントの画面からコアに接続できない場合がある
dns.listen内蔵DNSのリスニングアドレス関連するDNSクエリが失敗する場合がある

確認するのは数字だけではなく、「プロトコル+ローカルアドレス+ポート」です。127.0.0.1:7890、0.0.0.0:7890、[::]:7890ではリッスンする範囲が異なります。ワイルドカードアドレスやデュアルスタックのリスニングは、より具体的なアドレスと競合することがあります。

Windows:netstatとPowerShellでプロセスを特定

リスニング状態を確認し、PIDを調べる

PowerShellを開き、次のコマンドを実行します。1つ目は簡易確認用、2つ目はローカルTCPポートで絞り込むコマンドです。他のプロセスの詳細を確認するには、管理者としてターミナルを起動する必要がある場合があります。

netstat -ano -p tcp | findstr ":7890"
Get-NetTCPConnection -LocalPort 7890 -State Listen -ErrorAction SilentlyContinue |
  Select-Object LocalAddress, LocalPort, State, OwningProcess

netstatの最後の列はプロセスID(PID)です。findstrはリモートアドレスや78900などにも一致する場合があるため、「ローカルアドレス」列が7890で、状態がLISTENINGであることを確認してください。TIME_WAITは接続状態なので、それだけを理由にプロセスを終了しないでください。

検索結果のPIDが4321だったとします。続けてプロセス名、実行ファイルのパス、コマンドラインを確認します。4321は説明用の例です。実行時は必ず実際の検索結果に置き換えてください。

tasklist /FI "PID eq 4321"
Get-CimInstance Win32_Process -Filter "ProcessId = 4321" |
  Select-Object Name, ExecutablePath, CommandLine

別のプロキシクライアントが起動したmihomoなら、まずそのクライアントのタスクトレイメニューから終了するか、バックグラウンドサービスを停止してください。ウィンドウを閉じただけでは、コアが停止しないことがあります。PIDがシステムサービスや不明なソフトウェアのものなら、強制終了する前にパスと用途を確認してください。

リスニングが見つからないのにバインドエラーが出る場合

  • ログを確認し、対象ポートが7890ではなく7891、9090、または別のポートではないか調べます。
  • エラー後にクライアントがコアを繰り返し再起動していないか確認します。プロセスが終了しているタイミングに検索すると、見つからないことがあります。
  • ログにUDPと明記されている場合は、Get-NetUDPEndpoint -LocalPort 7890で確認してください。TCPだけを調べても特定できません。
  • アクセス権限に関するエラーなら、次のコマンドでIPv4 TCPの除外ポート範囲を確認します。ポートが範囲内にある場合は、システムの予約範囲を削除するより、別の空きポートを選ぶほうが安全です。
netsh interface ipv4 show excludedportrange protocol=tcp

macOS:lsofでリスナーとバックグラウンドサービスを確認

「ターミナル」で次のコマンドを実行します。-nPはアドレスやポートの名前解決を無効にし、-sTCP:LISTENはリスニング中のソケットだけを表示します。ローカルサービスと通常の外向き接続を区別しやすくなります。

sudo lsof -nP -iTCP:7890 -sTCP:LISTEN

結果のCOMMANDはプロセス名、PIDはプロセスID、NAMEはリスニングアドレスです。*:7890と表示された場合、特定のローカルインターフェースだけにバインドされているわけではありません。次に完全なコマンドラインを確認し、どのクライアントや起動項目がコアを起動したか特定します。

ps -p 4321 -o pid,ppid,user,command

古いクライアントのプロセスだと確認できたら、まず該当アプリを通常の手順で終了します。それでも停止しない場合は、「アクティビティモニタ」で確認済みのプロセスを選び、終了を試してください。コマンドラインから実際のPIDにkill -TERM 4321を送れば、正常に終了処理を行わせることができます。kill -9を最初の手段にしないでください。

終了後すぐに新しいPIDが現れる場合、自動起動の仕組みが動いている可能性があります。macOS 13以降では「システム設定」→「一般」→「ログイン項目」(バージョンによっては「ログイン項目と機能拡張」)でバックグラウンド項目を確認します。Homebrewでインストールしたサービスはbrew services listも確認してください。子プロセスを何度も終了するのではなく、該当するサービスの設定から停止します。

Ubuntu/Linux:ssでsystemdサービスや重複したコアを特定

Ubuntuではssを使ってTCPのリスニング状態を確認します。sudoを付けると、通常は他のユーザーのプロセスIDとプログラム名も表示されます。権限を省略すると、ソケットは見えてもプロセス情報が表示されないことがあります。

sudo ss -ltnp 'sport = :7890'
sudo ss -lunp 'sport = :7890'

1つ目のコマンドはTCP、2つ目はUDPを確認します。TCPの出力ではLISTENがリスニング中を示します。UDPは通常UNCONNと表示され、状態名が異なります。lsofがインストールされている環境では、macOSと同じsudo lsof -nP -iTCP:7890 -sTCP:LISTENも使えます。

デスクトップクライアントとsystemdが同時に起動している場合

よくある競合は、サーバー用に残したsystemdサービスが7890を使用中なのに、デスクトップクライアントが別のコアを起動しようとするケースです。PIDが4321なら、まずコマンドラインと所属サービスを確認し、どちらを残すか判断します。

ps -p 4321 -o pid,ppid,user,args
sudo systemctl status 4321

systemctl statusはPIDから所属ユニットを調べられます。mihomo.serviceという名前の自作サービスで、デスクトップクライアントを使う場合は、そのサービスを停止します。

sudo systemctl stop mihomo.service
sudo ss -ltnp 'sport = :7890'

サービス名は、必ずこのマシンでの実際の確認結果に合わせてください。今後、起動時にサービスを開始する必要がなければ、sudo systemctl disable mihomo.serviceを実行します。disableだけでは現在のプロセスは停止しません。ユーザー単位のサービスにはsystemctl --userを使います。自動再起動が有効なサービスでは、コアを直接終了しても再び起動することがあります。

リスナーがコンテナ関連のプロセスなら、コンテナのホスト側ポートマッピングも確認してください。プロキシポートを空けるためにコンテナ環境全体を停止する必要はありません。該当コンテナのマッピングを変更するか、ローカルプロキシの入口を別のポートに変更できます。

mixed-portを変更する:画面上の設定と実際に適用される設定

使用中のプログラムを停止できない場合は、Clashのローカル入口を7890から17890に変更できます。17890はこの記事の例であり、お使いの環境で空いているとは限りません。変更前に、前述のコマンドで新しいポートの使用状況を確認してください。

GUIクライアントでは、まず設定画面で変更

クライアントによって画面の名称は異なりますが、「設定」の「ポート」「プロキシポート」「コア設定」などから変更できます。コントローラーポートではなく、混合ポートの設定であることを確認してください。クライアントが生成設定に値を書き込み、サブスクリプションファイル内の同名項目を上書きする場合があります。ダウンロードしたサブスクリプションのYAMLだけを変更しないでください。

mihomoを単独で実行する場合はルート階層の項目を変更

設定ファイルを直接読み込むコアでは、起動オプション-fで指定したファイルを編集します。作業ディレクトリを-dで指定している場合は、そのディレクトリ内の実際の設定ファイルを確認してください。以下は入口の項目だけを変更する例で、ノードやルールを含む完全な設定ではありません。

mixed-port: 17890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: info
  • mixed-portはYAMLのルート階層に記述します。前にgeneral:を付けたり、dns:の下にインデントしたりしないでください。
  • 元の設定にportやsocks-portなどの専用入口もある場合は、それぞれが競合ポートを使用していないか確認してください。混合ポートだけを変更しても、ほかの入口は自動で変更されません。
  • ルート階層の入口を変更したら、クライアントの手順に従って設定を再適用するか、コアを再起動します。プロキシノードを切り替えただけでは、リスナーの設定が更新されるとは限りません。
  • サブスクリプションの更新で、直接編集した内容が上書きされることがあります。上書きやマージに対応したクライアントでは、ローカルのポート設定を永続化設定またはオーバーライド層に保存してください。

単独で導入した環境では、mihomo -t -f /etc/mihomo/config.yamlを実行して設定を解析できるか確認できます。パスは実際の導入環境に合わせてください。設定テストに成功しても、実行時にポートを使えるとは限りません。起動ログとリスニング状態も確認してください。

システムプロキシ・ブラウザー・ターミナルのポートをそろえる

コアのポートを17890に変更した後も、アプリが127.0.0.1:7890に接続していると、症状は「コアの起動失敗」から「プロキシサーバーが接続を拒否」に変わります。クライアント画面だけでなく、古いポートを手動入力したすべての設定を更新してください。

利用方法確認する設定箇所
Windowsのシステムプロキシ「設定」→「ネットワークとインターネット」→「プロキシ」→「手動プロキシセットアップ」
macOSのシステムプロキシ「システム設定」→「ネットワーク」→現在の接続→「詳細」→「プロキシ」
Ubuntu GNOME「設定」→「ネットワーク」→「ネットワークプロキシ」で手動プロキシのポートを確認
Firefoxの個別プロキシ設定「設定」→「一般」→「ネットワーク設定」→「接続設定」
ブラウザーのプロキシ拡張機能現在のプロファイルに設定されているHTTP/SOCKS5サーバーのアドレスとポート
ターミナルと開発ツールプロキシ環境変数、Git設定、IDE、パッケージマネージャー個別のプロキシ設定

クライアントでシステムプロキシを管理している場合は、新しい入口でリスニングできることを確認してから、「システムプロキシ」をいったんオフにして再度オンにします。クライアントがアドレスを設定し直します。Firefoxで「システムプロキシ設定を使用する」を選んでいれば、通常はポートを個別に入力する必要はありません。「手動でプロキシを設定する」を選んでいる場合は、ポートを更新してください。

LinuxまたはmacOSの現在のシェルでは、必要に応じて環境変数を更新します。https_proxyにhttp://を指定しても問題ありません。HTTPプロキシ経由でHTTPSトンネルを確立するという意味であり、接続先サイトがHTTPに切り替わるわけではありません。

export http_proxy=http://127.0.0.1:17890
export https_proxy=http://127.0.0.1:17890
export all_proxy=socks5h://127.0.0.1:17890

これらのコマンドが影響するのは現在のシェルと、その後に起動する子プロセスだけです。すでに開いているアプリには自動反映されません。シェルの起動ファイルに古い値が残っていないかも確認してください。Gitではまずgit config --show-origin --get-regexp '.*proxy.*'で設定元を調べ、実際に適用されている範囲を変更します。グローバル設定だけを変更して、リポジトリ単位の設定を見落とさないようにしてください。

TUNモードは仮想ネットワークインターフェースで通信を取り込み、明示的なHTTP/SOCKS入口とは別の仕組みで動作します。TUNを有効にしても、使用中のポートが空くわけではありません。設定で7890のリスニングが必要なままなら、引き続きエラーになる可能性があります。また、TUNで一部のアプリが使えるからといって、古いシステムプロキシ設定を放置しないでください。

復旧確認:リスニング・リクエスト・再起動後の設定保持

  1. リスニングプロセスを確認します。OSに対応したコマンドで17890を調べ、残す予定のコアがリスニングしていることと、ループバックまたはワイルドカードアドレスのどちらで待ち受けているかを確認します。
  2. プロキシ経由でリクエストを送信します。次のコマンドで、アプリがシステムプロキシ設定に従うかどうかに左右されず、HTTPとSOCKS5の入口をそれぞれテストします。
  3. クライアントの接続ログを確認します。テストリクエストがコアに届いたことを確認し、適用されたルールと出口を調べます。ローカルの入口に接続できても、リモートノードが利用できるとは限りません。
  4. 普段使うアプリで確認します。ブラウザーやターミナルを開き直し、7890を参照していないか確認してください。
  5. 再起動とサブスクリプション更新後も確認します。クライアントを再起動してポートを再確認します。サブスクリプション更新後も、保存した設定が上書きされていないことを確認してください。
curl --noproxy "" --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 20 -I https://example.com/
curl --noproxy "" --proxy socks5h://127.0.0.1:17890 --connect-timeout 5 --max-time 20 -I https://example.com/

WindowsのPowerShellでは、上記のcurlをcurl.exeと明示してください。旧バージョンのPowerShellでは同名のエイリアスによって、引数の解釈が異なる場合があります。--noproxy ""はプロキシをバイパスする設定による影響を除くための指定です。5秒と20秒はそれぞれ接続タイムアウトとリクエスト全体のタイムアウトであり、速度測定の結果ではありません。

接続拒否が返された場合は、ローカルのリスニング状態とポートを確認します。プロキシへの接続後にタイムアウトする場合は、ルール、ノード、DNS、接続先サイトへの到達性を調べます。エラーの対象ポートがコントロールAPIの9090なら、mixed-portを繰り返し変更するのではなく、コントローラーのアドレスとクライアントの接続パラメーターを合わせて変更してください。「ログで特定→プロセスを確認→重複サービスの停止またはポート変更→アプリの設定更新→動作確認」の順に進めると、ローカルのバインド障害と、その後のネットワーク障害を切り分けられます。

Clashをダウンロード