EC2에 SSL 설정하기 - Nginx, Let's Encrypt

Jimin Lee·2023년 5월 1일
0

EC2 배포하기

목록 보기
2/2

EC2에 SSL 인증서를 붙여서 https 통신이 되도록 하자.

SSL 필요성과 적용 원리

왜 필요한가?

SSL 프로토콜은 HTTP + 암호화 통신이다. 이 암호화 통신 과정에서 SSL 인증서를 사용한다. 그리고 SSL 인증서는 제3의 인증기관(CA)이 이 사이트와의 통신은 안전하다~ 고 보장해주는 역할을 한다. SSL 인증서에 포함된 정보는 인증서 유효기관, 발행기관, 암호화를 위한 public key 등이 담겨있다.

어떻게 적용하는가?

간단하게 말하면 SSL 인증서를 발급받아서 웹서버에 적용하면 된다.

1) SSL 인증서 발급받기
인증 기관에서 인증서를 주는데 이 인증 기관은 CA(Certificate Authority)라고 부른다. 인증기관은 사설도 있고 공인도 있고 여러 가지가 있다.

  • 서버에서 인증서 요청하기
    CA에 인증서를 달라는 인증서 신청 요청을 하는데 이걸 CSR(Certificate Signing Request)라고 부른다. 인증서 주세요 하는 신청서이다. 이 때 필요한 정보는 인증서를 적용할 도메인 정보, 그리고 공개키가 필요하다. 공개키는 서버에서 생성한다.

2) 인증서 설치하기
전달받은 인증서를 웹서버에 적용하면 된다. nginx 경우엔 nginx.conf를 변경해준다.

사전 준비

1. EC2 인스턴스에 탄력적IP 부여받기

먼저 EC2 인스턴스를 하나 띄워두고 탄력적IP를 부여받는다. 인스턴스를 재시작할 때마다 새로운 ip를 발급받는데 그때마다 DNS 재설정이 번거롭기 때문이다.

2. 도메인 구매

나는 구글 도메인에서 도메인을 구매했다.

3. DNS 연동

Route53을 사용했다.
1에서 받은 탄력적 IP와 2의 도메인을 연결한다.

SSL 설정하기

AWS에서 제공하는 Certificate Manager을 사용할까 했는데, 정식으로 인증서를 발급해주는 그런 서비스는 아닌거 같고... AWS에서 제공하는 로드밸런서나 CloudFront 등 몇가지 서비스와만 연동된다길래 포기했다.
대신 certbot이라는 무료 오픈소스 툴을 사용했다. certbot은 Let's Encrypt (인증기관) 인증서를 자동으로 발급, 갱신해주는 역할을 한다.
certbot instructions에서 서버 종류와 OS 종류를 선택하면 그에 맞는 가이드를 보여준다.

하지만 이 과정마저도 누군가 쉘스크립트로 자동화해놨다..! 쉘스크립트 github
쉘스크립트를 적용하는 가이드는 이 포스팅을 참고하면 된다.

docker-compose & nginx를 사용한 실제 적용

1. nginx.conf 수정


    server {
        listen 80;
        server_name [도메인];

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }

		# redirect 추가
        location / {
            return 307 https://$host$request_uri;
        }
    }

    upstream api {
       server api:8080;
    }

    # ssl 설정 추가
    server {
        listen 443 ssl;
        server_name [도메인];

        location /api {
            proxy_pass  http://api;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        ssl_certificate /etc/letsencrypt/live/[도메인]/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/[도메인]/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    }

}

2. docker-compose.yaml에 이미지 추가

위에 nginx.conf에서 인증서를 불러올 때 경로가 필요하므로 nginx의 volumes에서도 연결시켜준다.
[nginx 컨테이너 이름]은 nginx를 권장한다. 다른 걸로 지정해도 되지만 아래 init-letsnecrypt.sh에서 실행시킬 때 컨테이너명을 nginx로 가정해서 실행시키기 때문이다.

version: '1'

services:
  nginx:
    image: nginx:1.21.5-alpine
    ports:
      - 80:80
      - 443:443 # 443 포트 추가
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - [경로]/conf:/etc/letsencrypt
      - [경로]/www:/var/www/certbot
    container_name: [nginx 컨테이너 이름]

## certbot 추가
  certbot:
    image: certbot/certbot
    container_name: certbot
    depends_on:
      - [nginx 컨테이너 이름]
    volumes:
      - [경로]/conf:/etc/letsencrypt
      - [경로]/www:/var/www/certbot

3. 스크립트 실행

이제 서버에 접속해서 스크립트를 다운로드 & 실행시킬 것이다.

curl -L https://raw.githubusercontent.com/wmnnd/nginx-certbot/master/init-letsencrypt.sh > init-letsencrypt.sh

init-letsnecrypt.sh를 열어보면 상단에 변수 지정하는 부분이 있다. 이 부분을 수정해준다.

domains=([도메인])
rsa_key_size=4096
data_path="[경로]"
email="" # Adding a valid address is strongly recommended
staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits

그리고 2에서 nginx 컨테이너 이름을 다른 걸로 지정했다면 docker-compose 뒤에 나오는 nginx들을 모두 해당 [nginx 컨테이너 이름]으로 변경한다.

이제 실행시킨다.

chmod +x init-letsencrypt.sh
sudo ./init-letsencrypt.sh

4. 자동 갱신 명령어 추가하기

=> 이 부분을 미리 docker-compose.yaml에 추가하면 에러가 난다...마지막에 해주자.

docker-compose.yaml에 certbot 섹션에 12시간마다 인증서의 최신 상태를 확인해주는 명령어를 넣는다.

entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

마찬가지로 nginx 섹션에도 nginx가 갱신된 인증서를 가져오는 명령어를 추가한다.

command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

5. docker-compose up

이제 도커 컨테이너들을 모두 띄운다.

참고

https://yoonsj.tistory.com/6 (ssl 인증서 설치)
https://velog.io/@zero-black/Docker-compose-certbot-nginx-%EB%A1%9C-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EB%B0%9C%EA%B8%89%ED%95%98%EA%B8%B0 (docker-compose & nginx)
https://github.com/wmnnd/nginx-certbot (쉘스크립트)
https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71 (docker-compose & nginx)

0개의 댓글