먼저 리스닝 실패 원인을 확인한 뒤 포트 변경 여부를 결정하세요

Clash에서 7890 포트가 사용 중이라는 메시지가 표시되면, 먼저 어떤 프로세스가 해당 포트를 리스닝 중인지 확인하세요. 중복 실행된 인스턴스를 종료하거나 리스닝 포트를 변경하면 됩니다. 시스템 프록시의 포트 번호만 바꿔서는 커널의 실제 리스닝 포트가 바뀌지 않습니다. 반대로 설정 파일만 수정하고 시스템 프록시를 그대로 두면 브라우저는 계속 이전 포트에 연결합니다.

이 문서에서는 로컬 프록시 주소 127.0.0.1:7890를 기준으로 설명하고, 변경 예시로 17890을 사용합니다. 17890이 항상 비어 있는 것은 아니므로 사용 전에 점유 여부를 확인하세요. Clash, Clash Meta(현재 mihomo)와 그래픽 클라이언트는 기본 포트가 서로 다를 수 있습니다. 현재 적용된 설정과 시작 로그를 기준으로 확인하세요.

로그에 표시된 오류 유형에 따라 대응 방법이 다릅니다

로그 또는 증상우선 확인할 항목
address already in use이미 실행 중인 리스닝 프로세스, 중복 실행된 커널 또는 같은 주소와 포트를 사용하는 여러 인바운드 설정
Only one usage of each socket addressWindows에서 흔히 발생하는 주소 사용 오류입니다. 먼저 로컬 리스닝 포트와 PID를 확인하세요.
permission denied 또는 access permissions권한, 보안 소프트웨어 또는 시스템 예약 포트 범위를 확인하세요. 다른 프로그램이 포트를 점유했다고 단정해서는 안 됩니다.
브라우저에서 프록시 연결에 실패함프록시 주소가 올바른지, 커널이 실행 중인지 확인하세요. 이 증상만으로 포트 충돌이라고 판단할 수는 없습니다.

클라이언트 로그를 열어 오류가 발생한 주소, 포트, 프로토콜을 확인하세요. 로그에 9090이 표시된다면 7890이 아니라 컨트롤 인터페이스를 점검해야 합니다. 설정에서 mixed-port를 사용하지 않는다면 실제로 사용하는 port 또는 socks-port를 확인하세요.

Windows: netstat로 포트를 점유한 프로세스 찾기

터미널에서 먼저 TCP 리스닝 상태를 확인하세요. PowerShell 또는 명령 프롬프트를 열고 아래 명령을 실행합니다. 프로세스 정보가 충분히 표시되지 않으면 관리자 권한으로 다시 시도하세요.

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

‘로컬 주소’ 열이 :7890으로 끝나고 상태가 LISTENING인 항목을 찾으세요. ‘외부 주소’에 표시된 7890이나 TIME_WAIT 연결을 리스닝 중인 서비스로 오인하지 마세요. 아래는 형식 예시이며, 현재 기기의 실제 출력이 아닙니다.

  TCP    127.0.0.1:7890    0.0.0.0:0    LISTENING    6420

마지막 열의 6420은 예시 PID입니다. 실제 PID로 바꿔 프로세스 이름을 조회하세요.

tasklist /FI "PID eq 6420"

PowerShell에서 로컬 포트만 정확히 검색하기

문자열 검색 결과가 너무 많다면 아래 명령을 사용하세요. 결과가 없으면 조회 시점에 해당 TCP 포트를 리스닝 중인 프로세스를 찾지 못한 것입니다. 권한 오류나 다른 오류가 발생했다면 먼저 오류를 해결해야 합니다. 오류가 있다는 이유만으로 포트가 비어 있다고 판단해서는 안 됩니다.

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

Get-Process -Id 6420 |
  Select-Object Id, ProcessName, Path
  1. 다른 Clash 클라이언트가 점유 중이라면 트레이 메뉴에서 정상적으로 종료한 뒤 백그라운드 커널도 멈췄는지 확인하세요.
  2. 같은 클라이언트의 이전 커널이 점유 중이라면 클라이언트를 종료한 다음 서비스 모드가 계속 실행 중인지 확인하세요. 클라이언트에서 제공하는 서비스 관리 메뉴로 서비스를 중지해 인스턴스가 반복해서 실행되지 않도록 하세요.
  3. 계속 실행해야 하는 개발 서비스나 다른 프록시 프로그램이 점유 중이라면 해당 프로그램은 기존 포트를 사용하게 두고 Clash에 새 포트를 지정하세요.

