본문으로 건너뛰기

Clash 로그 보는 법: dial tcp·i/o timeout 등 주요 오류 해설

실행 로그는 문제 원인을 찾는 핵심 자료입니다. 로그 수준을 조정하는 방법과 dial tcp, i/o timeout, connection refused 등의 오류 의미를 살펴보고, 로그 한 줄로 노드·규칙·DNS 중 어디에서 문제가 생겼는지 확인하는 방법을 알아봅니다.

1. 문제를 한 번 재현한 뒤 같은 시각의 로그를 확인하세요

웹페이지가 열리지 않는다고 DNS, 노드, TUN, 규칙을 한꺼번에 바꾸지 마세요. 클라이언트의 ‘로그’ 화면을 열고 현재 시각을 확인한 다음, 문제가 발생한 페이지를 한 번만 새로고침합니다. 화면에 가득한 빨간 로그 중 가장 심각해 보이는 항목을 고르기보다, 해당 시각 전후 몇 초간의 기록을 먼저 확인하세요.

로그 색상은 기록 수준을 나타낼 뿐, 문제 범위를 뜻하지 않습니다. 백그라운드 속도 측정 실패가 경고로 기록돼도 브라우저 연결은 정상일 수 있습니다. 반대로 잘못된 DIRECT 규칙이 적용된 경우에는 눈에 띄는 오류 없이 일반 연결 기록만 남을 수도 있습니다.

  1. 클라이언트 이름과 버전, 코어 이름, 현재 사용 중인 ‘규칙’, ‘전역’, ‘직접 연결’ 모드를 기록합니다.
  2. 실패한 도메인과 발생 시각, 증상을 적어 둡니다. 예: 홈페이지는 열리지만 이미지가 로드되지 않음.
  3. 로그 화면을 지우거나 시간 필터를 적용한 뒤 같은 작업을 다시 해 보세요. 화면에서 로그를 지워도 디스크의 로그 파일까지 삭제되는 것은 아닐 수 있습니다.
  4. 실패한 요청 전후의 기록을 보관하세요. 특히 대상 주소, 적용된 규칙, 아웃바운드 정책, 오류 원인을 확인합니다.

2. 로그 수준 변경: 먼저 info를 사용하고, 필요할 때만 잠시 debug로 전환하세요

Clash 계열 클라이언트에서는 보통 사이드바의 ‘로그’에서 실행 기록을 확인할 수 있습니다. 로그 수준 필터가 있다면 표시되는 기록만 필터링하는지, 코어의 로그 수준 자체를 변경하는지 먼저 확인하세요. 필터만 Debug로 바꿔서는 코어가 디버그 정보를 출력하지 않을 수 있습니다.

코어 설정에서 로그 상세 수준을 제어하는 필드는 log-level입니다. 원본 Clash와 mihomo 모두 이 필드를 사용합니다. 클라이언트에 ‘로그 수준’ 설정이 있다면 먼저 해당 화면에서 변경하세요. 설정 메뉴가 없다면 클라이언트가 지원하는 설정 덮어쓰기 또는 병합 기능을 사용합니다. 구독으로 생성된 파일을 직접 수정했다고 해서 설정이 계속 유지되는 것은 아닙니다. 구독을 업데이트하면 변경 사항이 덮어써질 수 있습니다.

# 설정 최상위에 두고 dns 또는 rules 아래에 들여쓰지 마세요
log-level: info
수준사용 상황주의 사항
silent일반 로그 출력을 억제합니다문제 해결 시 이 수준은 사용하지 마세요
error오류만 확인합니다규칙 일치 여부와 연결 상황이 기록되지 않을 수 있습니다
warning경고를 비롯한 심각한 문제를 확인합니다반복되는 연결 실패를 빠르게 찾을 때 유용합니다
info일상적인 문제 해결의 출발점입니다대상 주소와 아웃바운드 정책을 함께 확인하세요
debugDNS 조회와 연결 등의 세부 정보를 추가로 기록합니다문제를 잠시 재현한 뒤 원래대로 돌려 로그가 쌓이지 않게 하세요

