V2Ray TLS 핸드셰이크 실패·인증서 오류 해결: 시스템 시간, SNI 설정, allowInsecure

인증서 만료, x509 오류, 핸드셰이크 시간 초과는 주로 시스템 시간 오차, SNI와 인증서 도메인 불일치, 잘못된 지문 설정 때문에 발생합니다. 항목별 확인 방법과 올바른 설정을 안내합니다.

핵심 내용

v2rayN, v2rayNG, v2flyNG의 TLS 연결 문제를 점검합니다. 먼저 로그를 보고 인증서 검증 실패와 연결 시간 초과를 구분한 다음, 기기 시간, 노드 SNI, 서버 인증서 체인, 지문 설정을 확인하세요. 한 번에 하나의 항목만 수정하고 연결이 복구되면 인증서 검증을 계속 활성화해 두세요. 노드가 REALITY를 사용한다면 전용 인증 매개변수를 확인해야 하며, 일반 TLS의 인증서 처리 방법을 그대로 적용하면 안 됩니다.

먼저 확인할 것: TLS 오류가 발생한 단계

TLS 핸드셰이크는 연결 수립과 프록시 프로토콜 인증 사이에서 진행됩니다. VMess와 VLESS는 프록시 프로토콜이고 TLS는 전송 보안 계층이므로 같은 설정이 아닙니다. 노드가 선택되어 있고 코어가 정상 실행 중이라는 사실은 로컬 프로그램이 시작되었다는 뜻일 뿐, 원격 인증서 검증이 통과했다는 의미는 아닙니다. 먼저 선택한 노드의 ‘전송 보안’이 TLS인지 REALITY인지 확인한 뒤 이 문서의 해당 절차를 따르세요.

서버 이름 확인원격 포트 연결TLS 협상인증서 검증프록시 프로토콜 인증

v2rayN 메인 화면의 로그 영역에서 실패한 요청의 시각을 찾고, 바깥쪽의 ‘연결 실패’ 메시지만 보지 말고 가장 안쪽에 표시된 원인을 복사하세요. v2rayNG와 v2flyNG에서는 사이드 메뉴의 ‘로그’로 확인할 수 있습니다. 버전에 따라 메뉴 이름은 다를 수 있으니 클라이언트 버전, 코어 종류, 노드 보안 유형, 전체 오류 내용을 기록하세요. 로그를 공유하기 전에는 구독 주소, 사용자 식별 정보, 인증 정보를 가리세요.

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

원인 및 해결: 기기의 현재 시간이 인증서 유효 기간에 포함되지 않습니다. 먼저 기기 시간을 맞추세요. 시간이 정확하다면 서버 관리자에게 인증서 만료 여부와 갱신 후 새 인증서가 적용되었는지 확인하도록 요청하세요.

오류: x509: certificate signed by unknown authority

원인 및 해결: 인증서 체인을 신뢰할 수 있는 루트 인증서까지 연결할 수 없습니다. 서버가 중간 인증서를 보내는지 확인하고, 자체 서명 인증서, 오래된 신뢰 저장소, 네트워크의 TLS 검사 장비도 점검하세요.

오류: context deadline exceeded

원인 및 해결: 제한 시간 안에 작업이 완료되지 않았다는 뜻입니다. 이 메시지만으로 인증서 문제라고 단정할 수는 없습니다. 앞뒤 로그를 함께 확인해 도메인 조회, 원격 포트, 핸드셰이크 진행 상황을 점검하세요.

시스템 시간 동기화: 기기 시간 오류부터 확인

인증서에는 유효 시작 시각과 만료 시각이 기록됩니다. 기기의 연도·날짜 또는 실제 시스템 시계가 잘못되면 정상 인증서도 ‘아직 유효하지 않음’ 또는 ‘만료됨’으로 판정될 수 있습니다. 화면에 표시되는 시간대만 바꾸는 것으로 실제 시계 오차가 해결되지는 않습니다. 시간대는 시간 표시 방식에 영향을 주지만, 인증서 검증은 실제 시각을 기준으로 합니다.

  1. 날짜 확인

    Windows에서 ‘설정’ → ‘시간 및 언어’ → ‘날짜 및 시간’을 열어 연도, 월, 날짜, 시간대를 확인하세요. 눈에 띄는 오류를 먼저 바로잡은 다음 인터넷 시간 동기화를 시도하세요.

  2. 시계 동기화

    ‘자동으로 시간 설정’을 켜고 ‘추가 설정’ 또는 ‘시계 동기화’ 영역에서 ‘지금 동기화’를 누르세요. Android에서는 시스템 ‘설정’ → ‘날짜 및 시간’으로 이동해 ‘자동으로 시간 설정’을 활성화하세요. 일부 기기에서는 이 항목이 ‘시스템’ 메뉴 안에 있습니다.

  3. 동기화 결과 확인

    Windows에서 마지막으로 동기화에 성공한 시각을 확인하세요. 동기화에 실패하면 관리자 권한 터미널에서 아래 명령을 실행해 시간 서비스를 점검하세요. 네트워크에서 시간 동기화 트래픽이 허용되지 않는 경우 먼저 네트워크나 서비스 상태를 해결해야 합니다.

  4. 다시 연결

    현재 연결을 끊고 같은 노드를 다시 시작한 뒤 새 요청을 한 번 보내세요. 새 로그의 타임스탬프를 확인하고, 로그 창에 남아 있는 이전 오류로 수정 결과를 판단하지 마세요.