macOS 및 Linux: lsof로 리스닝 상태 확인하기

macOS에서는 ‘터미널’에서 lsof를 실행하세요. Linux에 해당 도구가 설치되어 있지 않다면 ss를 사용할 수 있습니다. 아래 명령은 TCP 리스닝만 조회하므로 브라우저가 HTTP 프록시로 연결하는 포트를 우선 확인하기에 적합합니다.

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

-nP는 주소와 포트를 이름으로 변환하지 않도록 합니다. 출력에서 COMMAND는 프로세스 이름, PID는 프로세스 ID, NAME은 리스닝 주소입니다. 데스크톱 클라이언트가 실행한 커널인지 직접 실행한 서비스인지 구분하려면 전체 실행 명령도 확인하세요.

ps -p 6420 -o pid,ppid,command

Linux에서는 다음 명령도 사용할 수 있습니다.

sudo ss -ltnp 'sport = :7890'

127.0.0.1:7890은 IPv4 루프백 주소에서 리스닝한다는 뜻이고, 0.0.0.0:7890은 모든 IPv4 주소에서 리스닝한다는 뜻입니다. 와일드카드 주소의 리스닝은 같은 포트의 루프백 리스닝과 충돌할 수 있습니다. [::]:7890이 표시되면 시스템의 IPv6 듀얼 스택 동작도 고려하세요. IPv4 주소가 아니라는 이유만으로 충돌 가능성을 배제할 수는 없습니다.

필요하면 UDP도 확인하세요

TCP와 UDP는 포트 공간이 서로 독립적입니다. UDP 7890을 사용 중이라고 해서 TCP 7890을 반드시 사용할 수 없는 것은 아닙니다. 다만 관련 UDP 인바운드 기능을 사용 중이라면 로그를 바탕으로 추가 점검이 필요합니다.

# macOS / lsof가 설치된 Linux
sudo lsof -nP -iUDP:7890

# Linux
sudo ss -lunp 'sport = :7890'

프로세스가 어떤 서비스에 속하는지 확인한 뒤 해당 앱의 인터페이스나 서비스 관리자에서 중지하는 것이 좋습니다. 서비스가 자동 재시작되도록 설정되어 있다면 하위 프로세스만 종료해도 다시 실행되어 포트가 금세 점유될 수 있습니다.

방법 1: 클라이언트 설정에서 포트 변경하기

그래픽 클라이언트는 대개 시작할 때 실행용 설정을 생성합니다. 이런 클라이언트에서는 설정 화면에서 포트를 변경하고, 임시로 생성된 파일은 먼저 편집하지 마세요. 메뉴 이름은 클라이언트와 버전에 따라 다르지만 보통 ‘설정’에서 ‘포트’, ‘프록시 포트’ 또는 ‘혼합 포트’를 찾으면 됩니다.

  1. 먼저 앞에서 사용한 명령으로 17890을 확인하세요. 조회 명령의 7890을 17890으로 바꾸면 됩니다.
  2. 현재 포트와 시스템 프록시 사용 여부를 기록하세요. 클라이언트가 계속 시작에 실패한다면 사용할 수 없는 포트로 앱이 연결을 시도하지 않도록 시스템 프록시를 잠시 꺼 두세요.
  3. 클라이언트에서 ‘설정’을 열고 ‘혼합 포트’ 또는 mixed-port로 표시된 항목을 찾아 17890을 입력하세요. ‘외부 컨트롤’, ‘API’ 또는 ‘컨트롤러 포트’를 잘못 변경하지 않도록 주의하세요.
  4. 설정을 저장하고 화면 안내에 따라 설정을 다시 불러오거나 커널을 재시작하세요. 설정 창만 닫으면 변경 사항이 적용되지 않을 수 있습니다.
  5. 로그와 시스템 리스닝 상태를 확인해 대상 커널이 17890을 리스닝하는지 확인한 다음 시스템 프록시를 다시 켜세요.

클라이언트에서 ‘HTTP 포트’와 ‘SOCKS 포트’를 따로 표시한다면 먼저 혼합 포트를 사용 중인지 확인하세요. 세 항목을 모두 17890으로 바꾸지 마세요. 서로 바꿔 쓸 수 있는 같은 항목이 아닙니다. 각 항목의 의미를 확인하기 어렵다면 설정 참고 문서를 먼저 읽어 보세요.

방법 2: config.yaml에서 mixed-port 변경하기

