연결 문제 해결 · Clash 기술 블로그

Clash TLS 핸드셰이크 실패 해결 방법: 인증서, 시간 및 SNI 점검

TLS 오류가 구독 다운로드, 노드 핸드셰이크 또는 대상 웹사이트 접속 중 어디에서 발생하는지 먼저 확인하세요. 세 곳 모두 handshake failed가 표시될 수 있지만 확인할 인증서, 시간 및 SNI는 완전히 다릅니다.

  • TLS
  • 인증서 오류
  • SNI
  • 연결 문제 해결
이 글의 목차

TLS handshake failed가 보이면 전체 오류와 실패 단계부터 저장

인증서 오류, 잘못된 시스템 시간과 잘못 구성된 SNI는 모두 TLS 핸드셰이크 실패로 표시되지만 수정 방법은 전혀 다릅니다. 로그의 전체 원문을 먼저 복사한 뒤 구독 다운로드, 프록시 노드 핸드셰이크 또는 대상 웹사이트 접속 중 어디에서 오류가 발생하는지 확인하세요. 이 두 항목을 알아야 시간, 인증서 체인 또는 노드 필드 중 무엇을 확인할지 판단할 수 있습니다.

일반적인 원문

로그 문구우선 확인 방향
x509: certificate has expired or is not yet valid시스템 시간과 인증서 유효 기간
x509: certificate signed by unknown authority시스템 CA, 기업 SSL 검사와 개인 인증서
remote error: tls: handshake failureSNI, 프로토콜 필드와 서버 TLS 구성
tls: failed to verify certificate: x509인증서 체인, servername과 실제 인증서 이름
EOF / connection reset by peer상대가 조기에 연결을 종료했거나 네트워크가 차단함. 이 문구만으로 인증서 문제라고 단정할 수 없음

오류 전후의 몇 줄을 복사하고 시간, 대상 도메인과 포트는 보존하되 구독 token, UUID와 비밀번호는 가립니다. 'TLS failed'만 캡처하면 원인을 구분할 핵심 내용을 잃게 됩니다.

구독 다운로드, 노드 핸드셰이크와 대상 웹사이트는 서로 다른 세 연결

간단한 비교부터 시작하세요. 기존 노드로 다른 HTTPS 웹사이트에 접속할 수 있는지, 구독을 수동으로 업데이트할 수 있는지 확인합니다. 두 결과를 함께 보면 핸드셰이크 실패가 어느 구간에서 발생하는지 대개 판단할 수 있습니다.

Profile 업데이트에서 TLS 오류가 나지만 기존 노드는 사용 가능

구독 URL에서 실패했습니다. 해당 도메인 인증서, 시스템 시간과 네트워크 검사 장비를 확인합니다.

노드 하나에서만 handshake failure 발생

클라이언트와 프록시 서버 사이에서 실패했습니다. 해당 노드의 server, port, SNI와 TLS 필드를 비교하세요.

노드는 연결되지만 HTTPS 웹사이트 하나에서만 인증서 오류

대상 사이트 인증서, 브라우저/앱 인증서 저장소와 보안 소프트웨어의 복호화 여부를 확인합니다.

모든 노드에서 동시에 x509 오류가 시작됨

시스템 시간, 코어 업그레이드와 네트워크의 인증서 일괄 교체 여부부터 확인합니다.

시간이 잘못되면 모든 인증서 설정을 잘못 판단하게 됩니다

Linux와 Windows에서 먼저 확인
# Linux
date -R
timedatectl status

# Windows PowerShell
Get-Date
w32tm /query /status

인증서에는 Not Before와 Not After가 있습니다. 이중 부팅 전환, 가상 머신 스냅샷, 장기간 전원이 꺼진 OpenWrt 또는 자동 시간 동기화 비활성화로 시간이 어긋날 수 있습니다. 날짜, 시간대와 NTP 동기화를 복구한 뒤 Mihomo를 재시작하고 다시 재현하세요. 오류가 완전히 같을 때만 핸드셰이크 필드를 계속 확인합니다.