w32tm /query /status
w32tm /resync

위 명령은 Windows 시간 서비스용이며 프록시 코어 명령이 아닙니다. 서비스가 시작되지 않았다는 메시지가 나오면 시스템의 ‘서비스’에서 ‘Windows Time’을 확인하세요. 조직 정책으로 관리되는 PC는 관리자가 지정한 시간 소스를 사용해야 합니다. 재부팅 후 날짜가 계속 초기화된다면 노드를 바꾸기보다 기기의 시계 유지 기능과 시스템 시간 설정을 확인하세요.

SNI 설정: 연결 주소와 인증서 도메인은 다를 수 있습니다

노드의 ‘주소’는 연결할 서버를 지정하고, ‘포트’는 연결할 서비스를 지정합니다. SNI는 보통 코어의 serverName 필드로 설정하며 TLS 가상 호스트 선택과 인증서 이름 검증에 사용됩니다. 연결 주소가 IP여도 SNI에는 도메인을 지정할 수 있습니다. 원격 서비스가 해당 도메인에 맞는 인증서를 제공한다면 이 조합은 문제가 없습니다.

  • 주소: 구독 또는 서버 설정에 지정된 호스트 이름이나 IP를 입력하세요. 주소와 SNI를 임의로 바꾸어 쓰지 마세요.
  • 포트: 노드 설정에 지정된 포트를 입력하세요. 443은 흔히 사용하는 TLS 포트지만 필수값은 아니므로 모든 노드의 포트를 이 값으로 바꾸면 안 됩니다.
  • SNI / serverName: 서버에서 요구하는 인증서 도메인을 입력하세요. 예를 들면 안내에 나온 example.com과 같은 형식입니다. 이 값은 형식을 보여 주기 위한 예시일 뿐이며 실제 값은 노드 설정을 따라야 합니다.
  • 입력 형식: 호스트 이름만 입력하세요. https://, 경로, 쿼리 매개변수, :443은 붙이지 마세요.
  • 인증서 적용 범위: 최신 인증서 검증은 보통 SAN을 확인합니다. 와일드카드 *.example.com은 일반적으로 a.example.com과 일치하지만 루트 도메인 example.com이나 a.b.example.com과는 일치하지 않습니다.

v2rayN 메인 화면에서 대상 노드를 두 번 클릭해 편집 창을 열고, ‘전송 보안’의 TLS 설정에서 ‘SNI’ 또는 ‘serverName’을 확인하세요. v2rayNG와 v2flyNG에서도 노드 편집 화면의 같은 이름의 필드를 확인하면 됩니다. 버전에 따라 한 가지 이름만 표시될 수 있습니다. WebSocket의 ‘Host’를 SNI로 착각하지 마세요. ‘Host’는 HTTP 요청 헤더이고 SNI는 TLS 핸드셰이크에서 사용됩니다.

인증서 체인과 핸드셰이크 시간 초과: 이름·신뢰·포트를 각각 확인

이름 불일치와 알 수 없는 발급 기관은 서로 다른 문제입니다. 전자는 SNI가 인증서 SAN 범위에 포함되는지 확인하고, 후자는 인증서 체인이 완전한지와 발급 기관이 현재 환경에서 신뢰되는지 확인해야 합니다. 브라우저에서 같은 도메인의 웹페이지가 열리더라도 프록시 연결이 정상이라는 뜻은 아닙니다. 브라우저는 다른 포트나 주소에 연결했거나, 다른 신뢰 저장소와 인증서 체인 보완 방식을 사용했을 수 있습니다.