커널을 직접 실행하거나 로컬 설정 파일을 명시적으로 사용하는 경우 실제로 불러오는 YAML 파일을 수정할 수 있습니다. 시작 매개변수나 클라이언트에 표시된 설정 파일 경로를 확인해 적용 중인 파일을 편집하세요. 파일 이름이 config.yaml이라고 해서 반드시 사용 중인 설정 파일인 것은 아닙니다.

아래는 로컬에서 사용할 때의 최상위 필드 예시입니다. 기존 설정에 병합하면서 프록시 노드, 정책 그룹, 규칙을 유지하세요. 구독 설정 전체를 대체할 수 있는 파일이 아닙니다.

mixed-port: 17890
allow-lan: false
mode: rule
log-level: info
  • mixed-port: 하나의 리스닝 포트에서 HTTP 프록시와 SOCKS 프록시 연결을 모두 받습니다. 앱에서 올바른 프록시 프로토콜을 선택해야 합니다.
  • allow-lan: false: 로컬에서만 사용할 때 적합한 설정입니다. 로컬 포트 충돌을 해결하려고 LAN 접근을 무작정 허용하지 마세요.
  • mode: rule: 규칙 기반 분기 모드를 유지합니다. 인바운드 포트를 변경해도 분기 모드까지 바꿀 필요는 없습니다.
  • log-level: info: 시작 정보를 확인하기에 적합한 로그 수준입니다. 문제 해결이 끝나면 기존 로그 수준으로 되돌릴 수 있습니다.

중복 키와 다른 인바운드 설정 확인하기

필드는 YAML 최상위 수준에 두고 공백으로 들여쓰기하세요. proxies나 proxy-groups 안에 넣지 마세요. 같은 수준에서 mixed-port를 두 번 작성해서도 안 됩니다. 파서마다 중복 키를 처리하는 방식이 다를 수 있으므로 나중에 쓴 값이 앞선 값을 덮어쓴다고 가정하지 마세요.

기존 port, socks-port 및 기타 인바운드 리스닝 설정도 검색하세요. port: 17890과 mixed-port: 17890이 같은 TCP 주소를 동시에 점유하려 해서는 안 됩니다. 별도 인바운드 설정을 유지할지는 실제 앱 사용 방식에 따라 결정하세요.

설정 검사 후 다시 불러오기

mihomo를 직접 사용하는 경우 커널의 설정 테스트 옵션으로 구문을 확인할 수 있습니다. 아래 예시는 현재 디렉터리의 설정 파일을 실제 실행에 사용하는 것으로 가정합니다. 경로가 다르면 실제 경로를 지정하세요.

mihomo -t -f ./config.yaml

설정 테스트를 통과해도 리스닝이 시작된 것은 아닙니다. 저장한 다음 커널을 다시 불러오거나 재시작하고 시작 로그를 확인하세요. 구독으로 관리되는 파일은 구독을 업데이트할 때 수동 변경 사항이 덮어써질 수 있습니다. 클라이언트가 지원하는 지속형 덮어쓰기 기능을 사용하거나 포트를 클라이언트 전역 설정에서 관리하세요.

시스템 프록시와 앱 프록시 설정도 함께 변경하기

커널 포트를 17890으로 변경한 뒤에도 7890을 가리키는 프록시 설정이 남아 있는지 확인해야 합니다. 시스템 프록시, 브라우저 확장 프로그램, 터미널 환경 변수와 개발 도구는 각각 설정을 따로 저장하며 대개 자동으로 함께 바뀌지 않습니다.

설정 항목확인할 값
Windows 11‘설정’ → ‘네트워크 및 인터넷’ → ‘프록시’ → ‘수동 프록시 설정’ → ‘프록시 서버 사용’에서 주소를 127.0.0.1, 포트를 17890으로 설정하세요.
macOS‘시스템 설정’ → ‘네트워크’ → 현재 네트워크 연결 → ‘세부사항’ → ‘프록시’에서 웹 프록시, 보안 웹 프록시와 사용 설정된 SOCKS 프록시를 확인하세요.
브라우저 프록시 확장 프로그램현재 프로필의 서버 포트를 변경하고 7890이 남아 있지 않은지 확인하세요.
터미널 및 개발 도구HTTP_PROXY, HTTPS_PROXY, ALL_PROXY와 Git, 패키지 관리자, IDE의 별도 프록시 설정을 확인하세요.

클라이언트의 ‘시스템 프록시’ 스위치를 사용하는 경우 새 포트 설정이 적용된 뒤 스위치를 껐다가 다시 켜고, 운영체제 설정에서도 확인하세요. macOS의 ‘보안 웹 프록시’는 HTTPS 웹사이트에 연결할 때 사용하는 프록시를 뜻합니다. 로컬 프록시 자체에서 TLS를 사용해야 한다는 의미는 아닙니다.