노드 하나만 실패하면 SNI와 서버 인증서 이름 비교

TLS 노드 연결의 server는 IP이지만 인증서는 도메인에 발급되었을 수 있습니다. 이때 구성에는 올바른 servername 또는 sni가 필요합니다. 값은 서버 구성에서 받아야 하며 인터넷에서 인기 도메인을 추측하면 안 됩니다. 포트, 전송 유형, ALPN, Reality public-key/short-id 등의 필드도 한 세트로 일치해야 합니다.

프록시 유형과 현재 Mihomo 문서를 기준으로 필드 이름 확인
proxies:
  # 下列 IP、域名和密码都是占位值,不能直接连接
  - name: tls-example
    type: trojan
    server: 203.0.113.10
    port: 443
    password: REDACTED
    sni: edge.example.com
    skip-cert-verify: false

같은 네트워크에서 서버가 실제 반환하는 인증서 확인

도메인과 포트를 실패한 대상으로 교체
openssl s_client -connect edge.example.com:443   -servername edge.example.com -showcerts </dev/null

curl -Iv https://edge.example.com/

openssl 출력에서 subject, issuer, 유효 기간과 Verify return code를 확인합니다. -servername을 추가했을 때와 아닐 때 다른 인증서가 반환되면 서버가 SNI에 의존한다는 뜻입니다. 모바일 핫스팟에서는 인증서가 정상인데 회사 네트워크에서는 기업 CA로 바뀐다면 SSL 검사 또는 중간 게이트웨이가 존재합니다.

프록시 프로토콜 포트가 일반 HTTPS 페이지를 제공하는 것은 아니므로 curl 실패만으로 노드가 손상되었다고 판단할 수 없습니다. openssl의 인증서와 핸드셰이크 정보가 더 유용합니다. Reality 등의 프로토콜에도 일반 웹사이트 인증서 검사를 그대로 적용할 수 없으며 해당 프로토콜 문서로 돌아가야 합니다.

회사 네트워크에서만 실패하면 관리되는 인증서 검사가 있는지 먼저 확인

기업 프록시, 보안 게이트웨이와 일부 백신 프로그램은 HTTPS 인증서를 다시 발급합니다. 관리되는 기기에서는 관리자가 조직 CA를 설치하고 검사 가능한 트래픽을 설명해야 합니다. 개인 사용자는 오류 웹페이지에서 낯선 루트 인증서를 받거나 Clash 업데이트를 위해 시스템 전체 인증서 검증을 끄면 안 됩니다.

모바일 핫스팟으로 바꾼 뒤 같은 구독 URL이 바로 정상화되면 네트워크 경로 차이의 근거가 됩니다. 회사 네트워크에서의 issuer, 오류 시각과 대상 도메인을 관리자에게 전달하는 편이 노드를 계속 바꾸는 것보다 유용합니다.

수정 후 기존에 실패하던 같은 연결 반복

'다른 웹사이트도 열린다'는 사실로 검증을 대신하지 마세요. 처음 오류가 났던 구독, 노드 또는 대상 웹사이트로 돌아가 같은 네트워크에서 다시 시도하고 로그의 기존 오류가 사라졌는지 확인합니다.

검증 결과

  • 시스템 시간과 시간대가 올바르고 코어 재시작 후 not yet valid/expired가 더 이상 나타나지 않음
  • 구독이 실패한 경우 수동 업데이트에 성공하고 업데이트 시각이 바뀜
  • 노드가 실패한 경우 같은 노드에서 핸드셰이크를 완료하고 실제 연결 기록을 생성함
  • 대상 웹사이트가 실패한 경우 인증서 issuer와 도메인이 예상과 일치함
  • 임시로 끈 인증서 검사 또는 보안 설정을 복원함
  • 통제된 테스트에 명확한 이유가 없다면 skip-cert-verify를 false로 유지

참고 자료