로그 단서우선 확인할 항목점검 위치
expired / not yet valid실제 시스템 시간, 인증서 유효 기간기기 시간 설정, 서버 인증서 배포
certificate is valid for…not…SNI가 인증서 SAN과 일치하는지노드 TLS 필드, 서버 가상 호스트
unknown authority중간 인증서, 루트 신뢰, 자체 서명 인증서서버의 전체 인증서 체인, 관리되는 신뢰 설정
handshake failureTLS 매개변수, 클라이언트 지문, 서버 정책노드 전송 설정, 서버 핸드셰이크 로그
timeout / deadline exceeded이름 조회, 포트 연결 가능 여부, 패킷 손실, 서비스 응답네트워크 경로, 원격 서버 리스닝 상태와 방화벽

Windows에서는 PowerShell로 대상 TCP 포트를 확인할 수 있습니다. 아래 도메인과 포트는 명령 형식 예시이므로 선택한 노드의 실제 주소와 포트로 바꾸세요. TcpTestSucceeded가 참이면 TCP 연결에 성공했다는 뜻일 뿐, 인증서·SNI·프록시 인증이 올바르다는 의미는 아닙니다.

Test-NetConnection -ComputerName example.com -Port 443

OpenSSL이 설치된 환경에서는 원격 서버가 보내는 인증서 체인을 추가로 확인할 수 있습니다. 명령의 연결 대상과 SNI는 서로 달라도 되며 각각 노드의 ‘주소’와 ‘serverName’에 해당합니다. 아래 예시에서는 둘 다 설명용 도메인으로 지정하고 이름 검사를 명시적으로 활성화했습니다.

openssl s_client -connect example.com:443 -servername example.com -showcerts -verify_hostname example.com -verify_return_error
  • 반환된 인증서의 SAN, 유효 기간, 검증 오류를 확인하세요. 인증서가 출력된다는 이유만으로 검증에 성공했다고 판단하지 마세요.
  • 서버에서 인증서를 갱신했는데도 이전 인증서가 계속 반환된다면 인증서 파일 경로를 확인하고, 실제로 TLS를 종료하는 서비스가 설정을 다시 불러오도록 해야 합니다.
  • OpenSSL과 프록시 코어는 서로 다른 루트 신뢰 저장소를 사용할 수 있습니다. 도구의 결과는 원인 파악에 참고하되 클라이언트에서 최종적으로 다시 확인해야 합니다.

지문과 REALITY: 두 가지 점검 방식을 혼용하지 마세요

클라이언트 지문은 ClientHello의 표현 방식에 영향을 주지만, 잘못된 인증서 도메인이나 만료된 인증서, 누락된 중간 인증서를 해결하지는 않습니다. Xray와 V2Fly의 관련 기능이 완전히 같다고 가정해서는 안 됩니다. v2rayNG는 Xray 코어를, v2flyNG는 V2Fly 코어를 사용하므로 화면에 TLS 옵션이 있다고 해서 모든 매개변수가 호환되는 것은 아닙니다.

  • 일반 TLS 노드: 먼저 구독에 설정된 원래 지문 값을 복원하세요. 서버에서 지문을 명시적으로 요구하는 경우에만 안내된 값으로 설정하고, 여러 지문 값을 무작정 바꾸어 가며 시도하지 마세요.
  • 코어를 변경한 뒤: 로그에 알 수 없는 필드, 지원하지 않는 옵션, 설정 파싱 실패가 있는지 확인하세요. 이는 설정 호환성 문제이지 인증서 검증 문제가 아닙니다.
  • REALITY 노드: 서버에서 지정한 serverName, 공개 키 관련 매개변수, shortId, 지문을 확인하세요. 버전에 따라 화면에 표시되는 필드 이름이 다를 수 있으므로 해당 코어 문서와 서버 설정을 기준으로 삼으세요.
  • 값 설정 시 주의: REALITY의 대상 도메인을 임의로 추측하거나 일반 TLS의 ‘인증서 검증 건너뛰기’를 REALITY 인증 실패의 해결책으로 사용하지 마세요.

일반 TLS 노드가 특정 지문에서만 핸드셰이크에 성공한다면 서버의 접근 정책과 네트워크 중간 장비도 확인해야 합니다. 변경 전후의 전체 오류 내용을 저장해 두면 핸드셰이크 협상이 복구된 것인지, 테스트 요청이 애초에 다른 아웃바운드 경로를 이용한 것인지 구분할 수 있습니다. 점검하는 동안 같은 노드와 같은 대상 요청을 유지하고 라우팅 규칙, TUN, 시스템 프록시를 동시에 바꾸지 마세요.

allowInsecure 설정: 검증은 유지하고 근본 원인을 해결