터미널에서 환경 변수를 사용하는 경우 현재 macOS 또는 Linux 셸에서 다음과 같이 변경할 수 있습니다.

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

여기서 HTTPS_PROXY도 http://를 사용합니다. 로컬 HTTP 프록시를 통해 연결한다는 뜻입니다. socks5h는 이 형식을 지원하는 도구에서 대상 도메인 이름 조회를 프록시가 처리한다는 의미입니다. 이 명령은 현재 셸과 이후 실행되는 하위 프로세스에만 적용됩니다. 영구 설정 파일에 자동으로 저장되지 않으며 모든 도구가 이 환경 변수를 읽는 것도 아닙니다.

수정 결과와 반복되는 충돌 원인 확인하기

수정 후에는 새 포트가 실제로 리스닝 중인지, 예상한 커널이 리스닝하는지, 앱이 해당 포트로 요청을 보낼 수 있는지 확인해야 합니다. 앞에서 사용한 명령으로 17890을 조회한 뒤 시스템 프록시나 환경 변수의 영향을 피하도록 프록시를 명시해 요청을 보내세요.

# macOS / Linux
curl -I --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 15 https://example.com/

# Windows PowerShell: curl.exe 직접 실행
curl.exe -I --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 15 https://example.com/

5초는 연결 제한 시간이고 15초는 전체 요청 제한 시간입니다. 속도 측정 결과가 아닙니다. Connection refused가 표시되면 리스닝 주소와 커널 상태부터 확인하세요. 프록시가 연결을 수락한 뒤 시간 초과가 발생하면 규칙 적용, 출구 노드, DNS 로그를 이어서 확인하세요. HTTP 응답을 받았다는 사실만으로 이번 요청이 해당 포트를 거쳤다는 점을 알 수 있을 뿐, 모든 트래픽이 예상대로 프록시를 통과한다는 뜻은 아닙니다.

포트가 비어 있는데도 시작되지 않는 경우

  • Windows 예약 포트: 로그에 접근 권한 오류가 표시되고 리스닝 중인 프로세스가 없다면 아래 명령으로 제외된 포트 범위를 확인하세요. 새 포트는 해당 범위를 피하고, 시스템 예약 항목을 직접 삭제하지 마세요.
  • 이전 프로세스 자동 재시작: 시스템 서비스와 로그인 시 시작되는 항목을 확인하고 그래픽 클라이언트 두 개가 동시에 실행 중인지 살펴보세요.
  • 잘못된 설정 파일 수정: 실제로 불러오는 파일 경로, 시작 매개변수, 클라이언트 덮어쓰기 설정을 확인한 다음 다시 불러온 뒤의 로그와 비교하세요.
  • 가상화 환경의 네트워크 경계 차이: Docker, WSL, 호스트 시스템은 서로 다른 네트워크 네임스페이스를 사용할 수 있습니다. 실제로 포트를 바인딩하는 환경에서 확인하세요. 컨테이너 내부에서 리스닝에 성공해도 호스트 포트 매핑까지 성공한 것은 아닙니다.
netsh interface ipv4 show excludedportrange protocol=tcp
netsh interface ipv6 show excludedportrange protocol=tcp

TUN을 켜도 시스템 프록시를 변경해야 하나요?

TUN은 가상 네트워크 인터페이스와 라우팅을 이용해 트래픽을 처리합니다. 앱이 7890에 연결하는 방식과는 다릅니다. TUN이 정상 작동하더라도 설정된 혼합 포트의 바인딩은 실패할 수 있습니다. 반대로 혼합 포트가 다시 리스닝한다고 해서 TUN 라우팅과 DNS까지 정상이라는 뜻은 아닙니다. 문제를 해결할 때는 두 경로를 따로 점검하고, 브라우저에서 웹페이지가 열린다는 이유만으로 리스닝 상태를 확인한 것으로 간주하지 마세요.

마지막으로 클라이언트를 다시 시작해 포트 설정이 17890으로 유지되는지 확인하고, 필요하면 구독 업데이트 후 설정도 테스트하세요. 7890으로 되돌려야 한다면 기존 점유 프로세스가 종료됐는지 먼저 확인한 뒤 시스템 프록시와 앱 프록시를 함께 복구하세요. 문제 해결 전후의 포트를 기록해 두면 다음에 클라이언트를 옮길 때 같은 점검을 반복하지 않아도 됩니다.