HTTPS 적용된 것을 Nginx로 무중단 배포해보자.

원래 상황

AWS ACM이랑 ELB를 이용하여 HTTPS를 적용했었다. 하지만 8084 포트에만 적용되는 것이 문제다. 그 이유는 대상 그룹에 포트가 8084로만 되있었기 때문이다.

그런데 Nginx + SSL + ELB 관련 예제를 보니 대상 포트가 80으로 되있었다. 다음과 같이 말이다.

아마 구조가 80 -> 443 으로 리다이렉트해서 HTTPS를 먼저 적용한 후 ,
Nginx가 이를 받아서 원하는 포트로 다시 리다이렉트하는 것 같다.


ELB 및 대상 그룹 수정 후

위 그림처럼 80포트로 설정했다. 그리고 Route 53의 A레코드도 바뀐 elb로 적용해주었다.

이제 사이트로 다시 접속해보니 다음과 같은 에러가 맞이했다.

일단 추측해보자면, ec2에 접속은 되고 nginx가 받아냈는데 에러가 터진 것 같다.


Nginx 적용 이후

 server {
        listen       80;
        server_name  ~.;
        # redirect https setting
        if ($http_x_forwarded_proto != 'https') {
                return 301 https://$host$request_uri;
        }
        include /etc/nginx/conf.d/service-url.inc;

        location / {
                proxy_pass $service_url;
                proxy_redirect off;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header HOST $http_host;
                proxy_set_header X-NginX-Proxy true;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

443으로 오는 경우 HTTPS이므로 /etc/nginx/conf.d/service-url.inc에 적혀있는 URL 그대로 패스.

만약 HTTPS 요청이 아닌 경우 HTTPS로 리다이렉트 (301). 그리고 /etc/nginx/conf.d/service-url.inc에 적혀있는 URL로 패스.

흠.. 그런데 Nginx로 넘어가긴 하는데, idle port를 못 찾는 것 같다.
이유는 다음과 같다.

[ec2-user@dasd412-diabetes-diary-api zip]$ sudo curl -s http://localhost/properties
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.20.0</center>
</body>
</html>

find_idle_profile() 내의 curl을 그대로 해봤다. 그 결과 nginx 의 301처리 html 처리 문자열이 나온다.

        if ($http_x_forwarded_proto != 'https') {
                return 301 https://$host$request_uri;
        }

을 삭제하고 리눅스 쉘에 curl 해보니 이번엔 제대로 문자열이 나온다.
물론 윗줄은 필요하니 넣어야 한다. 하지만 uri가 properties면 curl http를 할 수 있도록 해야 한다.


Nginx 다중 if 우회해서 사용하기

    server {
        listen       80;
        server_name  ~.;
        # redirect https setting

        include /etc/nginx/conf.d/service-url.inc;
        set $need_redir 0;

        if ($http_x_forwarded_proto != 'https') {
                set $need_redir 1;
        }

        if ($request_uri = /properties){
                set $need_redir 0;
        }

        if ($need_redir = 1){
                return 301 https://$host$request_uri;
        }

        location / {
                proxy_pass $service_url;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header HOST $http_host;
                proxy_set_header X-NginX-Proxy true;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

Nginx는 문법 상 and 및 or가 지원되지 않는다. 따라서 C언어 flag 변경처럼 사용하면 다중 if를 쓴 것처럼 활용 할 수 있다.

뜻은 다음과 같다.
만약 https가 아니고 /properties API 호출이 아니면 HTTPS로 리다이렉트한다. 그렇지 않으면 HTTP 그대로 호출한다.

적용해보니 리눅스 쉘에서 curl/properties 호출 시 301.html이 아닌 real1과 같은 문자열이 제대로 나온다.


해결 및 정리!!!

포트 2개에 어플리케이션이 제대로 작동된다.
원인은 역시 idle port를 찾지 못해서였다.

즉, 정리하자면 https를 적용하게 되면 다음 코드에 의해

        if ($http_x_forwarded_proto != 'https') {
                return 301 https://$host$request_uri;
        }

CURRENT_PROFILE=$(curl -s http://localhost/properties)의 결괏값은 다음과 같이 나온다.

[ec2-user@dasd412-diabetes-diary-api zip]$ sudo curl -s http://localhost/properties
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.20.0</center>
</body>
</html>

따라서 curl -s http://localhost/properties를 할 때는 https 리다이렉트 하지 않도록 하면 된다!


다이어그램


참고

배포 기반은 이동욱 저 스프링 부트 서적.

(elb 및 대상 그룹)
https://ondolroom.tistory.com/873

(ACM + ELB + Nginx)
https://medium.com/@vdongbin/aws-elb%EC%99%80-nginx%EB%A1%9C-https-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0-736b8c5ee76

(Nginx)
https://developer88.tistory.com/299

(nginx 다중 if)
https://gist.github.com/jrom/1760790

https://akageun.github.io/2018/01/12/nginx-multiple-if-statements.html

좋은 웹페이지 즐겨찾기