먼저 로그 확인: 7890은 프록시 포트, 9090은 제어 API 포트

Clash 또는 mihomo 커널을 사용하는 클라이언트가 시작되지 않으면 먼저 커널 로그를 펼쳐 listen, bind, 구체적인 주소가 포함된 오류를 찾으세요. address already in use가 표시되면 대개 해당 주소와 포트를 이미 다른 프로세스가 사용 중이라는 뜻입니다. Windows에서는 “각 소켓 주소는 일반적으로 한 번만 사용할 수 있습니다”라는 메시지가 나타나기도 합니다. 먼저 포트, 바인딩 주소, 프로토콜을 기록한 다음 프로세스를 종료할지 설정을 변경할지 결정하세요.

7890과 9090은 흔히 쓰이는 설정값일 뿐, 모든 클라이언트가 이 포트를 고정으로 사용하는 것은 아닙니다. 실제 포트는 현재 적용된 설정과 시작 로그를 기준으로 확인하세요. 두 포트의 용도는 다르므로 오류가 하나 떴다고 모든 포트를 한꺼번에 바꾸면 안 됩니다.

설정 항목예시 값용도 및 영향
mixed-port7890하나의 포트에서 HTTP 프록시와 SOCKS5 연결을 모두 받습니다. 브라우저, 터미널, 시스템 프록시에서 사용할 수 있습니다.
external-controller127.0.0.1:9090클라이언트나 웹 패널에서 상태를 확인하고 정책을 전환할 수 있도록 제어 API를 제공합니다. 웹 프록시 포트는 아닙니다.
port7892별도의 HTTP 프록시 포트입니다. 이 항목을 활성화한 경우에만 확인하면 됩니다.
socks-port7893별도의 SOCKS 포트입니다. mixed-port만 변경했다고 이 포트도 바뀌는 것은 아닙니다.

Windows: netstat와 PowerShell로 포트 점유 프로세스 찾기

1단계: 숫자만 검색하지 말고 리스닝 상태 확인하기

PowerShell을 열고 아래 명령 두 개를 실행하세요. 출력된 로컬 주소가 대상 포트로 끝나는지 확인하고, 상태는 LISTENING이어야 합니다. 마지막 열에는 프로세스 ID인 PID가 표시됩니다. 7890만 검색하면 원격 주소나 다른 포트에 포함된 숫자까지 검색될 수 있으니 전체 열을 확인해야 합니다.

netstat -ano -p tcp | findstr ":7890"
netstat -ano -p tcp | findstr ":9090"

PowerShell에서 로컬 포트를 기준으로 리스닝 프로세스만 필터링하면 이미 연결된 항목을 포트 충돌로 잘못 판단하는 일을 피할 수 있습니다.

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

127.0.0.1:7890은 IPv4 루프백 주소에서 리스닝한다는 뜻이고, 0.0.0.0:7890은 모든 IPv4 인터페이스에서 리스닝한다는 뜻입니다. 후자의 경우 보통 다른 프로그램이 같은 컴퓨터에서 동일한 포트를 다시 바인딩할 수 없습니다. IPv6의 [::]:7890이 IPv4에도 영향을 주는지는 소켓 설정에 따라 다르므로, 점검할 때 IPv6 출력도 놓치지 마세요.

2단계: 프로그램 경로를 확인한 뒤 중복 실행 종료하기

아래에서는 PID 1234를 조회하는 예를 들었습니다. 실행할 때는 앞서 확인한 실제 PID로 바꾸세요. PID는 프로세스를 다시 시작할 때 달라지므로 예시 값을 그대로 복사해 프로세스를 종료하면 안 됩니다.

tasklist /FI "PID eq 1234"
Get-Process -Id 1234 | Select-Object Id,ProcessName,Path
  • 다른 프록시 클라이언트: 시스템 트레이에서 해당 클라이언트를 종료하고, 시작 프로그램 등록이나 커널 자동 실행도 해제한 다음 계속 사용할 클라이언트를 실행하세요.
  • 같은 클라이언트의 백그라운드 커널: 창을 닫아도 시스템 트레이로 최소화되기만 할 수 있습니다. 트레이 메뉴에서 완전히 종료한 다음 포트 리스닝이 사라졌는지 확인하세요.
  • 서비스로 관리되는 프로세스: 어떤 서비스인지 먼저 확인한 뒤 해당 클라이언트나 서비스 관리 도구에서 중지하세요. 하위 프로세스만 종료하면 감시 프로세스가 곧바로 다시 실행할 수 있습니다.
  • 다른 개발 도구: 사용 중인 서비스가 해당 포트를 점유하고 있다면 서비스는 그대로 두고 Clash 포트를 바꾸는 편이 낫습니다.

