2026-06-20 · 문제 해결 · 약 11분

TLS 핸드셰이크 및 인증서 오류 해결: 시스템 시간, SNI와 인증서 검증 우회 사용 시 주의점

인증서 오류의 원인은 노드 자체보다 시스템 시간 오차, 잘못된 SNI, 불완전한 인증서 체인인 경우가 많습니다. 오류별 점검 방법과 안전한 해결책을 안내합니다.

빠른 내용 확인

TLS 핸드셰이크 실패, 인증서 이름 불일치, 인증서 만료 또는 unknown authority 오류가 발생한 v2rayN, v2rayNG, v2flyNG 사용자를 위한 글입니다. 본인 기기 시간, 노드 주소와 SNI, 인증서 유효 기간, 전체 인증서 체인, 전송 설정 순서로 점검하고 마지막에만 검증 우회를 짧게 비교 테스트합니다.

TLS 핸드셰이크는 어느 단계에서 실패할까

TLS는 TCP 연결이 수립된 뒤, 프록시 프로토콜이 실제 페이로드를 교환하기 전에 동작합니다. TLS를 사용하는 VMess 또는 VLESS 노드에서는 클라이언트가 먼저 서버 주소를 해석하고 원격 포트에 연결합니다. 흔히 사용하는 포트는 443입니다. 이어서 SNI, 지원하는 TLS 버전, ALPN 등이 포함될 수 있는 ClientHello를 보냅니다. 서버가 인증서 체인을 반환하면 운영체제는 인증서의 유효 기간, 발급 관계, 이름을 확인하고, 검증을 통과해야 암호화 세션을 수립합니다.

따라서 ‘지연 시간 테스트 실패’를 곧바로 ‘노드를 사용할 수 없음’으로 단정할 수는 없습니다. DNS 해석 실패, TCP 포트 연결 불가, TLS 인증서 검증 실패, 프록시 프로토콜 매개변수 오류는 모두 테스트 결과를 시간 초과 또는 사용 불가로 표시할 수 있지만, 각각 문제가 발생한 네트워크 구간은 다릅니다. 로그에서 처음 확인되는 명확한 오류를 먼저 읽고 수정할 매개변수를 정하는 편이 노드를 계속 바꿔 보는 것보다 효과적입니다.

도메인 해석TCP 연결클라이언트 인사인증서 반환로컬 검증암호화 전송

원격 주소에 연결하기도 전에 로그에 ‘no such host’가 나타나면 먼저 DNS 또는 주소 오타를 확인해야 합니다. x509, certificate, handshake 같은 키워드가 이미 나타났다면 인증서와 TLS 문제를 점검합니다. TLS가 완료된 뒤 invalid user, authentication failed 또는 protocol response가 나타난다면 문제는 인증서가 아니라 UUID, 비밀번호, 프로토콜 유형 또는 전송 설정에 있습니다.

로그 원문으로 인증서 오류 식별하기

v2rayN 7.x에서는 먼저 메인 창 하단의 로그 영역에서 커널 출력을 확인하고, ‘설정’ → ‘매개변수 설정’에서 로그 수준이 지나치게 낮게 설정되지 않았는지 확인하세요. 테스트할 때는 현재 커널을 중지한 뒤 다시 시작하고 HTTPS 페이지에 접속하면 이전 로그의 영향을 줄일 수 있습니다. 서버 목록에서 노드를 마우스 오른쪽 버튼으로 클릭해 ‘서버 편집’을 선택한 다음 TLS와 SNI 필드를 확인하세요.

Android에서도 현재 설정부터 확인해야 합니다. v2rayNG는 Xray 커널을 사용하고 v2flyNG는 v2fly 커널을 사용합니다. 두 커널 모두 인증서 유효 기간과 호스트 이름을 기본적으로 검증하는 원칙은 같지만 로그 문구에는 약간의 차이가 있을 수 있습니다. 마지막 줄의 ‘시작 실패’만 확인하지 말고 위쪽으로 올라가 x509, tls 또는 certificate가 처음 나타난 기록을 찾으세요.

오류: x509: certificate has expired or is not yet valid

원인 및 해결:로컬 기기의 시간이 인증서 유효 기간을 벗어났거나 서버 인증서가 실제로 만료된 상태입니다. 먼저 시스템 날짜, 시간, 시간대를 동기화한 뒤 로그에 표시된 Not Before와 Not After 시간을 확인하세요.

오류: x509: certificate is valid for example.net, not edge.example.net

