이 글의 목차
handshake failed는 구독 다운로드, 프록시 서버 연결, 대상 웹사이트 접속 중 어느 단계에서도 나올 수 있습니다. 관련 인증서와 설정은 다르며 무작정 노드를 바꾸거나 검증을 끄면 원래 문제를 가릴 수 있습니다. 실패 위치를 찾고 정확한 오류 내용에 따라 시간, 신뢰 체인, 서버 이름을 확인한 뒤 같은 요청을 다시 시도하세요.
TLS 핸드셰이크 실패: 로그 원문과 실패 위치로 점검 대상 찾기
TLS 오류 전체를 보관하고 구독 다운로드, 노드 연결, 대상 사이트 접속 중 어디에서 발생했는지 기록하세요. 핸드셰이크는 암호화 통신 조건을 협의하며 일반 HTTPS에서는 보통 클라이언트가 서버의 신원을 검증합니다. 아래 표에서 시간, 인증서, 노드 필드별 확인 대상을 구분하세요.
일반적인 원문
| 로그 문구 | 우선 확인 방향 |
|---|---|
| x509: certificate has expired or is not yet valid | 시스템 시간과 인증서 유효 기간 |
| x509: certificate signed by unknown authority | 시스템 CA, 기업 SSL 검사와 사설 인증서 |
| remote error: tls: handshake failure | SNI, 프로토콜 필드와 서버 TLS 구성 |
| tls: failed to verify certificate: x509 | 인증서 체인, servername과 실제 인증서 이름 |
| EOF / connection reset by peer | 상대가 조기에 연결을 종료했거나 네트워크가 차단함. 이 문구만으로 인증서 문제라고 단정할 수 없음 |
오류 전후의 몇 줄을 복사하고 시간, 대상 도메인과 포트는 보존하되 구독 token, UUID와 비밀번호는 가립니다. 'TLS failed'만 캡처하면 원인을 구분할 핵심 내용을 잃게 됩니다.
구독, 특정 노드와 대상 웹사이트의 오류는 점검 대상이 다릅니다
Profile 업데이트에서 TLS 오류가 나지만 기존 노드는 사용 가능
구독 URL에서 실패했습니다. 해당 도메인 인증서, 시스템 시간과 네트워크 검사 장비를 확인합니다.
노드 하나에서만 handshake failure 발생
클라이언트와 프록시 서버 사이에서 실패했습니다. 해당 노드의 server, port, SNI와 TLS 필드를 비교하세요.
노드는 연결되지만 HTTPS 웹사이트 하나에서만 인증서 오류
대상 사이트 인증서, 브라우저/앱 인증서 저장소와 보안 소프트웨어의 복호화 여부를 확인합니다.
모든 노드에서 동시에 x509 오류가 시작됨
시스템 시간, 코어 업그레이드와 네트워크의 인증서 일괄 교체 여부부터 확인합니다.
인증서가 만료됐거나 아직 유효하지 않다고 표시되면 시스템 시간 확인하기
# 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 등의 필드도 한 세트로 일치해야 합니다.
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 -verify_hostname edge.example.com -verify_return_error -showcerts </dev/null
curl -Iv https://edge.example.com/openssl 출력에서 subject, issuer, 유효 기간과 Verify return code를 확인하세요. 도메인으로 연결하면 SNI가 자동 전송될 수 있으므로 인수 하나를 삭제했다고 SNI가 전송되지 않았다고 판단할 수는 없습니다.
SNI 없이 비교하기 전에 사용 중인 OpenSSL이 -noservername을 지원하는지 확인하세요. -servername과 그 값을 삭제한 뒤 -noservername을 추가합니다. 같은 대상, -verify_hostname, -verify_return_error는 그대로 유지하세요. 두 SNI 옵션은 함께 사용할 수 없습니다.
같은 대상이 모바일 핫스팟에서는 정상 인증서를 반환하지만 회사 네트워크에서는 기업 CA 인증서를 반환한다면 검사 장비가 인증서를 바꿨을 수 있습니다. 두 결과를 관리자에게 전달하고 낯선 루트 인증서를 직접 설치하지 마세요.
프록시 프로토콜 포트가 일반 HTTPS 페이지를 제공하는 것은 아니므로 curl 실패만으로 노드가 손상되었다고 판단할 수 없습니다. openssl의 인증서와 핸드셰이크 정보가 더 유용합니다. Reality 등의 프로토콜에도 일반 웹사이트 인증서 검사를 그대로 적용할 수 없으며 해당 프로토콜 문서로 돌아가야 합니다.
회사 네트워크의 HTTPS 검사로 인증서가 바뀌었나요?
기업 프록시, 보안 게이트웨이와 일부 백신 프로그램은 HTTPS 인증서를 다시 발급합니다. 관리되는 기기에서는 관리자가 조직 CA를 설치하고 검사 가능한 트래픽을 설명해야 합니다. 개인 사용자는 오류 웹페이지에서 낯선 루트 인증서를 받거나 Clash 업데이트를 위해 시스템 전체 인증서 검증을 끄면 안 됩니다.
모바일 핫스팟으로 바꾼 뒤 같은 구독 URL이 바로 정상화되면 네트워크 경로 차이의 근거가 됩니다. 회사 네트워크에서의 issuer, 오류 시각과 대상 도메인을 관리자에게 전달하는 편이 노드를 계속 바꾸는 것보다 유용합니다.
수정 후 기존에 실패하던 같은 연결 반복
검증 결과
- 시스템 시간과 시간대가 올바르고 코어 재시작 후 not yet valid/expired가 더 이상 나타나지 않음
- 구독이 실패한 경우 수동 업데이트에 성공하고 업데이트 시각이 바뀜
- 노드가 실패한 경우 같은 노드에서 핸드셰이크를 완료하고 실제 연결 기록을 생성함
- 대상 웹사이트가 실패한 경우 인증서 issuer와 도메인이 예상과 일치함
- 임시로 끈 인증서 검사 또는 보안 설정을 복원함
- 통제된 테스트에 명확한 이유가 없다면 skip-cert-verify를 false로 유지
