[SSL] Nginx와 Let's Encrypt로 HTTPS 웹 서비스 배포하기 (certbot)
클라이언트와 WAS 사이에 리버스 프록시 서버를 둔다. 클라이언트는 리버스 프록시 서버에 요청하고, WAS는 리버스 프록시로부터 사용자의 요청을 대신 받는다. 클라이언트는 리버스 프록시 서버 뒷단의 WAS의 존재를 알지 못한다. 이로 인해 보안이 한층 강화되었다.
리버스 프록시 서버에 SSL 인증서를 발급하여 HTTPS를 적용한다. WAS 서버가 여러대로 늘어나도 SSL 인증서 발급은 추가로 하지 않아도 되니 확장성이 좋다. 또한 WAS 서버가 SSL 요청을 처리하는데 비용도 들지 않는다.
리버스 프록시 서버는 Nginx를 사용한다. CA로 무료 SSL 인증서 발급기관인 Let's Encrypt를 사용한다. 또한, 간단한 SSL 인증서 발급 및 Nginx 환경설정을 위해 Certbot을 사용한다.
리버스 프록시란? 클라이언트 요청을 대신 받아 내부 서버로 전달해주는 것
- 서버의 응답을 캐시에 저장하여 서버에 요청하지 않고, 응답해서 리소스를 절약한다.
- 내부의 WAS를 보호한다.
- 많은 요청을 처리하기 위해 여러 대의 서버에 부하를 분산시킬 수 있다.
리버스 프록시인 Nginx를 사용하면 클라이언트 요청을 프록시 서버에 분산하기 위해 로드밸런싱으로 부하가 줄여줄 수 있고, 분산처리 또한 가능하며, 웹 서버의 SSL 인증도 적용할 수 있다.
WAS 서버 세팅
준비된 서버에 WAS를 띄우자. 이 포스팅에선 8080포트로 어플리케이션 서버를 실행한다.
리버스 프록시 서버 세팅
Nginx 설치
nginx 패키지를 설치한다.
$ sudo apt update
# Nginx 설치
$ sudo apt install nginx
# Nginx 실행
$ sudo service nginx start
Nginx 리버스 프록시 설정
리버스 프록시를 위한 Nginx 설정을 해줄 것이다. /etc/nginx/conf.d 디렉토리로 이동해서 Nginx를 위한 설정파일을 생성하자.
sites-available, sites-enabled는 더이상 사용하지 않는 Nginx 설정방법이라고 한다. conf.d 디렉터리에 Nginx 설정 파일을 만들고 관리한다.
만약 sites-available과 sites-enabled에 기본 설정 파일이 있다면 제거하자. 또한 conf.d에 기본으로 default.conf 파일이 존재하면, 그 파일을 수정해서 설정하자.
$ cd /etc/nginx/conf.d
$ vi default.conf
위 명령을 실행해서 default.conf 파일을 생성하자.
server {
listen 80;
server_name your.domain.com;
location / {
proxy_pass http://192.168.XXX.XXX;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
server_name 은 SSL을 적용할 도메인을 입력한다. 후술할 Certbot은 이 server_name을 기준으로 Nginx 설정파일을 찾고 여기에 HTTPS에 대한 설정을 자동으로 추가해준다.
proxy_pass 에는 프록시 서버가 클라이언트 요청을 전달할 리얼 서버의 주소를 적는다. 리버스 프록시의 가장 큰 목적 중 하나는 실제 서버의 IP 주소를 클라이언트에게 노출하지 않기 위함이므로 여기서는 프라이빗 IP를 입력한다. (퍼블릭 IP를 입력해도 큰 차이는 없다.)
Certbot 설치 및 Let's Encrypt에서 SSL 인증서 발급
Certbot은 손쉽게 SSL 인증서를 자동 발급할 수 있도록 도와주는 도구이다. Certbot은 우분투의 snap라는 패키지 매니저를 사용하여 설피하는 것이 권장된다. (참고: Certbot 사이트 주소)
# snapd 설치
$ sudo yum install snapd
$ sudo snap install core
$ sudo snap refresh core
$ sudo snap install certbot --classic
아래 명령을 실행하여 SSL 인증서를 발급받는다.
$ sudo certbot --nginx
이메일을 입력하고, 이용약관에 동의 후 사용할 도메인을 입력한다. 이때, 적용할 도메인에 대한 A 레코드가 반드시 적용되어 있어야 한다.
이 과정을 거치면 Certbot은 Let's Encrypt를 통해 자동으로 SSL 인증서를 발급해온다.
위 명령을 수행 후, 아래처럼 뜬다면 잘 발급받은 것이다.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Your existing certificate has been successfully renewed, and the new certificate
has been installed.
The new certificate covers the following domains: https://your.domain.com # https가 설정된 도메인
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Subscribe to the EFF mailing list (email: jy.jeon@gmail.com).
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/your.domain.com/fullchain.pem # 공개키 경로이므로 기억해두자.
Your key file has been saved at:
/etc/letsencrypt/live/your.domain.com/privkey.pem # 비밀키 경로이므로 기억해두자.
Your certificate will expire on 2021-08-15. To obtain a new or
tweaked version of this certificate in the future, simply run
certbot again with the "certonly" option. To non-interactively
renew *all* of your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
출력된 문구를 보면 다음을 확인할 수 있다.
1. https가 설정된 도메인
https://your.domain.com
2. 공개키 경로
/etc/letsencrypt/live/your.domain.com/fullchain.pem
3. 비밀키 경로
/etc/letsencrypt/live/your.domain.com/privkey.pem
또한 우리가 작성한 Nginx의 default.conf 를 확인해보면 HTTPS를 위한 여러 설정이 자동으로 추가된 것을 볼 수 있다.
# 433 포트로 접근 시, ssl 적용 후 8080 포트로 요청을 전달
server {
server_name your.domain.com;
location / {
proxy_pass http://192.168.XXX.XXX:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
# 80 포트로 접근 시, 433 포트로 리다이렉트
server {
if ($host = your.domain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name your.domain.com;
return 404; # managed by Certbot
}
기존에 작성한 리버스 프록시 관련 세팅을 유지한 채 80 포트 즉, HTTP로 들어온 요청중 host 헤더가 your.domain.com 이라면 443 즉, HTTPS로 301 Moved Permanently Status를 사용해서 리디렉션 해주는 것을 확인할 수 있다. host가 일치 하지 않으면 404 를 반환한다.
Crontab으로 SSL 인증서 자동 갱신 설정
Let's Encrypt에서 발급해주는 SSL 인증서는 90일짜리 단기 인증서이다. 90일마다 SSL 인증서를 수동으로 갱신해줘야한다.
# ssl 인증서 갱신 테스트
$ certbot renew --dry-run
# ssl 인증서 갱신
$ certbot renew
# ssl 인증서 만료일 확인
$ certbot certificates
리눅스 Crontab을 이용하여 ssl 인증서 갱신 자동화를 할 수 있다.
Crontab이란 리눅스에서 제공하는 기능으로 특정한 시간 혹은 특정한 주기로 명령을 수행하고 싶을 때 사용한다. 즉, Crontab은 스케줄링 도구이다. 아래 명령을 이용해서 cron job 하나를 생성하자.
$ crontab -e
vim 선택 후, 주석 가장 아래에 아래 내용을 추가하고 파일을 저장하자.
0 0 * * * certbot renew --post-hook "sudo service nginx reload"
매월, 매일 0시 0분에 certbot을 실행하여 SSL 인증서를 갱신하고, 갱신 이후 nginx의 설정파일을 reload 해주는 작업이다.
참고
https://frogand.tistory.com/109
출처
https://hudi.blog/https-with-nginx-and-lets-encrypt/
https://gist.github.com/woorim960/dda0bc85599f61a025bb8ac471dfaf7a
https://devlog.jwgo.kr/2019/04/16/how-to-lets-encrypt-ssl-renew/
'programming language > Dev' 카테고리의 다른 글
메시지 큐 Message Queue (0) | 2023.02.17 |
---|---|
Boolean 변수에 적절한 이름을 지어주기 (2) | 2023.02.15 |
[Graceful Shutdown] kill -9 쓰지말자! (0) | 2022.06.29 |
Mac OS에 NTFS 읽고 쓰기 위한 Mounty 설치 (0) | 2022.05.31 |
[SSH] SSH 접속정보 설정파일로 저장하여 접속하기 (0) | 2022.02.15 |
댓글 개