디버깅이 필요하면 이 필드를 잠시 debug로 변경하고, 클라이언트 안내에 따라 설정을 다시 불러오거나 코어를 재시작한 뒤 문제를 한 번 재현하세요. 이후 info로 되돌립니다. 설정 필드에는 warning을 사용하지만 로그의 수준 표시는 WARN 또는 warning으로 나올 수 있으니 혼동하지 마세요.

기록을 공유하기 전에 구독 링크, 액세스 토큰, 노드 암호, 서버 주소, 로컬 경로가 포함돼 있는지 확인하세요. 오류 원문과 포트 구조만 남기면 됩니다. 공개적으로 도움을 요청할 때 구독 설정 전체를 제공할 필요는 없습니다.

3. 연결 로그에서 먼저 볼 네 가지: 대상·규칙·아웃바운드·오류

[info] [TCP] 127.0.0.1:53142 --> www.example.com:443
match DomainSuffix(example.com) using Proxy[노드-A]

이 간략한 기록은 로컬 프로그램이 임시 포트 53142에서 TCP 요청을 보내고, 대상 www.example.com:443에 대해 도메인 접미사 규칙이 적용돼 Proxy 정책 그룹에서 선택된 노드-A를 통해 연결했다는 뜻입니다. 왼쪽의 임시 포트는 클라이언트의 프록시 수신 포트가 아니므로 이를 기준으로 설정을 바꿀 필요는 없습니다.

MATCH는 보통 기본 규칙이 적용됐다는 뜻이며 규칙 엔진이 작동하지 않는다는 의미는 아닙니다. 특정 정책을 사용해야 하는 사이트가 기본 규칙에 걸린다면 앞선 규칙에서 해당 도메인을 처리하는지, 규칙 세트가 로드됐는지, 의도한 설정을 실제로 사용 중인지 확인하세요.

4. dial tcp: TCP 연결을 시도 중이라는 뜻이며, 원인은 뒤에 이어지는 내용에서 확인하세요

dial tcp는 연결 동작을 나타낼 뿐, 그 자체로 오류 원인을 말해 주지는 않습니다. 뒤에는 보통 주소와 하위 단계의 오류가 이어집니다. 다음 두 기록에는 같은 문구가 있지만 해결 방향은 다릅니다.

dial tcp 203.0.113.10:443: i/o timeout
dial tcp 127.0.0.1:7897: connect: connection refused

원격 주소 연결 실패: 먼저 어떤 주소인지 확인하세요

첫 번째 기록의 원격 주소는 프록시 서버일 수도 있고 직접 연결하려는 웹사이트일 수도 있습니다. 아웃바운드 필드와 설정을 함께 확인해야 합니다. 현재 노드의 서버 주소라면 먼저 내 기기에서 노드까지의 연결을 점검하세요. DIRECT로 접속하는 사이트 주소라면 로컬 네트워크와 라우팅, 해당 사이트 상태를 확인해야 합니다.

로컬 주소 연결 실패: 먼저 수신 포트를 확인하세요

두 번째 기록은 로컬 주소 127.0.0.1:7897을 가리킵니다. 브라우저나 명령줄에서 사용하는 프록시 진입점이라면 연결 거부는 해당 주소에서 서비스를 수신하지 않거나 서비스가 정상적으로 시작되지 않았다는 뜻일 수 있습니다. 여기서 7897은 예시일 뿐, 모든 클라이언트의 기본 포트가 아닙니다.

클라이언트에서 실제 ‘혼합 포트’ 또는 HTTP/SOCKS 포트를 확인하세요. 혼합 포트를 사용한다면 해당 설정 필드는 mixed-port입니다. Windows에서는 다음 명령으로 예시 포트의 수신 여부를 확인할 수 있습니다.

netstat -ano | findstr :7897

출력에 표시된 로컬 주소와 LISTENING 상태를 확인한 뒤 프로세스 PID도 대조하세요. 해당 숫자가 포함된 원격 연결 행만으로는 로컬에서 포트를 수신 중이라고 볼 수 없습니다. 클라이언트가 아예 시작되지 않았다면 노드를 바꾸기 전에 시작 오류부터 해결하세요.

5. i/o timeout: 응답 대기 시간 초과이며 노드 장애로 단정할 수 없습니다

