v2rayN, v2rayNG 또는 v2flyNG에서 TLS 핸드셰이크 실패, 인증서 만료, 도메인 불일치가 발생한 경우에 유용한 안내입니다. 로그가 구독 업데이트에서 나온 것인지 노드 연결에서 나온 것인지 먼저 확인한 뒤 시간, 주소와 포트, SNI, 인증서 체인, 전송 설정을 차례로 점검하세요. 어떤 설정은 클라이언트에서 수정할 수 있고 어떤 문제는 노드 관리자가 해결해야 하는지, allowInsecure를 상시 연결 설정으로 사용하면 안 되는 이유도 확인할 수 있습니다.
먼저 TLS 오류가 발생한 연결을 확인하세요
‘핸드셰이크 실패’는 결과일 뿐, 원인을 하나로 특정하지 않습니다. 일반적인 TLS 연결은 서버 주소를 확인하고 TCP 연결을 맺은 다음 TLS 설정을 협상하고 인증서를 검증합니다. 프록시 프로토콜 인증과 실제 트래픽 전달은 대개 그 이후에 이뤄집니다. 도메인 확인 실패, 443 포트 연결 불가, 프로토콜 인증 거부도 클라이언트에는 연결 실패로 표시될 수 있지만, 이런 경우 인증서 설정을 바꿔도 해결되지 않습니다.
오류가 어떤 작업 직후 발생했는지 먼저 확인하세요. ‘구독 업데이트’를 누른 뒤 인증서 오류가 나타났다면 구독 서버와의 HTTPS 연결 문제입니다. 노드를 선택해 웹에 접속할 때 핵심 로그에 x509가 표시된다면 프록시 아웃바운드 TLS 인증서 검증 실패일 수 있습니다. 노드 편집 화면의 allowInsecure는 일반적으로 구독 다운로드에 사용되는 HTTPS 검증에는 영향을 주지 않습니다.
- 구독 업데이트 실패: 업데이트 시각과 구독 서비스 도메인을 기록하고 시스템 시간 및 구독 서비스 인증서를 확인하세요. 구독 주소 전체를 공개하지 마세요.
- 노드 연결 실패: v2rayN 메인 화면에서 로그 출력을 확인하거나, v2rayNG 메뉴의 ‘로그’에서 같은 시각의 아웃바운드 오류를 찾으세요.
- 브라우저에서만 오류 발생: 오류가 표시된 도메인이 접속하려는 웹사이트의 도메인인지 확인하세요. 웹사이트 인증서 오류를 곧바로 프록시 노드 문제로 단정하지 마세요.
오류 메시지로 문제 범위 좁히기
코어와 버전에 따라 오류 메시지 앞뒤에 연결 정보가 추가될 수 있습니다. 아래는 흔히 볼 수 있는 핵심 오류이며 로그 전체가 똑같이 표시될 필요는 없습니다. 오류 문구로 원인 범위를 좁힐 수는 있지만, 하나의 메시지만으로 원인을 확정하기는 어렵습니다.
오류: x509: certificate has expired or is not yet valid
원인과 해결: 기기 시간이 인증서 유효 기간과 맞지 않거나 서버 인증서가 실제로 만료된 경우입니다. 먼저 시스템 시간을 동기화하세요. 시간이 정확한데도 문제가 반복되면 관리자에게 인증서 유효 기간과 갱신 후 서버 재시작 여부를 확인해 달라고 요청하세요.
오류: x509: certificate is valid for edge.example, not node.example
원인과 해결: 클라이언트가 검증하는 이름이 인증서 적용 범위에 포함되지 않았습니다. 서버에서 요구하는 SNI와 인증서 SAN을 확인하세요. 연결 주소가 node.example이라는 이유만으로 SNI도 같은 주소로 설정하지 마세요.
오류: x509: certificate signed by unknown authority
원인과 해결: 신뢰 체인을 구성하지 못한 경우입니다. 중간 인증서 누락, 자체 서명 인증서, 오래된 신뢰 저장소 또는 네트워크에서의 인증서 교체가 원인일 수 있습니다. 다른 기기와 네트워크에서도 비교한 뒤 서버가 완전한 인증서 체인을 제공하는지 확인하세요.
오류: remote error: tls: handshake failure
원인과 해결: 상대 서버가 핸드셰이크를 거부했습니다. SNI, 프로토콜 버전, 클라이언트 지문 또는 서버 정책이 원인일 수 있습니다. 기존 노드 설정에 따라 항목을 하나씩 복원하고, 이 오류를 곧바로 인증서 만료로 해석하지 마세요.
오류: tls: first record does not look like a TLS handshake
원인과 해결: 대상 포트에서 TLS가 아닌 데이터가 반환됐습니다. 포트와 TLS 사용 여부를 확인하세요. 예를 들어 일반 HTTP를 제공하는 80 포트를 TLS 서비스용 443 포트처럼 취급하면 안 됩니다.
EOF, connection reset by peer, i/o timeout은 원인 범위가 더 넓습니다. 연결 중단, 방화벽, 잘못된 포트, 서버 장애 등이 원인일 수 있으므로 이 문구만 보고 인증서 검증 생략을 켜지 마세요. 먼저 TCP 연결이 가능한지 확인한 뒤 TLS 문제를 살펴보세요.
시스템 시간과 노드 설정을 확인하는 5단계
한 번에 설정 하나만 바꾸고 같은 요청으로 다시 테스트하세요. 먼저 원래 설정을 저장하세요. 주소, 포트, SNI, 지문을 한꺼번에 바꾸면 연결에 성공해도 무엇이 문제를 해결했는지 알 수 없습니다. 아래 Windows 경로는 Windows 11 중국어 인터페이스를 기준으로 했습니다. 클라이언트 버전과 화면에 따라 항목 위치는 달라질 수 있지만 의미는 같습니다.
-
시간 동기화
Windows에서 ‘설정’ → ‘시간 및 언어’ → ‘날짜 및 시간’으로 이동해 ‘자동으로 시간 설정’을 켜고 ‘지금 동기화’를 누르세요. Android에서는 일반적으로 ‘설정’ → ‘시스템’ → ‘날짜 및 시간’에서 자동 시간 설정을 켭니다. 제조사에 따라 ‘추가 설정’에 있을 수 있습니다. 시간대 이름뿐 아니라 실제 날짜와 시각도 확인하세요.
-
포트 확인
v2rayN 메인 화면에서 현재 노드를 두 번 클릭해 편집 화면을 여세요. v2rayNG에서는 노드 목록에서 해당 노드의 편집 아이콘을 누르면 됩니다. 노드 제공자가 안내한 ‘주소’와 ‘포트’를 대조하세요. TLS에서 443을 흔히 사용하지만 8443이나 다른 포트도 정상일 수 있습니다. 인증서 오류가 났다고 포트를 무조건 443으로 바꾸지 마세요.
-
SNI 확인
노드 편집 화면의 TLS 또는 전송 보안 항목에서 ‘SNI’ 또는 ‘serverName’ 값을 확인하세요. 서버가 요구하는 도메인을 입력하고
https://, 포트, 경로, 공백은 넣지 마세요. 연결 주소와 SNI는 서로 다를 수 있으므로 임의로 추측하지 말고 노드 설정을 따르세요. -
인증서 검증 복원
‘안전하지 않은 연결 허용’ 또는 ‘allowInsecure’ 설정을 확인하세요. 일반적으로 꺼야 하며 값은
false여야 합니다. 제공자가 안내한 지문과 ALPN 설정도 복원하세요. 원래 설정에 해당 값이 없었다면 오류를 없애기 위해 임의로 추가하지 마세요. -
재연결 후 로그 확인
노드를 저장하고 연결을 다시 시작하세요. v2rayNG에서는 연결을 중지했다가 다시 시작할 수 있습니다. v2rayN에서는 저장 후 수정한 노드가 선택되어 있는지 확인하고 다시 테스트하세요. 오류가 인증서 오류에서 연결 시간 초과나 프로토콜 인증 오류로 바뀌었는지 기록하세요. 실패 단계가 달라졌다는 뜻입니다.
인증서 검증에는 실제 시각이 사용됩니다. 표시되는 시간대만 바꾸고 잘못된 시스템 시계를 그대로 두면 유효 기간 문제는 대개 해결되지 않습니다. 예를 들어 시스템 날짜가 2025년인데 인증서 유효 기간이 2026년부터라면 ‘아직 유효하지 않음’ 오류가 발생합니다. 반대로 시스템 날짜가 미래로 설정되면 유효한 인증서도 만료된 것으로 판단될 수 있습니다.
# Linux: 시스템 시간과 동기화 상태 확인
timedatectl status
# Linux: 관리자 권한으로 시스템의 네트워크 시간 동기화 기능 활성화
sudo timedatectl set-ntp true
Linux의 두 번째 명령은 시스템에서 사용 가능한 시간 동기화 서비스를 제공해야 실행할 수 있습니다. 설정 후에는 동기화 상태를 다시 확인하세요. macOS에서는 ‘시스템 설정’ → ‘일반’ → ‘날짜 및 시간’에서 자동 설정을 확인할 수 있습니다. 시간이 정확하고 특정 노드에서만 오류가 난다면 기기 시간을 반복해서 바꿀 필요 없이 서버 인증서와 노드 설정을 확인하세요.
SNI, 연결 주소, Host는 서로 다른 항목입니다
SNI는 TLS 핸드셰이크에서 클라이언트가 서버에 전달하는 이름으로, 가상 호스트와 인증서를 선택하는 데 자주 사용됩니다. 일반 TLS 설정의 serverName은 보통 인증서 검증 이름을 지정하는 역할도 합니다. 연결 주소는 서버에 접속하는 데 쓰이고, HTTP Host는 그보다 상위 계층인 HTTP 요청에 속합니다. 서비스 구성에 따라 세 값이 같을 수도, 각각 다를 수도 있습니다.
| 항목 | 적용 단계 | 설정 기준 | 흔한 오류 |
|---|---|---|---|
| 주소와 포트 | 주소 확인 및 연결 설정 | 실제 노드 접속 주소(예: 443 또는 8443) | 구독 웹사이트 주소를 노드 주소로 입력 |
| SNI / serverName | TLS 핸드셰이크 및 이름 검증 | 서버에서 허용하는 이름과 인증서 SAN | 프로토콜 접두사나 경로를 추가하거나 임의로 도메인 변경 |
| WebSocket Host | HTTP 업그레이드 요청 | 리버스 프록시의 가상 호스트 설정 | Host를 바꾸면 SNI도 자동으로 수정된다고 생각함 |
| WebSocket path | 요청 경로 일치 여부 | 서버에서 지정한 경로 | 경로가 잘못됐는데 인증서만 점검 |
예를 들어 접속 주소가 node.example이고 서버에서 요구하는 SNI가 edge.example이라면 접속은 기존 주소로 하되 일반 TLS 인증서는 edge.example을 포함해야 합니다. 여기서 사용한 .example 도메인은 설명용 예약 도메인이며 실제 노드 주소가 아닙니다. IP로 직접 연결하면서 올바른 검증 이름을 설정하지 않으면 인증서가 도메인만 포함하는 경우 이름 불일치가 발생할 수 있습니다.
결론: 항목을 대조한 뒤 도메인을 수정하세요
이름 불일치가 발생하면 먼저 관리자에게 주소, SNI, HTTP Host 값을 각각 확인하세요. 실제 인증서가 포함하고 서버가 허용하는 이름만 사용할 수 있습니다. 유명 웹사이트 도메인으로 바꾼다고 일반 TLS 설정 문제가 해결되지는 않습니다.
‘위장 도메인’은 모든 설정에서 같은 항목을 가리키는 기술 용어가 아닙니다. 설정에 따라 SNI를 뜻할 수도, HTTP Host나 REALITY 서버 이름을 뜻할 수도 있습니다. 먼저 전송 보안 방식부터 확인하세요. 일반 TLS의 CA 인증서 검증과 REALITY의 인증 매개변수는 서로 다른 방식으로 점검해야 합니다.
인증서 체인, 지문, 전송 설정 확인하기
같은 도메인이 브라우저에서 열린다고 해서 프록시 노드의 TLS 설정까지 올바르다는 뜻은 아닙니다. 브라우저는 443에 연결하고 노드는 8443에 연결할 수 있으며, 두 요청의 SNI나 접속 주소, 신뢰 저장소가 서로 다를 수도 있습니다. 같은 접속 지점과 같은 이름을 기준으로 비교해야 진단에 도움이 됩니다.
- 완전한 인증서 체인: 서버는 일반적으로 최종 인증서와 필요한 중간 인증서를 함께 보내야 합니다. 중간 인증서가 누락되면 일부 기기는 신뢰 체인을 구성하지만 다른 기기에서는 unknown authority 오류가 발생할 수 있습니다.
- 도메인 포함 여부: 인증서의 Subject Alternative Name을 확인하세요.
*.example.com은 일반적으로a.example.com을 포함하지만a.b.example.com이나example.com까지 자동으로 포함하지는 않습니다. - TLS 버전: TLS 1.2와 TLS 1.3은 프로토콜 버전이지 클라이언트 버전 번호가 아닙니다. 양쪽이 공통으로 지원하는 버전이나 암호화 스위트가 없으면 인증서 검증 전에 연결이 실패할 수 있습니다.
- 클라이언트 지문: Xray에서는 지문 옵션으로
chrome처럼 ClientHello 특성을 조정할 수 있습니다. 서버 인증서 지문과는 다르며 인증을 끄는 설정도 아닙니다. 지원 범위는 현재 사용하는 코어를 기준으로 확인하세요. - ALPN:
h2와http/1.1은 애플리케이션 프로토콜 협상에 사용됩니다. gRPC, WebSocket, 일반 TCP는 배포 설정이 서로 다르므로 다른 노드의 ALPN 목록을 그대로 복사하지 마세요.
기기에 OpenSSL이 설치되어 있다면 아래 명령으로 일반 TLS 접속 지점을 확인할 수 있습니다. 예시에는 예약 도메인을 사용했으므로 실행 전에 실제 접속 주소와 SNI에 맞게 수정하세요. 이는 프록시 프로토콜 테스트가 아니며 REALITY 노드의 사용 가능 여부를 확인하는 방법도 아닙니다.
openssl s_client \
-connect node.example:443 \
-servername edge.example \
-verify_hostname edge.example \
-verify_return_error \
-showcerts
-connect는 접속 대상을 지정하고 -servername은 SNI를 전송하며 -verify_hostname은 검증할 이름을 명시합니다. SNI만 전송한다고 도메인 일치 여부까지 검증되는 것은 아닙니다. 인증서 유효 기간, 이름, 검증 결과를 확인하세요. 도구가 사용하는 신뢰 저장소가 클라이언트와 다를 수 있으므로 결과는 문제를 좁히는 참고 자료로만 활용하세요.
allowInsecure를 계속 켜 두면 안 되는 이유
일반적인 V2Ray/Xray TLS 설정에서 allowInsecure: true는 서버 인증서 체인과 이름을 정상적으로 검증하지 않도록 합니다. 연결이 암호화될 수는 있지만, 클라이언트는 연결 상대의 신원을 신뢰할 만한 방식으로 확인하지 못합니다. 데이터가 암호화되어 전송된다고 해서 상대가 의도한 서버라는 뜻은 아닙니다.
| 문제 | 켜면 달라질 수 있는 점 | 올바른 조치 |
|---|---|---|
| 인증서 만료 또는 이름 불일치 | 검증 오류를 우회할 수 있음 | 시간과 SNI를 바로잡거나 서버 인증서 갱신 |
| 자체 서명 인증서를 신뢰하지 않음 | 신뢰 체인 오류를 우회할 수 있음 | 통제된 환경의 요구사항에 맞춰 신뢰 가능한 인증서나 지원되는 신뢰 설정을 구성 |
| 포트 연결 불가 또는 연결 시간 초과 | 네트워크 연결 문제는 해결할 수 없음 | 포트, 네트워크, 서비스 상태 확인 |
| 경로 또는 인증 매개변수 오류 | 상위 프로토콜 설정은 해결할 수 없음 | 올바른 경로와 노드 인증 정보 복원 |
| REALITY 인증 실패 | REALITY 인증 절차를 대신할 수 없음 | REALITY 전용 매개변수와 코어 지원 여부 확인 |
통제된 진단을 위해 잠시 켰더니 연결됐다면 인증서 검증이 실패에 관여했을 가능성만 확인한 것입니다. 노드의 보안성이나 모든 문제가 해결됐다는 뜻은 아닙니다. 진단 중에는 민감한 트래픽을 전송하지 말고, 확인이 끝나면 즉시 끄세요. 원래 오류를 기준으로 구체적인 원인을 해결하세요. 장기간 검증을 생략해 ‘연결되는 상태’를 유지하기보다 로그와 인증서를 확인해 원인을 찾는 편이 안전합니다.
결론: 검증을 복원해야 해결된 것입니다
allowInsecure를 false로 되돌린 뒤 같은 노드로 다시 연결하세요. 오류가 계속되면 시간, 이름, 신뢰 체인을 차례로 바로잡으세요. 정상적으로 검증을 통과하고 실제 요청까지 성공해야 인증서 문제 해결이 완료된 것입니다.
자주 묻는 질문과 문제 정보 공유
PC에서는 연결되는데 Android에서 인증서를 신뢰할 수 없다고 나오는 이유는 무엇인가요?
먼저 두 기기에서 같은 노드, SNI, 네트워크를 사용하고 자동 시간 설정이 켜져 있는지 확인하세요. 설정이 같다면 시스템 신뢰 저장소의 차이와 서버의 중간 인증서 누락 여부를 확인하세요. PC의 인증서 검증 생략 설정을 그대로 복사하지 마세요.
구독을 업데이트한 뒤 갑자기 핸드셰이크가 실패합니다. 재설치해야 하나요?
먼저 노드 편집 화면에서 주소, 포트, TLS 유형, SNI가 바뀌었는지 비교하고 새 노드가 선택되어 있는지 확인하세요. 재설치로 서버의 만료된 인증서가 해결되는 경우는 드뭅니다. 오류 원문을 저장한 다음 관리자에게 설정을 확인해 달라고 요청하세요.
휴대폰 핫스팟으로 바꾸면 왜 정상 연결되나요?
네트워크 경로가 연결에 영향을 줄 가능성이 있지만 원인이 확정된 것은 아닙니다. 노드 설정을 유지한 채 두 네트워크에서 나타나는 오류를 각각 기록하세요. 특정 네트워크에서 알 수 없는 발급 기관 오류가 발생한다면 HTTPS 검사나 인증서 교체가 있는지 확인하세요. 출처를 알 수 없는 루트 인증서를 무작정 신뢰하지 마세요.
지연 시간 테스트에 성공하면 인증서도 정상이라는 뜻인가요?
반드시 그렇지는 않습니다. TCP 지연 시간 테스트는 포트 연결만 확인하며 TLS 검증이나 프록시 요청까지 수행하지 않을 수 있습니다. 테스트 종류를 확인한 뒤 실제 요청을 보내고 코어 로그를 살펴보세요. 지연 시간 숫자 하나만으로 연결이 정상이라고 판단하지 마세요.
인증서를 갱신했는데도 클라이언트에서 만료됐다고 표시하는 이유는 무엇인가요?
관리자에게 새 인증서를 서버에 다시 불러왔는지, 다른 접속 지점에서 여전히 이전 인증서를 제공하는지 확인해 달라고 요청하세요. 클라이언트에서는 시간과 접속 주소도 확인해야 합니다. 여러 서버나 IPv4·IPv6 접속 지점의 설정이 서로 다르면 일부 연결에서만 문제가 생길 수 있습니다.
추가 지원이 필요하다면 문제를 재현하는 데 필요한 최소한의 정보만 공유하세요. 설정 파일 전체를 올릴 필요는 없으며 구독 링크가 포함된 화면을 공유하지 마세요. 아래 목록을 참고해 정보를 정리한 뒤 사이트의 문제 해결에서 계속 확인할 수 있습니다. 항목의 의미가 불분명하다면 개념 빠른 참조를 확인하세요.
- 클라이언트 이름과 실제 버전, 사용 중인 코어의 이름과 버전, 운영체제 버전.
- 구독 업데이트, 노드 테스트, 실제 접속 중 어느 작업에서 발생했는지와 발생 시각, 민감 정보를 가린 오류 원문.
- 포트, 전송 유형, TLS 또는 REALITY 유형, SNI와 연결 주소의 일치 여부. 노드 인증 정보는 공유하지 마세요.
- 시스템 시간 동기화 여부, 네트워크를 바꾸었을 때 재현되는지, 다른 기기에서는 정상인지, 시도한 개별 설정 변경 사항.