프로그램 경로를 조회할 때 권한 오류가 나면 관리자 권한으로 터미널을 다시 여세요. 이름이 비슷하다는 이유만으로 시스템 서비스를 종료하거나, 관리자 권한 실행이 모든 바인딩 충돌을 해결한다고 생각해서는 안 됩니다. 관리자 권한으로 실행해도 다른 프로세스가 이미 사용 중인 포트가 자동으로 비워지지는 않습니다.

macOS·Linux: lsof 또는 ss로 리스닝 프로세스 확인하기

macOS에서는 터미널에서 lsof를 사용할 수 있습니다. Linux에서도 해당 도구가 설치되어 있다면 같은 명령을 실행하면 됩니다. -nP는 주소와 포트를 숫자로 표시하고, -sTCP:LISTEN은 TCP 리스닝 항목만 보여 주므로 PID와 프로세스 이름을 바로 확인할 수 있습니다.

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

Linux에서는 ss로 두 포트를 한 번에 조회할 수도 있습니다. 일반 사용자 권한으로 프로세스 정보가 보이지 않으면 권한을 높여 확인하세요. 커널을 계속 재시작하는 것부터 시도하지 마세요.

sudo ss -ltnp '( sport = :7890 or sport = :9090 )'

데스크톱 클라이언트와 systemd 서비스를 같은 포트에서 중복 실행하지 마세요

Linux에서 흔히 발생하는 충돌은 mihomo를 백그라운드 서비스로 설정한 뒤 커널이 포함된 데스크톱 클라이언트도 실행하는 경우입니다. 두 프로그램이 서로 다른 설정을 읽으면서 모두 7890을 리스닝하려고 할 수 있습니다. 배포 시 사용한 서비스 이름이 실제로 mihomo.service라면 먼저 상태와 로그를 확인하세요.

systemctl status mihomo --no-pager
journalctl -u mihomo -n 50 --no-pager

데스크톱 클라이언트로 전환하기로 했다면 sudo systemctl stop mihomo를 실행해 서비스를 중지할 수 있습니다. 부팅 시 자동 시작을 끌지는 실제 배포 방식에 맞춰 결정하세요. 서비스 이름이 다르면 실제 이름을 사용해야 합니다. macOS에서는 메뉴 막대에서 기존 클라이언트를 종료하는 것이 우선입니다. 커널이 백그라운드 작업으로 실행 중이라면 기존 관리 방식으로 중지해야 합니다. 그렇지 않으면 프로세스를 한 번 종료해도 다시 실행될 수 있습니다.

mixed-port 변경: 설정과 프록시 사용처를 함께 업데이트하기

먼저 백업하고 최종 설정을 생성하는 주체 확인하기

GUI 클라이언트는 설정 화면, 설정 덮어쓰기, 설정 병합 기능 등을 통해 커널 실행 파일을 생성할 수 있습니다. 캐시된 구독 YAML을 직접 수정하면 구독을 업데이트하거나 클라이언트를 다시 시작할 때 변경 내용이 사라질 수 있습니다. 먼저 설정을 백업한 뒤 현재 클라이언트에서 제공하는 지속 설정 메뉴를 통해 포트를 변경하세요. 메뉴 이름은 클라이언트마다 다르므로 특정 앱의 메뉴 경로를 모든 프로그램에 그대로 적용하지 마세요.

  1. 새로 사용할 포트(예: 7891과 9091)를 조회해 이미 리스닝 중인 서비스가 없는지 확인하세요.
  2. 화면에 ‘혼합 포트’ 항목이 있으면 값을 7891로 바꾸고 저장하세요. 직접 배포한 경우 실제로 읽히는 설정 파일을 수정하면 됩니다.
  3. 클라이언트 안내에 따라 설정을 다시 불러오거나 커널을 재시작한 다음, 로그에서 실제 리스닝 주소를 확인하세요.
  4. 시스템 프록시, 브라우저 프록시 확장 프로그램, 명령줄 환경 변수와 직접 설정한 프록시 주소도 업데이트하세요.

아래 내용은 기존 설정의 최상위 항목에 병합할 설정 조각이며, 단독으로 가져와 사용할 수 있는 완성된 구독 파일이 아닙니다. 기존 노드, 정책 그룹, 규칙은 유지하세요. 같은 이름의 키가 이미 있다면 중복으로 추가하지 말고 기존 값을 수정해야 합니다. 새 포트 두 개는 예시이므로 사용 전에 비어 있는지 확인하세요.

config.yaml · 포트 설정 예시
mixed-port: 7891
allow-lan: false
external-controller: 127.0.0.1:9091