i/o timeout은 네트워크 읽기 또는 쓰기 작업이 제한 시간 안에 완료되지 않았다는 뜻입니다. TCP 연결 설정, DNS 조회, 프록시 핸드셰이크, 연결 후 데이터 읽기 단계에서 발생할 수 있습니다. 이 문구만으로는 통신사 경로, 원격 서비스, UDP 패킷 손실, 로컬 방화벽 중 어느 쪽의 문제인지 구분할 수 없습니다.

  1. 실패한 대상을 먼저 확인하세요. 노드 서버와 DNS 서버의 시간 초과는 서로 다른 단계의 문제입니다. read udp, dial tcp 같은 접두 문구를 함께 확인하세요.
  2. 같은 네트워크에서 노드를 바꿔 보세요. 규칙, DNS, TUN 설정은 그대로 두고 정책 그룹에서 선택한 노드만 바꾼 다음 같은 대상에 접속합니다.
  3. 같은 노드로 네트워크를 바꿔 보세요. 예를 들어 Wi-Fi에서 휴대폰 핫스팟으로 전환해 비슷한 시간 초과가 사라지는지 확인합니다.
  4. 모든 사이트에서 발생하는지 특정 사이트에서만 발생하는지 구분하세요. 도메인 하나만 실패한다면 대상 사이트의 상태와 해당 사이트에 적용되는 규칙도 확인해야 합니다.

여러 대상이 같은 노드에서만 실패한다면 노드 또는 해당 노드까지의 경로를 우선 점검하세요. 백그라운드 속도 측정에서 한 번 시간 초과가 발생했더라도 웹 요청이 정상이라면 전체 설정을 초기화할 필요는 없습니다. 속도 측정용 URL과 프로토콜은 실제 서비스 요청과 다를 수 있습니다.

6. connection refused: 연결 거부는 시간 초과와 구분해서 처리하세요

connection refused는 응답이 없었던 것이 아니라 연결 요청이 명시적으로 거부됐다는 뜻인 경우가 많습니다. 대상 포트에서 서비스를 수신하지 않거나 기기의 정책이 연결을 거부할 때 발생할 수 있습니다. 암호 오류와는 다릅니다. 암호나 프로토콜이 일치하지 않는 문제는 대개 연결 후 인증 또는 핸드셰이크 단계에서 나타납니다.

로그에 address already in use가 표시된다면 의미가 다릅니다. 클라이언트가 포트를 열려고 했지만 이미 사용 중인 상태입니다. 먼저 해당 포점을 점유한 프로세스를 확인한 다음 기존 인스턴스를 종료할지 포트를 바꿀지 결정하세요. 포트를 변경하면 프록시를 수동으로 설정한 앱에서도 포트를 함께 바꿔야 합니다.

7. DNS 오류: 노드 도메인과 웹사이트 도메인을 구분하세요

no such host는 도메인 조회 결과를 얻지 못했다는 뜻인 경우가 많습니다. 이름이 존재하지 않거나 오타가 있거나 조회 경로에 문제가 있을 수 있습니다. server misbehaving은 보통 리졸버가 비정상 상태를 반환했다는 뜻입니다. 이런 문구가 보이면 DNS 설정 전체를 바로 바꾸기보다 어떤 이름을 조회 중인지 먼저 확인하세요.

lookup www.example.com: no such host
read udp 192.168.1.20:53000->192.168.1.1:53: i/o timeout

두 번째 기록은 192.168.1.1:53으로 보낸 UDP 읽기 요청이 시간 초과됐다는 뜻이므로 DNS 조회 경로를 살펴봐야 합니다. DoH를 사용한다면 DNS 리졸버의 443 포트 연결이나 TLS 오류가 나타날 수도 있으므로 기존 UDP 53 포트 기준으로만 점검해서는 안 됩니다.

노드 서버 도메인 조회 실패

노드 자체의 도메인을 확인할 수 없으면 이후 프록시 핸드셰이크를 시작할 수 없습니다. mihomo의 proxy-server-nameserver 필드로 프록시 서버 도메인을 조회할 DNS 서버를 지정할 수 있습니다. 다만 버전과 설정 방식에 따라 사용 조건이 달라지는 필드이므로 지원하지 않는 구형 코어에 그대로 복사하면 안 됩니다. 먼저 실제 사용 중인 코어를 확인하고, 프록시 연결이 시작되기 전에도 현재 리졸버에 접근할 수 있는지 점검하세요.

