プロキシの待受ポートとコントロールポートを区別する
Clash、またはClash Meta(mihomo)コアを使うクライアントの起動時にログへ address already in use と表示される場合、コアが待ち受けようとしているアドレスとポートを、ほかのプロセスがすでに使用している可能性があります。エラーに表示されたプロトコル、アドレス、ポートを控え、どのプログラムを終了するか、どの設定項目を変更するか判断してください。「起動に失敗しました」という表示だけを見てサブスクリプションを何度も切り替えても、通常は端末上の待受ポート競合は解消しません。
listen tcp 127.0.0.1:7890: bind: address already in use
listen tcp 127.0.0.1:9090: bind: address already in use
この2行はそれぞれ異なる機能を示します。7890はプロキシの接続先、9090はコントロールAPIでよく使われますが、どちらも一般的な設定例であり、すべてのクライアントで固定されているわけではありません。現在の設定と起動ログを確認してください。
| 項目 | 用途 | 競合時によくある症状 |
|---|---|---|
mixed-port | 同じポートでHTTPとSOCKSのプロキシ接続を受け付ける | アプリからローカルプロキシに接続できない |
port | HTTPプロキシ専用の待受ポート | このHTTPポートを使うリクエストが失敗する |
socks-port | SOCKSプロキシ専用の待受ポート | このSOCKSポートを使うリクエストが失敗する |
external-controller | クライアントやパネルから呼び出すコントロールAPIのアドレス | パネルが接続できない、状態を取得できない、またはルールを切り替えられない |
Windows:待受ポートから使用中のプロセスを特定する
手順1:TCPの待受ポートとPIDを確認
PowerShellを開き、次のコマンドを実行します。この例では、ローカルで待ち受けている7890と9090だけを確認するため、リモート側の同じポートへの通常の接続は混在しません。権限不足やプロセス情報の欠落がある場合は、管理者としてターミナルを起動してください。
Get-NetTCPConnection -State Listen -LocalPort 7890,9090 -ErrorAction SilentlyContinue |
Select-Object LocalAddress, LocalPort, OwningProcess
出力で7890の OwningProcess が 14620 だった場合は、続けてプロセス名、実行ファイルのパス、起動引数を確認します。14620は説明用のPIDです。実際には、端末で確認したPIDを使ってください。
Get-Process -Id 14620 | Select-Object Id, ProcessName, Path
Get-CimInstance Win32_Process -Filter "ProcessId = 14620" |
Select-Object ProcessId, ExecutablePath, CommandLine
手順2:コアが重複して起動していないか確認
- 以前使っていたプロキシクライアント:まずタスクトレイから終了し、使用するクライアントを起動します。
- 同じクライアントのバックグラウンドサービス:クライアントからコアやサービスを停止してから、通常の方法で終了してください。子プロセスを直接終了すると、自動的に再起動することがあります。
- ほかの開発ツールやサービス:そのプロセスの待受は維持し、Clash側に別の空きポートを設定します。
- 正体がわからないシステムプロセス:まずサービスの所属を確認してください。ポートを空けるために、安易に強制終了しないでください。
コマンドプロンプトから次のコマンドを実行する方法もあります。ただし、findstr :7890 ではリモートアドレスや78900などの類似ポートまで一致する場合があります。「ローカルアドレス」のポートが正確に7890で、状態が LISTENING であることを確認してください。
netstat -ano -p tcp | findstr :7890
tasklist /FI "PID eq 14620"
ログにUDPのバインド失敗が明記されている場合は、Get-NetUDPEndpoint -LocalPort 7890 で該当する使用状況を確認します。TCPとUDPは別々のポート空間を使うため、番号が同じというだけで競合とは判断できません。
macOS・Linux:待受アドレスとサービスの起動元を確認
macOSでは lsof でTCPの待受を確認できます。Linuxでは ss でソケットとプロセスを確認できます。次のコマンドは状態を表示するだけで、サービスは停止しません。何も表示されない場合は、起動失敗後にクライアントが終了していないかも確認してください。
sudo lsof -nP -iTCP:7890 -sTCP:LISTEN
sudo lsof -nP -iTCP:9090 -sTCP:LISTEN
sudo ss -ltnp 'sport = :7890'
sudo ss -ltnp 'sport = :9090'
ps -p 14620 -o pid,ppid,user,args
待受アドレスを確認してください。127.0.0.1:7890 はIPv4のループバックアドレス、0.0.0.0:7890 はすべてのIPv4インターフェースでの待受を表します。通常、後者は別のプログラムが同じポートを特定のIPv4アドレスにバインドする際にも影響します。[::]:7890 はIPv6に関係し、IPv4接続も受け付けるかどうかはシステムやソケットの設定によります。
プロセスがsystemdなどのサービスマネージャーから起動している場合は、該当サービス経由で停止するか設定を変更してください。kill を実行するだけでは、サービスマネージャーがすぐにプロセスを再起動し、「終了したのにまたポートが使用中になる」ことがあります。ホスト側でコンテナのポート転送プロセスが見つかった場合は、コンテナ内部だけでなく、コンテナのポートマッピングも確認してください。
mixed-portを変更する:空き状況を確認してから設定を保存
元のポートをほかのプログラム用に空けておく必要がある場合は、プロキシの混合ポートを7890から17890に変更できます。17890はこの記事の例です。まず前述のコマンドで空いていることを確認してください。結果が何も表示されなくても、確認時点で該当する待受が見つからなかったというだけです。最終的には再起動後のバインド結果で判断してください。
GUIクライアントとYAMLファイルの設定箇所
- クライアントの設定で「ポート」「混合ポート」「Mixed Port」を探します。検索欄があれば
mixed-portで検索してください。 - クライアントに全体のポート設定がある場合は、まずその設定箇所を変更してください。メニューの場所はクライアントごとに異なるため、特定バージョンの「設定」手順を共通の操作方法として扱わないでください。
- mihomoを直接実行している場合は、起動引数
-fで指定した設定ファイルを編集します。サービス経由で起動している場合は、サービスが実際に使っている起動引数と作業ディレクトリも確認してください。 - クライアントがサブスクリプションから実行用設定を生成する場合は、クライアントが対応する永続的な上書き設定やマージ設定を使ってください。サブスクリプションの更新でポート設定が元に戻るのを防げます。
mixed-port: 17890
allow-lan: false
external-controller: 127.0.0.1:9090
この3項目だけでサブスクリプション全体を上書きしないでください。元の設定の該当箇所を変更し、既存のプロキシ、グループ、ルール、DNS、認証設定は残します。mixed-port はトップレベルの項目であり、proxies や proxy-groups の中にインデントしてはいけません。同じマッピング内に同じキーを重複して記述することも避けてください。
設定に port: 7890 や socks-port: 7890 もある場合、混合ポートだけを変更しても旧ポートで待ち受けようとすることがあります。必要に応じて各項目を個別に変更するか、独立した待受を無効にし、複数の入口に同じ競合アドレスとTCPポートを設定しないようにしてください。
external-controllerを変更する:パネルの接続先も更新
エラーが9090を示している場合、混合ポートは17890のままにして、空いていることを確認した19090へコントロールAPIを移せます。コントロールAPIはブラウザーの通常のプロキシ通信には使われません。システムプロキシのポートまで19090に変更しないでください。
mixed-port: 17890
allow-lan: false
external-controller: 127.0.0.1:19090
既存の設定に secret がある場合はそのまま残し、外部パネルにも同じキーを設定してください。独立したパネルを使う場合は、APIアドレスを http://127.0.0.1:19090 に合わせます。デスクトップクライアントによってはコントロールポートやキーを自動管理しています。生成されたファイルを手動で変更すると、画面からコアに接続できなくなることがあるため、その場合はクライアントが提供する設定画面から変更してください。
- プロキシポートは使えるのにパネルが接続できない場合は、コントロールアドレス、キー、クライアントが旧ポートに接続していないかを確認してください。
- パネルには状態が表示されるのにブラウザーで接続できない場合は、混合ポートとアプリのプロキシ設定を確認してください。パネルが使えるだけで、プロキシの入口も正常とは限りません。
- リモートからパネルにアクセスする場合は、待受アドレス、アクセス制御、ファイアウォールルールを別途設計してください。競合を解消するためだけに、すべてのインターフェースで公開してはいけません。
allow-lan: false はプロキシ入口へのLANアクセスを制限する設定であり、コントロールAPIのバインドアドレスや認証の代わりにはなりません。コントロールAPIを端末内だけで使う場合は、ループバックアドレスに設定するのが簡潔で確実です。
ポート変更後にシステムプロキシとアプリの設定も更新
ポートの移行には、コアが新しいポートで待ち受けることと、接続する側も新しいポートを使うことの2つが必要です。前者だけを済ませてブラウザーが旧ポートの7890に接続し続けると、「コアは正常に動いているのにWebページが開けない」という状態になります。
| 接続元 | 確認する設定 |
|---|---|
| Windowsのシステムプロキシ | 「設定」→「ネットワークとインターネット」→「プロキシ」にある手動プロキシのアドレスとポート |
| macOSのシステムプロキシ | 「システム設定」→「ネットワーク」→ 使用中のネットワークサービス →「詳細」→「プロキシ」 |
| ブラウザーのプロキシ拡張機能 | 拡張機能に手動で保存したHTTPまたはSOCKSのアドレスとポート |
| ターミナルとスクリプト | HTTP_PROXY、HTTPS_PROXY、ALL_PROXY およびコマンドライン引数 |
| 独立したコントロールパネル | 混合プロキシポートではなく、コントロールAPIのアドレス、ポート、キー |
システム設定の手順はOSのバージョンによって異なることがあります。クライアントがシステムプロキシを管理している場合は、クライアントの「システムプロキシ」設定をいったんオフにしてからオンにし、新しいプロキシポートを反映してください。操作後は実際の設定値も確認します。ブラウザーやIDE、ダウンロードツールで個別に設定したプロキシは、システム設定に自動で追従するとは限りません。
ターミナルでプロキシを明示すると、古い環境変数を引き継がずに済みます。次の例では、新しい混合ポートにHTTPプロキシで接続します。Windowsでは curl.exe、macOSとLinuxでは curl を使えます。
curl.exe --proxy http://127.0.0.1:17890 --noproxy "" --connect-timeout 5 --max-time 15 -I https://example.com/
ここでの5秒は接続タイムアウト、15秒はリクエスト全体の制限時間であり、通信速度の目安ではありません。テスト先には、現在のネットワークとルールでアクセスできるサイトを選んでください。HTTPステータスコードは必ずしも200である必要はありません。レスポンスとログを照らし合わせ、リクエストがプロキシを通ったか確認してください。TLS証明書エラー、接続先からの拒否、ローカル接続の拒否は、それぞれ異なる段階で起きる問題です。
使用中のプロセスが見つからないのにバインドに失敗する場合
権限エラーはポート競合とは別の問題
Windowsの access permissions やUnix系システムの permission denied は、通常のポート競合と同じものとして扱わないでください。Windowsでは、特定のポート範囲がシステムや仮想化機能によって予約されていることがあります。次の読み取り専用コマンドで確認し、使用予定のポートが予約範囲に含まれる場合は、予約されていない空きポートを選んでください。
netsh interface ipv4 show excludedportrange protocol=tcp
netsh interface ipv6 show excludedportrange protocol=tcp
7890を使うために、システムの予約範囲をそのまま削除しないでください。Linuxでは通常、1024未満のポートで待ち受けるには相応の権限やケーパビリティが必要です。一方、7890と17890は低位ポートではありません。セキュリティポリシーやサービスのログも確認し、原因を特定してください。
古いプロセスが自動再起動する、または編集した設定ファイルが違う
使用中プロセスのPIDが何度も変わる場合は、スタートアップ設定、バックグラウンドサービス、別クライアントの自動復旧機能を確認してください。PIDが変わらず、ログにも旧ポートが表示される場合は、起動引数、設定のマージ順、クライアントの全体ポート上書きを確認します。サブスクリプションのファイルで7890を書き換えても、最終的な実行設定まで変わるとは限りません。
エラーが cannot assign requested address の場合は、バインド先のIPアドレスが現在も端末に割り当てられているか確認してください。ネットワークを切り替えた後は、以前のLANアドレスが使えなくなっていることがあります。これは別のプログラムがポートを占有している問題とは異なります。
修正の確認:待受・リクエスト・再起動の3段階
- 待受プロセスを確認:17890とコントロールポートを再度確認し、ポートが存在するだけでなく、プロセスのパスが使用するクライアントまたはコアのものか照合します。
- リクエストの経路を確認:プロキシを明示したコマンドでリクエストを送り、クライアントの接続履歴に該当する通信が表示されるか確認します。ルールの適用結果と接続先のプロキシも確認してください。
- 設定の永続性を確認:クライアントを再起動し、サブスクリプションも更新して、ポートが旧設定に戻らないことを確認します。システムプロキシと外部パネルが再接続できることも確認してください。
プロキシを明示したリクエストは成功するのに通常のブラウザーで接続できない場合は、システムプロキシ、ブラウザー拡張機能、アプリ独自の設定を引き続き確認してください。リクエストがコアに届いてから名前解決や接続に失敗する場合は、DNS、ノード、ルールを調べます。ローカルの待受ポートを何度も変更する必要はありません。
ポート競合は、バインドエラー全体を確認し、プロトコルとアドレスを指定して使用中のプロセスを特定したうえで、重複サービスを停止するか待受ポートを変更し、すべての接続元の設定を更新する順に対処します。必要なバックグラウンドサービスを維持しながら、「ポートを変えたのにアプリは古いアドレスへ接続している」という二次的なトラブルも防げます。