(Docker + virtual host) AWS ELB 를 통해 HTTPS 구성하기
기존에 Docker 를 이용한 가상 호스트 환경에서 도메인을 운영하고 있었는데 (참조: Docker 를 사용한 가상 호스트(Virtual Host) 구축 및 서브 도메인 연결), HTTPS 서버를 구성할 필요가 생겼다. 검색을 해 보니 추가적인 비용 없이 간단하게 구성할 수 있는 방법으로 아마존 웹 서비스 (Amazon Web Service, AWS) 를 사용하는 방법이 있었고, 상세한 자료가 많아서 이를 따라 구축하였다 (참고: AWS SSL 적용 방법). 다만 가상 호스트 환경에서 HTTP 접속을 항상 HTTPS 접속으로 redirect 하기 위해서 추가적인 작업이 필요하여, 이 과정을 정리하였다. (수정: 아마존의 DNS 서비스인 Route53 을 사용 시 도메인 당 $0.5 의 비용이 있음)
아마존을 통한 HTTPS 인증 방식의 기본적인 구조
아마존에서 발급받은 인증서를 사용하기 위해서는 아마존의 로드 밸런서 (Elastic Load Balancer, ELB) 를 사용해야 한다. 이 로드 밸런서가 인증을 담당하고 HTTPS 트래픽을 실제 머신 (EC2) 으로 넘겨주는 것이다. 가장 기본적인 설정은 아래 그림과 같이, ELB 가 80 및 443 포트의 요청을 받으면 이를 모두 HTTP 요청으로 변환하여 백엔드 서버에 전달하는 것이다. 이렇게 하면 백엔드 서버를 수정하지 않고도 쉽게 HTTPS 요청을 받을 수 있는 장점이 있어 나와 같이 기존 HTTP 서버를 확장할 때 간편해 보인다.
Nginx 서버의 설정 변경
위와 같은 설정을 마치면 HTTPS 요청을 잘 받는 것을 확인할 수 있다 (보안 정책에서 443 포트를 여는 것을 잊으면 안 된다). 두 번째로는 HTTP 요청이 들어와도 HTTPS 로 처리하도록 하는 작업이 필요한데, 예를 들어 blog.youngbin.kim
으로 접속을 할 경우 https://blog.youngbin.kim
으로 접속이 되도록 설정하는 것이다. 이 설정은 백엔드 서버에서 해 줘야 하는데, 문제는 ELB 가 모든 요청을 HTTP 로 변환해서 전달하기 때문에 서버에서는 들어온 요청이 원래 HTTPS 였는지 확인이 어렵다는 점이다.
이를 알려주기 위해서 ELB 에서는 X-Forwarded-Proto
헤더를 설정한다. (참고: Redirecting EC2 elb from http to https, How to force HTTPS behind AWS ELB) 이에 따라 nginx 서버 설정 파일에 아래와 같은 코드를 추가하여 HTTP 요청을 HTTPS 주소로 redirect 시켜줄 수 있다.
if ($http_x_forwarded_proto = 'http') {
return 301 https://example.com$request_uri;
}
Nginx-proxy 이미지를 수정하여 HTTPS redirection 설정하기
일반적인 서버의 경우 위와 같은 처리를 해 주면 완료가 되지만, 나의 경우 nginx-proxy
(jwilder/nginx-proxy) 를 이용한 virtual host 환경을 사용하고 있기 때문에 추가적인 처리가 필요하다. 이전 글 에서 언급했듯이 nginx-proxy
는 새로운 컨테이너가 로드될 경우 서버 설정 파일을 업데이트하는데, 이 과정은 새로운 컨테이너와 nginx.tmpl
파일을 기반으로 conf
파일을 새로 작성하는 것이다. 따라서 새로운 컨테이너가 추가될 때마다 기존 서버 설정이 nginx.tmpl
을 바탕으로 초기화되므로, 위 설정 코드를 nginx.tmpl
에 추가해 주어야 한다. 나의 경우 /app/nginx.tmpl
파일에서 HTTP 리퀘스트를 처리하는 부분 의 location
위에 다음과 같은 코드를 추가하였다.
if ($http_x_forwarded_proto = 'http') {
return 301 https://{{ trim $upstream_name }}$request_uri;
}