先区分代理监听端口与控制端口

启动 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

这两行对应不同功能:7890 常被用作代理入口,9090 常被用作控制接口,但它们只是常见配置值,并非所有客户端的固定端口。应以当前设置和启动日志为准。

字段用途冲突后的典型表现
mixed-port同一端口接收 HTTP 与 SOCKS 代理连接应用连接本地代理失败
port独立的 HTTP 代理监听端口使用该 HTTP 入口的请求失败
socks-port独立的 SOCKS 代理监听端口使用该 SOCKS 入口的请求失败
external-controller供客户端或面板调用的控制 API 地址面板无法连接、读取状态或切换策略

Windows:用监听端口找到占用进程

第一步:查询 TCP 监听与 PID

打开 PowerShell,执行下面的命令。示例只查询本机处于监听状态的 7890、9090,不会把访问远端同端口的普通连接混在一起。若权限不足或进程信息不完整,再以管理员身份运行终端。

PowerShell
Get-NetTCPConnection -State Listen -LocalPort 7890,9090 -ErrorAction SilentlyContinue |
  Select-Object LocalAddress, LocalPort, OwningProcess

假设输出中 7890 对应的 OwningProcess 是 14620,再查询进程名称、可执行文件路径和启动参数。这里的 14620 仅用于演示,执行时应使用本机实际查到的 PID。

PowerShell · 进程详情
Get-Process -Id 14620 | Select-Object Id, ProcessName, Path
Get-CimInstance Win32_Process -Filter "ProcessId = 14620" |
  Select-Object ProcessId, ExecutablePath, CommandLine

第二步:判断是否是重复启动的内核

  • 旧代理客户端:优先从托盘菜单退出旧客户端,再启动准备使用的客户端。
  • 同一客户端的后台服务:先在该客户端中停止内核或服务,再正常退出;直接结束子进程可能触发自动拉起。
  • 其他开发工具或服务:保留其监听,给 Clash 选择另一个空闲端口。
  • 无法识别的系统进程:先核实服务归属,不要为了释放端口直接强制结束。

也可以在命令提示符中执行以下命令。注意 findstr :7890 可能匹配远端地址或 78900 等相似端口;必须核对“本地地址”的端口恰好是 7890,并确认状态为 LISTENING。

Windows 命令提示符
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 查看套接字及进程。以下命令只读取状态,不会停止任何服务。输出为空时,还应确认客户端是否已因启动失败退出。

macOS
sudo lsof -nP -iTCP:7890 -sTCP:LISTEN
sudo lsof -nP -iTCP:9090 -sTCP:LISTEN
Linux
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 仅是本文示例,必须先用前面的命令查询它是否空闲;没有输出只能说明查询时未发现该类监听,最终仍以重新启动后的绑定结果为准。

图形客户端与 YAML 文件的修改入口

  1. 在客户端设置中查找“端口”“混合端口”或“Mixed Port”。若有搜索框,可直接搜索 mixed-port。
  2. 客户端提供全局端口设置时,优先修改该入口。不同客户端的菜单位置不同,不应把某一个版本的「设置」路径当作通用路径。
  3. 直接运行 mihomo 时,修改启动参数 -f 指向的配置文件;通过服务启动时,还要检查服务实际使用的参数和工作目录。
  4. 订阅由客户端生成运行配置时,使用客户端支持的持久覆写或合并配置机制,避免订阅更新后把端口改回去。
config.yaml · 仅展示需要调整的顶层字段
mixed-port: 17890
allow-lan: false
external-controller: 127.0.0.1:9090

不要用这三个字段覆盖整份订阅。应在原配置对应位置修改,并保留已有的代理、策略组、规则、DNS 和鉴权配置。mixed-port 是顶层字段,不能缩进到 proxies 或 proxy-groups 内;同一个映射中也不要重复写两次同名键。

配置中若同时存在 port: 7890 或 socks-port: 7890,仅修改混合端口可能仍会尝试监听旧端口。应按实际需要分别调整或关闭独立监听入口,避免把多个入口设置成相同的冲突地址与 TCP 端口。

修改 external-controller:同步面板连接地址

当报错明确指向 9090,可以保留混合端口 17890,把控制接口迁移到已确认空闲的 19090。控制接口不承载浏览器的普通代理请求,因此不能把系统代理端口也顺手改成 19090。

config.yaml · 控制接口迁移示例
mixed-port: 17890
allow-lan: false
external-controller: 127.0.0.1:19090

现有配置若设置了 secret,应保留它,并在外部面板中使用相同密钥。使用独立面板时,将 API 地址同步为 http://127.0.0.1:19090。有些桌面客户端会自行管理控制端口和密钥,手工改生成文件反而可能让界面与内核失联,此时应通过客户端支持的设置修改。

  • 代理端口可用、面板断开:优先检查控制地址、密钥,以及客户端是否仍连接旧端口。
  • 面板能显示状态、浏览器失败:继续检查混合端口和应用代理设置,不要据此认定代理入口已正常。
  • 远程面板需要访问:必须另行设计监听地址、访问控制和防火墙规则,不能仅为消除冲突就开放到全部接口。

allow-lan: false 用于限制代理入口的局域网访问,不代替控制 API 的地址绑定和鉴权。只在本机使用控制接口时,保持回环地址是更直接的边界设置。

端口改完后:同步系统代理与应用设置

端口迁移包含两个动作:内核在新端口监听,调用方也连接新端口。只完成前者,浏览器仍访问旧的 7890,就会出现“内核运行正常但网页打不开”。

调用方需要核对的设置
Windows 系统代理「设置」→「网络和 Internet」→「代理」中的手动代理地址与端口
macOS 系统代理「系统设置」→「网络」→ 当前网络服务 →「详细信息」→「代理」
浏览器代理扩展扩展内手动保存的 HTTP 或 SOCKS 地址与端口
终端与脚本HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 和命令行参数
独立控制面板控制 API 地址、端口与密钥,而非混合代理端口

系统设置路径可能随操作系统版本调整。由客户端管理系统代理时,通常应先关闭再开启客户端中的“系统代理”开关,让它写入新的代理端口;操作后仍需核对实际值。单独设置代理的浏览器、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 中某些端口范围可能被系统或虚拟化组件保留,可用下列只读命令检查;若选定端口落在保留范围内,优先换一个未被保留的空闲端口。

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 是否确实属于当前设备。例如切换网络后,旧的局域网地址可能已经不存在;这与另一个程序抢占端口不是同一个问题。

修复验收:监听、请求、重启三步确认

  1. 确认监听归属:重新查询 17890 和控制端口,核对进程路径确实属于准备使用的客户端或内核,而不是只看端口存在。
  2. 确认请求路径:使用显式代理命令发起请求,在客户端连接记录中观察是否出现对应连接,并检查规则命中与出口策略。
  3. 确认配置持久:重启客户端,再更新一次订阅,核对端口没有恢复为旧值,系统代理和外部面板也能重新连接。

如果显式代理请求成功,而普通浏览器仍然失败,应继续排查系统代理、浏览器扩展和应用自己的设置。如果请求已经进入内核,却在解析或连接远端时失败,则转向 DNS、节点和规则排查,不必继续反复更换本地监听端口。

端口冲突的处理顺序可以归纳为:读取完整绑定错误,按协议和地址查占用者,选择停止重复服务或迁移监听,然后同步所有调用方。这样既能保留必要的后台服务,也能避免“端口改了,应用还连旧地址”的第二轮故障。