대상 웹사이트만 도메인 조회 실패

해당 도메인이 nameserver-policy 등의 설정에 영향을 받는지, 클라이언트가 실제로 앱의 DNS 요청을 처리하는지 확인하세요. 브라우저의 보안 DNS, 앱 내장 DNS 조회, 시스템 캐시, TUN의 DNS 가로채기 설정에 따라 조회 경로가 달라질 수 있습니다.

Fake-IP를 사용하는 경우 로그에 198.18.0.0/16 등 설정된 대역의 매핑 주소가 보여도 곧바로 DNS 오염을 뜻하지는 않습니다. 도메인 매핑과 아웃바운드 결과를 이어서 확인하세요. 시스템에서 실행한 nslookup은 해당 조회가 거친 경로만 보여 줄 뿐, 브라우저나 코어도 같은 리졸버를 사용한다고 증명하지는 않습니다.

8. 그 밖의 자주 보이는 오류: TLS, EOF, 시작 실패

로그 문구의미 및 우선 점검 항목
TLS handshake timeoutTLS 핸드셰이크가 제시간에 완료되지 않았습니다. 먼저 핸드셰이크 대상이 노드인지, 웹사이트인지, DoH 서비스인지 확인한 다음 경로와 프로토콜 설정을 점검하세요.
x509: certificate has expired or is not yet valid시스템 날짜와 시간, 시간대, 상대 서버 인증서의 유효 기간을 확인하세요. 원인을 감추기 위해 인증서 검증을 건너뛰지 마세요.
EOF / unexpected EOF연결이 종료됐거나 데이터를 다 읽기 전에 종료됐습니다. 안정적으로 재현되는지, 사용 프로토콜과 주변 상황은 어떤지 함께 살펴보세요. 이 기록만으로 차단됐다고 단정할 수는 없습니다.
connection reset by peer연결이 재설정됐습니다. 원격 서버, 네트워크 장비, 프로토콜 불일치가 원인일 수 있으므로 다른 노드와 네트워크에서도 비교해 보세요.
network is unreachable로컬 라우팅, 네트워크 인터페이스, IPv6 연결 가능 여부를 확인하세요. 특히 절전 모드에서 복귀했거나 네트워크를 전환했거나 TUN을 켜고 끈 뒤 발생했는지 살펴봅니다.
Parse config error먼저 설정 구문 오류를 해결하세요. 이어지는 안내에 따라 YAML 들여쓰기와 필드 유형, 현재 코어의 프로토콜 지원 여부를 확인합니다.

원본 Clash, Clash Meta, 후속 mihomo는 지원하는 설정 기능이 완전히 같지 않습니다. 구독 설정에 현재 코어가 지원하지 않는 프로토콜이나 필드가 포함돼 있으면 연결 단계가 아니라 설정을 불러오는 단계에서 문제가 발생합니다. 이 경우 노드를 바꿔도 해결되지 않는 경우가 많습니다. 설정이 정상적으로 로드됐는지와 프록시 그룹이 생성됐는지 먼저 확인한 뒤 연결 시간 초과를 살펴보세요.

TUN 시작 실패는 권한, 가상 네트워크 어댑터 또는 라우트 생성 문제와도 관련될 수 있습니다. 이때 시스템 프록시 경로와 TUN 경로에서 증상이 다르게 나타날 수 있습니다. 브라우저에서 시스템 프록시로 접속된다고 해서 TUN도 작동한다고 볼 수는 없습니다. TUN 오류가 발생했다고 시스템 네트워크 구성 요소를 바로 삭제하지 마세요.

9. 전체 사례: timeout 로그 한 줄로 노드 경로 문제 좁히기

브라우저에서 www.example.com에 접속할 수 없고 같은 시각에 다음과 같은 간략한 로그가 표시됐다고 가정해 보겠습니다.

