nginx ssl handshake failed

nginx와 tomcat 웹/앱을 서비스하고있습니다

최근 크롬브라우저, 안드로이드 웹뷰에서


크롬: "서버에서 잘못된 응답을 전송했습니다", 

웹뷰: "웹페이지를 사용할 수 없음" 


둘다 SSL_PROTOCOL_ERROR 가 나타납니다.


에러내용: 

/var/log/nginx/error.log

---------------------

SSL_do_handshake() failed (SSL: error:14094085:SSL routines:SSL3_READ_BYTES:ccs received early) while SSL handshaking, client: 64.41.200.107, server: 0.0.0.0:443

SSL_read() failed (SSL: error:1408F092:SSL routines:SSL3_GET_RECORD:data length too long) while waiting for request, client: 64.41.200.107, server: 0.0.0.0:443

---------------------


nginx.conf

---------------------

server {

        listen       443 ssl;

        server_name  domain;


        ssl on;

        ssl_certificate       /etc/nginx/ssl/cert.pem;

        ssl_certificate_key   /etc/nginx/ssl/cert.pem;

        ssl_password_file     /etc/nginx/ssl/cert.pass;


        client_max_body_size 20M;

        client_body_buffer_size 10M;


        ssl_session_timeout  30m;

        ssl_protocols TLSv1.2;

        ssl_ciphers HIGH:!aNULL:!MD5:!RC4;

        ssl_prefer_server_ciphers   on;


        location / {

                proxy_pass http://domain:port/;

                proxy_max_temp_file_size 0;

                proxy_buffering off;

        }


        error_page 403 404 500 502 503 504 /50x.html;

        location = /50x.html {

                root /home/project/tomcat/;

                internal;

        }

}


server {

        listen 80;

        server_name domain;

        root /home/project/tomcat/www/;


        client_max_body_size 20M;

        client_body_buffer_size 10M;


        location / {

                proxy_pass http://domain:port/;

        }


        error_page 403 404 500 502 503 504 /50x.html;

        location = /50x.html {

                root /home/project/tomcat/;

                internal;

        }


        return 301 https://domain;

}

---------------------


추가정보

OS: CentOS release 6.6

nginx -v: nginx/1.10.2

SSL: Sectigo RSA Domain Validation Secure Server CA




✅최고의 답변✅

안녕하세요. 리얼리눅스 입니다.

아래 오류는 SSL 핸드쉐이크 과정에서 CCS(Change Cipher Spec) 메시지가 예상보다 일찍 수신되었음을 나타냅니다. CCS 메시지는 TLS 암호화 모드로 전환할 것을 알리기위해 SSL 핸드쉐이크의 마지막 단계에서 전송되는 메시지입니다.

SSL_do_handshake() failed (SSL: error:14094085:SSL routines:SSL3_READ_BYTES:ccs received early) while SSL handshaking, client: 64.41.200.107, server: 0.0.0.0:443

그런데 예상보다 일찍 CCS 먼저 수신되었다는것은 현재 nginx 에서 지원하고 있는 TLS 버전과 브라우저에서 사용하는 TLS 버전이 맞지않아서 발생했을 가능성이 큽니다.

현재 질문자님께서 공유해주신 nginx 설정(nginx.conf)을 기반으로 볼때 아래처럼 TLS v1.2 만 지원하고 있습니다.

ssl_protocols TLSv1.2;

따라서 아래와 같이 TLS 버전지원을 늘려서 다른 TLS 버전을 쓰는 클라이언트, 브라우저가 문제 없이 동작하도록 할 수 있습니다.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

실제 질문자 님의 웹사이트 에서 TLS 버전을 정확히 어떻게 지원하고 있는지는

https://www.ssllabs.com/ssltest/analyze.html 위 사이트에 접속해서 확인 가능합니다.

SSL Server Test (Powered by Qualys SSL Labs)

Hostname: Do not show the results on the boards Domain name is mandatory (Hostname) Recent Best A+ www.balearsvadegust.cat A+ www.shipped.top A+ www.franklinyu.name A+ app.shipped.top A+ psp-test.idomitech.net A+ werkplek.i-dienst.nl A+ zorgdomein-ijsselland.hix365 ... B ntda.wda.gov.tw B jxaas.cn B...

www.ssllabs.com

사용하고 계신 도메인 웹사이트 주소를 입력해서 확인가능하고 확인결과는 아래로 스크롤하여 다음과 같이 확인 가능합니다.

본 예시는 리얼리눅스 웹사이트(https://reallinux.co.kr)에서 지원되고있는 TLS 버전을 보여주고 있습니다.

질문자님은 TLS v1.2 만 지원되는것으로 보이고 TLSv1 TLSv1.1 TLSv1.2 까지 지원하는 버전을 추가 해보는것을 추천드립니다. 다만 서버에서 사용중인 openssl 버전에 따라 사용가능한 TLS 버전이 제한될 수있으니 아래와 같이 버전 확인이 필요합니다. (openssl 버전 예시: v1.1.1)

$ openssl version OpenSSL 1.1.1 11 Sep 2018

참고로 TLSv1.1 및 매개 변수 TLSv1.2 는 OpenSSL 1.0.1 이상이 사용되는 경우에만 작동합니다.

매개 변수 TLSv1.3 는 OpenSSL 1.1.1 이상을 사용하는 경우에만 작동합니다.

두번째로 아래와 같은 SSL 에러는 SSL 핸드쉐이크 과정(연결과정) 중 SSL/TLS 라이브러리 내부적으로 TLS 레코드 데이터를 클라이언트로 부터 받는 처리가 있습니다. 이때 클라이언트로부터 수신한 데이터의 길이가 너무 길어서 처리하지 못했다는 것을 나타냅니다.

SSL_read() failed (SSL: error:1408F092:SSL routines:SSL3_GET_RECORD:data length too long) while waiting for request, client: 64.41.200.107, server: 0.0.0.0:443

하지만 실제 해당 에러는 사이드 이펙트로 발생한 "결과/현상" 으로 보이고 예상해봤을때 SSL 서버인증서,체인, 루트, 개인키 등의 문제일 수 도 있겠습니다. 질문자님께서 지정한 설정은 통합된 pem 으로 아래와 같이 ssl_certificate 와 ssl_certificate_key 를 동일하게 설정했습니다. 하지만 해당 부분을 수정하는것을 추천드립니다.

ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/cert.pem;

예를 들어 setigo 에서 받은 아래 3개의 파일을 기준(예시 도메인: example_com)으로

1. 서버인증서 : example_com.crt 파일 2. 중간인증서: example_com.ca-bundle 파일 3. 키(private key): example_com.key

위 첫번째, 두번째 인증서를 하나로 통합하고

$ cat example_com.crt example_com.ca-bundle > ssl-bundle.crt

아래와같이 세번째 키(private key)와 함께 nginx 설정(nginx.conf) 수정 하는것을 추천드립니다.

(참고로 인증서와 키 파일의 경로 /etc/nginx/ssl/example_com/ 를 수정이 필요합니다.)

 ssl_certificate /etc/nginx/ssl/example_com/ssl-bundle.crt; ssl_certificate_key /etc/nginx/ssl/example_com/example_com.key;

그리고 나서 nginx 재시작 또는 리로드 를 진행하고 재점검 부탁 드리겠습니다.

감사합니다

리얼리눅스 관련 강의로는 "네트워크 완정정복" 수업을 추천 드립니다.

https://reallinux.co.kr/course/se_network

Real Linux | 최신트렌드 리눅스 전문교육|임베디드|서버

직장인을 위한 리눅스교육

reallinux.co.kr

질문과 답변을 친구들과 공유하세요.