독립 항목인 port, socks-port, redir-port, tproxy-port가 활성화되어 있는지도 확인하세요. 오류가 발생한 포트 항목만 처리하면 됩니다. 별도로 리스닝해야 하는 여러 항목에 같은 주소와 포트를 지정하지 마세요.

시스템 프록시와 터미널 환경 변수 각각 확인하기

Windows 11에서는 ‘설정’ → ‘네트워크 및 인터넷’ → ‘프록시’ → ‘수동 프록시 설정’에서 주소와 포트를 확인할 수 있습니다. macOS에서는 ‘시스템 설정’ → ‘네트워크’ → 현재 네트워크 서비스 → ‘세부사항’ → ‘프록시’에서 확인하세요. 클라이언트가 시스템 프록시를 자동 설정한다면 클라이언트에서 설정을 다시 적용하는 것이 좋습니다. 수동으로 입력한 값이 나중에 덮어써지는 일을 막을 수 있습니다.

터미널 환경 변수는 시스템 프록시를 바꿔도 자동으로 업데이트되지 않습니다. 아래 설정은 현재 터미널 세션에만 적용되므로 새 포트를 시험할 때 사용할 수 있습니다. 시작 스크립트나 개발 도구 설정에 7890이 남아 있다면 해당 항목도 별도로 수정하세요.

PowerShell · 현재 세션
$env:HTTP_PROXY = "http://127.0.0.1:7891"
$env:HTTPS_PROXY = "http://127.0.0.1:7891"
macOS / Linux · 현재 셸
export http_proxy=http://127.0.0.1:7891
export https_proxy=http://127.0.0.1:7891

HTTPS_PROXY라는 변수 이름은 HTTPS 대상에 사용할 프록시 설정을 뜻할 뿐, 로컬 프록시 주소를 반드시 https://로 적어야 한다는 의미는 아닙니다. 여기서는 로컬 HTTP 프록시 포트에 연결하므로 http://127.0.0.1:7891을 사용합니다. ALL_PROXY나 앱별 프록시 설정도 있다면 함께 확인하세요. 대소문자 변수와 우선순위는 도구마다 다르게 처리될 수 있습니다.

9090 포트 변경: 제어 패널 주소와 인증 설정도 업데이트하기

충돌이 발생한 항목이 external-controller라면 값을 127.0.0.1:9091로 바꾼 뒤 웹 패널의 백엔드 주소도 http://127.0.0.1:9091로 변경하세요. 기존 secret은 유지하고 패널에 일치하는 인증 정보를 입력해야 합니다. 일부 데스크톱 클라이언트는 제어 인터페이스와 인증 값을 자체적으로 관리하므로, 프런트엔드와 커널 설정이 달라지지 않도록 클라이언트 설정에서 변경하는 것이 좋습니다.

  • 프록시는 되지만 패널 연결이 끊김: 패널이 아직 이전 포트인 9090에 연결 중인지 확인한 뒤 인증 정보와 클라이언트 로그를 점검하세요.
  • API가 401을 반환함: 보통 HTTP 서비스는 응답했지만 요청에 유효한 인증 정보가 없다는 뜻입니다. 포트가 여전히 사용 중이라는 의미는 아닙니다.
  • 연결이 거부됨: 대개 해당 시점에 주소에서 연결을 받을 수 있는 프로세스가 리스닝하지 않았다는 뜻입니다. 커널 실행 여부와 바인딩 주소를 확인하세요.

변경 후 확인 방법: 리스닝, 프록시, 제어 API를 각각 테스트하기

1. 새 포트를 예상한 프로세스가 리스닝하는지 확인

앞서 사용한 조회 명령에서 포트를 7891과 9091로 바꿔 다시 실행하세요. 리스닝 여부뿐 아니라 PID가 현재 사용하려는 커널의 것인지도 확인해야 합니다. 이전 프로세스가 종료되지 않은 상태에서 브라우저가 계속 이전 포트를 사용하면 문제가 해결된 것처럼 보일 수 있습니다.

2. 프록시를 명시적으로 지정해 이전 시스템 프록시 설정의 영향 배제하기

Windows PowerShell에서는 curl이 다른 명령으로 해석되는 환경이 있으므로 curl.exe를 사용하세요. macOS와 Linux에서는 curl을 사용하면 됩니다. 아래 명령은 새 포트에 직접 연결하며, --noproxy ""는 이번 요청에서 우회 목록을 비웁니다. 예시 대상은 연결 확인용이며 속도 측정 기준이 아닙니다.