[warning] [TCP] dial Proxy (match DomainSuffix/example.com)
127.0.0.1:53142 --> www.example.com:443
error: dial tcp 203.0.113.10:443: i/o timeout
  1. 이번 요청의 기록인지 확인합니다. 대상 도메인과 작업 시각이 일치하는지 확인해 백그라운드 속도 측정 기록을 제외합니다.
  2. 규칙이 의도대로 적용됐는지 확인합니다. 로그에는 Proxy를 사용했다고 표시됩니다. 원래 프록시로 접속하려던 경우라면 우선 규칙을 바꾸지 마세요.
  3. 실패한 주소를 확인합니다. 현재 노드의 서버 주소가 203.0.113.10:443이라고 가정하면, 현재 증거는 웹사이트의 HTTP 오류가 아니라 노드까지 연결하는 과정의 시간 초과를 가리킵니다.
  4. 노드만 바꿔 봅니다. 노드-B를 선택하고 모드와 대상은 그대로 유지합니다. 요청이 정상화되면 노드-A 자체 또는 노드-A까지의 경로를 우선 점검하세요.
  5. 필요하면 네트워크를 바꿔 다시 확인합니다. 노드-A가 핫스팟에서는 작동하고 기존 네트워크에서는 계속 시간 초과가 발생한다면 기존 네트워크 경로에 문제가 있을 가능성이 높습니다. 다만 어떤 기기가 차단했는지까지 확정할 수는 없습니다.

반대로 기존 기록에 using DIRECT라고 표시됐다면 위의 노드 관련 결론을 그대로 적용할 수 없습니다. 먼저 직접 연결이 선택된 이유를 확인한 다음 클라이언트의 ‘연결’ 화면에서 해당 요청의 규칙과 아웃바운드를 대조하세요. 비교를 위해 잠시 전역 모드로 전환할 수는 있지만, 확인이 끝나면 원래 모드로 되돌리고 규칙을 바로잡아야 합니다. 전역 모드를 모든 문제의 장기 해결책으로 삼지 마세요.

10. 로그가 없으면 진입 경로부터 확인하고, 도움을 요청할 때는 최소한의 증거를 남기세요

페이지를 새로고침해도 해당 기록이 전혀 없다면 트래픽이 이 코어로 들어오지 않았거나 로그 화면에서 기록이 필터링됐을 가능성이 큽니다. 앱이 시스템 프록시를 사용하는지, 브라우저 확장 프로그램이 프록시 설정을 덮어쓰는지, 다른 VPN에 연결돼 있는지, TUN이 실제로 시작됐는지 확인하세요. 시스템 프록시를 켰다고 해서 모든 앱이나 UDP 트래픽이 Clash를 거치는 것은 아닙니다.

로컬 혼합 포트로 요청을 보내 진입 경로를 직접 확인할 수도 있습니다. 아래 명령의 7897은 클라이언트에 표시된 실제 포트로 바꿔야 합니다. Windows PowerShell에서는 curl.exe를 사용하면 일부 구형 환경에서 같은 이름의 별칭으로 인한 차이를 피할 수 있습니다.

curl.exe -I --proxy http://127.0.0.1:7897 https://example.com

명령을 실행한 직후 로그를 확인하세요. 로컬 포트 연결 실패가 표시되면 먼저 포트 수신 상태와 코어 실행 여부를 점검합니다. 대상 연결 기록이 나타났다면 규칙, 아웃바운드, 오류 순서로 원인을 좁혀 가세요. 명령에서 반환된 HTTP 상태는 해당 요청의 결과만 보여 주며 다른 앱의 상태까지 확인해 주지는 않습니다.

문제 정보를 전달할 때 포함할 내용

문제 해결 순서를 일정하게 유지하세요. 먼저 트래픽이 코어에 들어오는지 확인하고, 다음으로 규칙과 아웃바운드를 확인한 뒤, 마지막으로 DNS·연결·핸드셰이크 단계 중 어디에서 문제가 생겼는지 찾습니다. 한 번에 하나씩만 변경하고 결과를 기록하세요. 접속이 복구되면 디버그 수준을 원래대로 돌립니다. 이렇게 하면 다음에 같은 오류가 발생해도 모든 설정을 처음부터 다시 시험할 필요 없이 기존 증거를 바탕으로 이어서 점검할 수 있습니다.

Clash 설치 파일