원인 및 해결:클라이언트가 검증하는 이름이 인증서의 허용 범위에 없습니다. SNI를 구독에 지정된 인증서 도메인으로 변경하고, 노드 별칭, CDN 주소 또는 IP 주소를 임의로 입력하지 마세요.

오류: x509: certificate signed by unknown authority

원인 및 해결:서버가 중간 인증서 체인을 모두 보내지 않았거나 로컬 기기가 신뢰하지 않는 발급 체인을 사용하고 있을 수 있습니다. 먼저 다른 네트워크에서 다시 테스트한 뒤 서버 측에서 중간 인증서를 보완하세요. 검증 우회를 장기간 사용해서는 안 됩니다.

오류: remote error: tls: handshake failure

원인 및 해결:원격 서버가 핸드셰이크를 능동적으로 거부했습니다. SNI, ALPN, TLS 활성화 여부, 포트, 전송 방식이 한 세트로 일치하는지 확인하세요. 특히 WebSocket, gRPC, TCP 설정을 서로 섞지 마세요.

오류: tls: failed to verify certificate

원인 및 해결:인증서 검증 실패를 요약한 메시지입니다. 바로 이어지는 하위 원인을 확인한 뒤 시간 오류, 이름 불일치, 신뢰 체인 누락에 따라 각각 처리하세요.

오류: context deadline exceeded

원인 및 해결:제한 시간 안에 핸드셰이크가 완료되지 않았습니다. 먼저 도메인 해석과 원격 포트를 테스트해 패킷 손실, 방화벽, 잘못된 포트 문제가 아닌지 확인한 뒤 TLS 매개변수를 점검하세요.

EOF, connection reset by peer, unexpected EOF는 대개 연결이 중간에 종료되었다는 뜻이며, 그 자체만으로 인증서 오류를 입증하지는 않습니다. 같은 노드가 모바일 네트워크에서는 작동하지만 유선 네트워크에서 계속 재설정된다면 DNS 결과, IPv4와 IPv6 경로, 원격 443 포트의 TCP 연결 가능 여부를 우선 비교하세요.

curl -vI --connect-timeout 8 https://node.example.net/

openssl s_client \
  -connect node.example.net:443 \
  -servername node.example.net \
  -showcerts

위 명령은 일반 TLS 사이트의 핸드셰이크를 독립적으로 확인하는 데 사용합니다. 실행할 때 예시 도메인을 노드 설정에서 요구하는 인증서 도메인으로 바꾸세요. OpenSSL 출력의 subject, issuer, 인증서 시작·종료 시간, Verify return code를 통해 이름, 유효 기간, 인증서 체인 문제를 구분할 수 있습니다. 다만 프록시 서비스가 특정 경로나 애플리케이션 계층 프로토콜을 요구한다면 일반 HTTPS 요청 실패만으로 프록시 진입점이 작동하지 않는다고 단정할 수는 없습니다.

시스템 시간과 시간대 확인 방법

인증서에는 유효 시작 시간과 만료 시간이 포함되어 있으며, 로컬 기기는 자체 시계로 현재 시각이 해당 범위에 들어가는지 판단합니다. 날짜는 맞지만 시간대가 잘못되면 표시된 시각은 비슷해 보여도 실제 UTC 시간이 몇 시간 어긋날 수 있습니다. 듀얼 부팅, 메인보드 전원 차단, 가상 머신 일시 중지 후 복원, 자동 시간 동기화 해제 등이 흔한 원인입니다.

  1. Windows에서 ‘설정’ → ‘시간 및 언어’ → ‘날짜 및 시간’을 열고 ‘자동으로 시간 설정’과 ‘자동으로 시간대 설정’을 켠 다음 ‘지금 동기화’를 클릭하세요.
  2. macOS에서 ‘시스템 설정’ → ‘일반’ → ‘날짜 및 시간’을 열고 날짜와 시간을 자동으로 설정하도록 한 뒤 현재 시간대를 확인하세요.
  3. Android에서 ‘설정’ → ‘시스템’ → ‘날짜 및 시간’을 열고 네트워크 제공 시간과 시간대를 활성화하세요. 시스템에 따라 메뉴 이름이 조금 다를 수 있습니다.
  4. Linux에서는 timedatectl status로 Universal time, RTC time, Time zone, System clock synchronized를 확인하고, 필요하면 timedatectl set-ntp true를 실행해 네트워크 시간 동기화를 켜세요.
  5. 동기화가 끝나면 클라이언트를 완전히 종료하고 커널을 다시 시작하세요. 기존 연결에서 지연 시간 테스트만 반복하지 마세요.