일반 TLS 설정의 allowInsecure는 표준 인증서 검증을 건너뛸 수 있는지 제어합니다. 이 옵션을 켜도 트래픽은 암호화될 수 있지만 정상적인 인증서 체인 및 이름 검증으로 서버 신원을 확인할 수 없으므로, 서버 사칭이나 중간자 공격에 노출될 위험이 있습니다. 호환성을 높이거나 속도를 빠르게 하는 옵션이 아닙니다.

아래는 일반 TLS의 streamSettings 안에 있는 tlsSettings 객체 예시입니다. 전체 노드 설정이 아니며 REALITY에는 적용되지 않습니다. serverName은 서버에서 요구하는 실제 도메인으로 바꿔야 합니다. 예시를 모든 노드에 그대로 붙여 넣지 마세요.

{
  "serverName": "example.com",
  "allowInsecure": false
}
  • 검증을 건너뛴 뒤 연결이 복구되더라도 인증서 검증을 더 살펴봐야 한다는 뜻일 뿐, 원인이 시간·도메인 이름·신뢰 체인 중 무엇인지는 알 수 없습니다.
  • 옵션을 켠 뒤에도 시간 초과가 발생한다면 포트와 핸드셰이크 단계부터 다시 확인하세요. 이 옵션을 반복해서 켜고 끄더라도 연결할 수 없는 원격 서비스가 복구되지는 않습니다.
  • 문제를 해결한 뒤 노드 편집 화면에서 ‘안전하지 않은 연결 허용’이 꺼져 있는지 확인하고 연결을 끊었다가 다시 연결하세요.

자주 묻는 질문: 문제가 해결되었는지 확인하는 방법

시간 동기화에 성공했는데도 인증서가 만료되었다고 표시되는 이유는 무엇인가요?

새 로그가 이번 연결에서 생성되었는지 먼저 확인한 뒤 서버가 실제로 반환하는 인증서의 유효 기간을 살펴보세요. 기기 시간이 정확한데 인증서가 만료되었다면 서버에서 인증서를 갱신하고 다시 불러와야 합니다. 클라이언트만 재시작해도 원격 서버가 보내는 인증서는 바뀌지 않습니다.

주소에는 IP를, SNI에는 도메인을 입력해도 되나요?

가능합니다. 단, 해당 IP와 포트에서 그 도메인에 맞는 TLS 서비스를 제공해야 하고 인증서에도 해당 도메인이 포함되어야 합니다. 노드를 두 번 클릭해 ‘주소’, ‘포트’, ‘SNI’를 확인하세요. 필드 값을 서로 같아 보이게 하려고 SNI를 IP로 바꾸지 마세요.

웹페이지는 열리는데 클라이언트에서 unknown authority 오류가 발생하는 이유는 무엇인가요?

먼저 연결 주소, 포트, SNI를 비교한 뒤 서버가 중간 인증서 체인 전체를 보내는지 확인하세요. 브라우저와 프록시 코어는 서로 다른 신뢰 저장소나 인증서 체인 처리 방식을 사용할 수 있으므로 브라우저에서 정상적으로 열려도 클라이언트의 검증까지 통과한다고 볼 수 없습니다.

구독을 업데이트한 뒤 SNI가 원래 값으로 돌아가면 어떻게 하나요?

노드를 복제해 임시로 테스트하고, 정상 작동하는 필드 값을 기록한 다음 구독 제공자에게 원본 설정 오류를 알리세요. 원본이 수정되면 구독을 업데이트하고 SNI, 지문, 검증 옵션을 확인한 뒤 같은 노드에서 새 요청을 보내세요. 기존 연결만으로 결과를 판단하지 마세요.

로그에 TLS 오류가 더 이상 없는데도 웹페이지가 열리지 않는 이유는 무엇인가요?

프록시 프로토콜 인증, 라우팅 분기, DNS, 시스템 프록시 설정을 계속 확인하세요. 인증서 검증이 통과했다는 것은 TLS 계층이 완료되었다는 뜻일 뿐 VMess 또는 VLESS 인증, 대상 사이트 연결, 애플리케이션의 프록시 설정까지 올바르다는 의미는 아닙니다.

최종 확인은 다음 순서로 진행하세요. 시스템 시간이 정확한지 확인하고, 노드 필드가 서버 설정과 일치하는지 확인한 뒤, 인증서 검증을 켠 상태로 유지합니다. 다시 연결해 새 TLS 검증 오류가 로그에 없는지 확인하고 애플리케이션 요청이 예상한 아웃바운드로 전달되는지도 점검하세요. 변경한 필드 이름과 결과를 기록해 두면 다음 구독 업데이트나 코어 변경 때 항목별로 비교할 수 있습니다.

v2rayN 다운로드