curl.exe --noproxy "" --proxy http://127.0.0.1:7891 --connect-timeout 5 --max-time 15 -I https://example.com

대상 사이트의 응답을 받았다면 로컬 프록시 포트가 적어도 이번 요청을 처리할 수 있다는 뜻입니다. 다만 규칙에 따라 요청이 DIRECT로 나갔을 수도 있으므로, 명령이 성공했다는 이유만으로 원격 노드가 작동한다고 단정할 수는 없습니다. 클라이언트 연결 기록에서 도메인에 적용된 규칙과 정책 그룹, 실제 출구를 확인하세요.

3. 제어 API 별도로 확인하기

curl.exe --connect-timeout 5 --max-time 10 -i http://127.0.0.1:9091/version

macOS와 Linux에서는 명령의 curl.exe를 curl로 바꾸세요. 인증을 사용하지 않으면 정상 API에서 버전 정보가 반환될 수 있습니다. 인증을 사용 중이라면 인증 정보를 포함하지 않은 요청은 401을 반환할 수 있습니다. 테스트를 위해 기존 키를 삭제하지 말고, 실제 키가 포함된 전체 명령이나 로그 화면을 공개하지 마세요.

리스닝 중인 프로세스가 없는데도 바인딩할 수 없음: 예약 포트와 오류 유형 확인하기

로그에 permission denied, access permissions, cannot assign requested address가 표시되면 일반적인 포트 점유 문제로 다뤄서는 안 됩니다. Windows의 포트 제외 범위, 존재하지 않는 로컬 주소에 대한 바인딩, 보안 소프트웨어의 제한 등은 서로 다른 유형의 바인딩 오류를 일으킬 수 있습니다.

Windows에서는 아래 명령으로 TCP 제외 범위를 확인할 수 있습니다. 대상 포트가 해당 범위에 포함되면 범위 밖의 빈 포트를 선택하고 가상화 또는 네트워크 구성 요소 설정을 확인하세요. 시스템이 관리하는 제외 항목을 직접 삭제하지 마세요.

netsh interface ipv4 show excludedportrange protocol=tcp
netsh interface ipv6 show excludedportrange protocol=tcp

오류가 UDP 리스닝을 가리킨다면 앞서 TCP만 조회한 명령으로는 원인을 전부 확인할 수 없습니다. Windows에서는 Get-NetUDPEndpoint -LocalPort 7890, Linux에서는 sudo ss -lunp, macOS에서는 sudo lsof -nP -iUDP:7890를 실행하세요. TCP와 UDP는 서로 다른 포트 공간이므로 로그에서 실패한 프로토콜에 맞춰 각각 확인해야 합니다.

마지막으로 잘못된 설정 파일을 수정한 것은 아닌지 확인하세요. 서비스로 실행되는 mihomo는 시작 매개변수에서 다른 설정 디렉터리를 지정할 수 있고, 데스크톱 클라이언트는 실행 중에 설정 파일을 생성할 수도 있습니다. 재시작 후에도 이전 포트가 리스닝한다면 숫자를 계속 바꾸기보다 설정 출처와 덮어쓰기 순서를 먼저 확인하세요.

포트 충돌 해결 체크리스트

  1. 로그 확인: 실패한 주소와 포트, TCP 또는 UDP 여부, 전체 오류 유형을 기록하세요.
  2. 점유 프로세스 확인: netstat, lsof 또는 ss로 리스닝 PID를 찾고 프로그램 경로와 실행 방식을 확인하세요.
  3. 해결 방법 선택: 더 이상 필요하지 않은 중복 실행을 중지하거나 함께 사용해야 하는 서비스에 서로 다른 포트를 지정하세요.
  4. 지속 설정 변경: 실제로 적용되는 mixed-port 또는 external-controller를 수정해 구독 업데이트 후 이전 값으로 돌아가지 않도록 하세요.
  5. 사용처 동기화: 프록시 포트는 시스템 프록시와 앱 설정을, 제어 포트는 패널 백엔드 주소와 인증 정보를 함께 업데이트하세요.
  6. 단계별 확인: 먼저 리스닝을 확인하고, 프록시를 직접 지정해 테스트한 다음 제어 API와 규칙 적용 결과를 확인하세요.

TUN 모드는 가상 네트워크 인터페이스로 트래픽을 처리하므로 로컬 프록시 리스닝과는 다른 계층에서 작동합니다. TUN을 켜도 점유 중인 7890이나 9090이 자동으로 해제되지는 않습니다. 먼저 로그에 명시된 리스닝 오류를 해결한 뒤 TUN 권한, 라우팅, DNS를 점검하면 여러 문제가 뒤섞이는 일을 줄일 수 있습니다.