점검할 때는 눈대중이 아니라 오차를 기록해야 합니다. 로컬 시간이 신뢰할 수 있는 시간보다 24시간 빠르면 아직 유효한 인증서도 만료된 것으로 판단될 수 있고, 24시간 느리면 새로 발급된 인증서가 아직 유효하지 않은 것으로 판단될 수 있습니다. 일부 환경에서는 핸드셰이크 시 작은 시간 차이를 허용하지만, 몇 분의 허용 오차를 항상 적용되는 규칙으로 보면 안 됩니다.

점검 항목 정상 기준 이상 징후
시스템 날짜 년·월·일이 실제 날짜와 일치함 인증서가 만료되었거나 아직 유효하지 않다고 표시됨
시스템 시간대 현재 지역과 일치함 UTC 시간이 몇 시간 어긋남
자동 시간 동기화 동기화 성공 상태 재시작 후 다시 큰 오차가 발생함
인증서 유효 기간 현재 시간이 시작·종료 시간 사이에 있음 여러 기기에서 같은 시각에 모두 실패함

결론: 먼저 시계를 동기화한 뒤 노드 필드를 수정하세요

같은 구독의 여러 TLS 노드에서 동시에 ‘expired or is not yet valid’ 오류가 발생한다면, 여러 서버의 인증서가 동시에 무효화되었을 가능성보다 로컬 기기의 시간 이상일 가능성이 일반적으로 더 높습니다. 시간 동기화 후 커널을 재시작하는 것이 비용이 가장 적은 첫 단계입니다.

SNI, 주소, Host와 인증서 이름의 관계

노드의 ‘주소’는 DNS 해석과 TCP 연결에 사용되고, SNI는 TLS ClientHello에서 서버에 클라이언트가 접속하려는 이름을 알립니다. 또한 커널이 인증서 이름을 검증할 때 사용되는 경우가 많습니다. 두 값은 같을 수도 있지만 진입점 구조에 따라 다를 수도 있습니다. 올바른 값은 유효한 구독 또는 서버 설정에서 확인해야 하며 노드 별칭만으로 추정해서는 안 됩니다.

WebSocket 설정에는 Host 요청 헤더가 포함될 수도 있습니다. Host는 TLS 연결이 수립된 뒤의 HTTP 계층에 속하고 SNI는 TLS 핸드셰이크 계층에 속합니다. 두 필드에 같은 도메인을 입력하는 경우가 많더라도 완전히 같은 기능이라고 볼 수는 없습니다. gRPC에는 serviceName도 관련되며 REALITY 설정에는 serverName, publicKey, shortId가 함께 사용될 수 있습니다. 각 필드는 서로 다른 역할을 합니다.

필드 해당 단계 일반적인 용도 잘못 입력했을 때의 증상
주소 DNS 및 TCP 원격 서버 위치 확인 해석 실패, 연결 거부 또는 시간 초과
포트 TCP 또는 UDP 원격 수신 진입점에 연결 connection refused 또는 시간 초과
SNI TLS ClientHello 인증서 선택 및 이름 검증 이름 불일치 또는 handshake failure
Host HTTP 또는 WebSocket 애플리케이션 계층 가상 호스트 선택 TLS 성공 후 오류 응답 반환
ALPN TLS 협상 h2 또는 http/1.1 협상 원격 거부 또는 애플리케이션 계층 불일치

v2rayN에서 대상 노드를 마우스 오른쪽 버튼으로 클릭하고 ‘서버 편집’을 선택한 뒤, 보안 유형이 실제로 TLS인지 먼저 확인하고 SNI를 점검하세요. 구독을 업데이트한 뒤 수동 수정 내용이 덮어써진다면 매번 다시 값을 바꾸지 말고 구독 그룹으로 돌아가 원본 데이터를 확인하세요. VLESS REALITY에는 일반 공개 인증서의 점검 결과를 그대로 적용해서는 안 됩니다. 다만 serverName, 시스템 시간, 관련 매개변수가 한 세트로 일치하는 것은 여전히 중요합니다.

SNI를 비워야 오히려 연결되는데, 계속 비워 둬도 될까요?

먼저 구독 원본 설정을 확인하세요. 일부 커널은 필드가 비어 있으면 서버 주소를 대신 사용하지만, 이는 주소 자체가 올바른 인증서 이름일 때만 유효합니다. 서버에서 SNI를 명시했다면 원래 값을 입력하세요.

노드 주소가 IP라면 SNI에도 IP를 입력해야 하나요?

