Post View

nginx에서 HTTPS가 HTTP로 변경되는 이슈 해결

제 블로그(https://www.kurien.net)의 경우 github의 master branch에 push를 하게 되면 github의 Webhooks이 젠킨스 서버에 이벤트를 발생시켜 자동으로 master branch의 소스로 배포가 되도록 되어있습니다.

하지만 이런 경우 master banche를 push 한 경우에만 자동으로 배포되다보니 운영환경에서만 나타날 수 있는 오류를 발견하기 어려운 상황이 자주 발생했기 때문에 develop branch에도 동작하는 개발용 서버를 구축하게 되었습니다.

개발 서버는 생긴건 동일하지만 경로는 https://www.kurien.net:30443으로 포트가 다르고 실제 동작하는 서버는 도커를 이용하여 별개의 인스턴스로 구축되어 있습니다.

이렇게 개발 서버 구축을 끝내고 정상적으로 화면이 표시되어서 안심하고 있었지만 테스트를 해보니 오류가 발생했습니다.

대부분의 링크는 별 문제가 없었지만, 일부 상황에서 HTTPS 프로토콜에서 HTTP 프로토콜로 변경되어버리는 현상이 있었습니다.
분명 링크 자체는 HTTPS 프로토콜로 되어있었지만, http://www.kurien.net:30443 처럼 HTTP 프로토콜로 변경되어 정상적으로 연결이 되지 않았습니다.

HTTPS 기본 포트(443)인 경우 아무 문제도 없었기 때문에 포트의 문제인가 싶어서 여러가지로 찾아보았고 오류메시지로 나타났던 "The plain HTTP request was sent to HTTPS port" 키워드로 검색을 해서 스택오버플로우를 통해 nginx 설정을 변경하면 해결이 된다는 내용을 확인했습니다.

아래의 설정은 제 블로그의 개발 서버(nginx)에 적용된 설정입니다.

server {
    listen       80;
    server_name  www.kurien.net kurien.net;

    location / {
        return         301 https://www.kurien.net$request_uri;
    }
}

server {
    listen       443 ssl http2 default_server;
    listen       [::]:443 ssl http2 default_server;
    server_name  www.kurien.net kurien.net;

    if ($host !~* 'www.kurien.net') {
        return 301 https://www.kurien.net:$server_port$request_uri;
    }

    ssl_certificate "/etc/nginx/key/www.kurien.net/fullchain.pem";
    ssl_certificate_key "/etc/nginx/key/www.kurien.net/privkey.pem";

    client_max_body_size 1024M;
    proxy_max_temp_file_size 10m;

    location / {
        proxy_redirect off;
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://tomcat1:8080;
        proxy_http_version 1.1;
    }

    error_page 497 https://$host:30443$request_uri;
}

설정 자체는 nginx로 reverse proxy server 구축하기에 적용해놨던 설정파일과 크게 차이가 없지만 "error_page 497 https://$host:30443$request_uri;"라는 부분이 추가되었습니다.

nginx(http://nginx.org/en/docs/http/ngx_http_ssl_module.html) 측의 문서에는 497 error code에 대해서 "a regular request has been sent to the HTTPS port."라고 나와있습니다.
HTTP 요청이 HTTPS 포트로 요청되었다는 것으로, 이 경우 error_page 497 뒤의 "https://$host:30443$request_uri" 경로로 redirect 시키는데, 이를 통해 HTTP 포트로 들어온 요청은 HTTPS로 redirect 시키게 되어 문제가 해결됩니다.

개발 서버를 구축하면서 HTTPS에 대해서 사용자 포트를 사용한 것만으로 이런 문제가 발생해서 당황했지만 이후 다른 웹서버(HAProxy)에서도 동일한 현상이 있다는 것을 알고 정리할 겸 적어보았습니다.

Comments