반드시 그렇지는 않습니다. 공개 인증서는 일반적으로 도메인에 발급되므로 노드는 IP로 연결하고 도메인으로 SNI 및 이름 검증을 수행할 수 있습니다. 서버가 제공한 인증서 도메인을 사용하고 IP를 SNI에 자동으로 복사하지 마세요.

WebSocket의 Host와 SNI는 반드시 같아야 하나요?

절대적인 규칙은 없습니다. SNI는 TLS 단계의 이름과 인증서를 결정하고 Host는 HTTP 계층의 라우팅을 결정합니다. 진입점 설정에 따라 두 값이 같을 수도, 다를 수도 있으므로 구독 매개변수를 한 세트로 유지해야 합니다.

포트를 443에서 8443으로 바꾸면 핸드셰이크 실패를 해결할 수 있나요?

서버가 실제로 8443 포트를 수신 대기 중일 때만 가능합니다. 포트는 임의로 시도하는 최적화 항목이 아니며 잘못 입력하면 대개 연결 거부 또는 시간 초과가 발생합니다.

구독을 업데이트한 뒤 이름 불일치가 발생하면 어떻게 해야 하나요?

업데이트 전후의 주소, SNI, 전송 방식, TLS 활성화 여부를 먼저 비교해 이름만 같고 매개변수가 다른 노드를 선택한 것은 아닌지 확인하세요. 그런 다음 올바른 그룹을 다시 업데이트하고 이전에 수동으로 만든 복사본은 계속 사용하지 마세요.

불완전한 인증서 체인과 네트워크 중간 장비

서버는 일반적으로 사이트 인증서와 필요한 중간 인증서를 함께 전송하고, 클라이언트는 시스템 또는 커널의 신뢰 저장소에 있는 루트 인증서로 검증을 완료합니다. 서버가 사이트 인증서만 전송하면 중간 인증서를 캐시한 일부 기기에서는 일시적으로 작동해도, 새 기기에서는 unknown authority 오류가 발생할 수 있습니다. ‘일부 기기만 정상’이라는 사실만으로 서버의 체인 설정이 완전하다고 볼 수는 없습니다.

같은 기기에서 유선 네트워크와 모바일 네트워크를 각각 테스트하세요. 특정 네트워크에서만 실패한다면 DNS 해석 결과를 비교해 도메인이 서로 다른 진입점으로 해석되는지 확인하세요. 모든 네트워크와 여러 플랫폼에서 같은 시각에 동일한 인증서 체인 오류가 발생한다면 서버 설정 이상일 가능성이 더 높습니다. 기업용 프록시, HTTPS 검사 장비, 사용자 지정 인증서 환경도 실제로 수신하는 발급 체인을 바꿀 수 있습니다.

결론: 여러 기기 비교로 로컬 문제와 서버 문제를 빠르게 구분할 수 있습니다

같은 노드에서 Windows, Android, Linux 모두 동일한 인증서 체인 오류를 반환한다면 클라이언트를 반복해서 재설치하지 말고 원격 서버가 전송하는 전체 체인과 진입점 설정을 확인하세요.

인증서 검증 우회는 짧은 진단 테스트에만 사용하세요

v2rayN 및 관련 커널 설정의 allowInsecure는 인증서 검증에 실패하더라도 TLS 연결을 계속 허용한다는 뜻입니다. 만료된 인증서, 잘못된 SNI, 누락된 중간 인증서를 수정하지 않고 해당 검증 결과만 우회합니다. 연결이 복구되었다고 해서 장애 지점이 인증서 검증 단계에 있을 가능성만 확인된 것이며, 현재 매개변수가 올바르다는 뜻은 아닙니다.

이 옵션은 통제된 비교 테스트에 적합합니다. 주소, 포트, 프로토콜, 전송 방식, 라우팅은 그대로 유지하고 인증서 검증 설정만 전환하세요. 커널을 시작해 요청을 한 번 완료한 뒤 검증을 복원하고 원본 로그를 바탕으로 시간, SNI, 인증서 체인을 수정합니다. SNI, Host, 포트, allowInsecure를 동시에 바꾸면 테스트 결과를 판단할 수 없습니다.

  1. 원본 노드의 복사본을 저장하고 현재 allowInsecure 상태를 기록하세요.
  2. 테스트 대상의 출처가 분명하며 다른 연결 매개변수를 함께 수정하지 않았는지 확인하세요.
  3. 일시적으로 활성화한 뒤 커널을 다시 시작하고 기존 x509 오류가 사라지는지 확인하세요.
  4. 여전히 시간 초과가 발생하면 DNS, TCP 포트, 전송 방식, 서버 상태를 계속 점검하세요.
  5. 연결이 복구되면 즉시 인증서 검증을 복원하고 시스템 시간, SNI 또는 전체 인증서 체인을 수정하세요.

검증을 장기간 우회하면 원격 신원의 핵심 확인 절차를 잃게 됩니다. 특히 노드 주소가 DNS를 통해 여러 진입점으로 연결될 때 클라이언트는 인증서 이름과 발급 체인으로 현재 연결이 의도한 서비스에 도달했는지 더 이상 판단할 수 없습니다. 구독 필드와 서버 설정을 일치시키고 시스템 신뢰 저장소와 시간을 정상적으로 동기화하는 것이 더 안전합니다.

테스트 결과 판단할 수 있는 내용 다음 단계
활성화 직후 연결 복구 문제가 인증서 검증 단계에 집중됨 검증을 복원하고 시간, 이름, 인증서 체인 확인
활성화 후에도 시간 초과 인증서 검증만의 문제는 아님 DNS, 포트, 패킷 손실, 전송 매개변수 확인
활성화 후 프로토콜 오류 발생 TLS는 통과했지만 상위 설정이 일치하지 않음 UUID, 프로토콜, Path, Host 또는 serviceName 확인
특정 네트워크 환경에서만 실패 경로 또는 해석 결과가 다를 수 있음 DNS, IPv4, IPv6 및 원격 진입점 비교

재현 가능한 최종 점검 순서

인증서 문제는 여러 매개변수를 동시에 변경하면 원인을 추적하기 가장 어렵습니다. 실제로는 동일한 노드와 네트워크를 유지하고 시점을 기록하면서 로그에서 처음 나타나는 하위 수준 오류를 기준으로 삼아야 합니다. 각 단계를 완료할 때마다 커널을 재시작하고 같은 요청을 반복해야 결과를 비교할 수 있습니다.

  1. 시스템 시간 확인: 날짜, 시간대, 네트워크 시간을 동기화하고 오차를 수 초 이내로 줄이세요. 몇 분 또는 몇 시간 차이가 나서는 안 됩니다.
  2. 해석 결과 확인: 노드 도메인이 해석되는지 확인하고 IPv4와 IPv6가 예상한 진입점을 가리키는지 판단하세요.
  3. TCP 포트 확인: 구독에 지정된 443, 8443 또는 기타 포트를 확인하고 임의로 바꾸지 마세요.
  4. TLS 활성화 여부 확인: 노드가 TLS를 요구하면 반드시 활성화하고, 비TLS 진입점에는 TLS를 강제로 적용하지 마세요.
  5. SNI 확인: 구독에 지정된 인증서 이름을 사용하고 노드 주소, 별칭, Host, serviceName을 구분하세요.
  6. 인증서 유효 기간 확인: 현재 UTC 시간과 인증서의 시작·종료 시간을 비교해 로컬 시계 문제인지 서버 인증서 만료인지 판단하세요.
  7. 인증서 체인 확인: 서버가 필요한 중간 인증서를 전송하는지 확인하고 여러 플랫폼에서 비교 테스트를 진행하세요.
  8. 전송 매개변수 확인: WebSocket의 Path와 Host, gRPC의 serviceName, REALITY 관련 필드는 한 세트로 일치해야 합니다.
  9. 짧은 비교 검증: 원인을 찾는 동안에만 allowInsecure를 전환하고 테스트가 끝나면 인증서 검증을 복원하세요.
  10. 원본 구독으로 돌아가기: 수동 수정이 지나치게 많아졌다면 올바른 그룹을 다시 가져오고 테스트 설정은 하나만 남기세요.

위 단계를 완료하면 오류는 대개 세 가지로 분류됩니다. 로컬 시간 또는 신뢰 환경 이상, 노드 필드와 진입점의 불일치, 서버 인증서 또는 수신 설정 이상입니다. 첫 번째 유형만 로컬에서 직접 해결할 수 있고, 두 번째는 올바른 구독 매개변수로 되돌려야 하며, 세 번째는 서버에서 인증서를 갱신하거나 인증서 체인을 보완하고 진입점 설정을 수정해야 합니다.

결론: 인증서 오류는 발생한 연결 단계에 따라 처리하세요

먼저 로그로 DNS, TCP, TLS, 프록시 프로토콜을 구분한 다음 ‘시간 → SNI → 유효 기간 → 인증서 체인 → 전송 매개변수’ 순서로 확인하세요. 검증 우회는 변수를 통제한 진단 테스트에 한 번만 사용하고 최종 설정으로 삼지 마세요.

클라이언트 다운로드