본문 바로가기
Server&Infra/Nginx

Nginx에 Let's Encrypt SSL(https) 보안 인증서 적용하기(with certbot 인증서 자동갱신)

by Deoking 2022. 11. 22.
반응형

Overview

인증 기관으로부터 보안 인증서(SSL/TLS) 인증서를 발급받고 이를 웹서버에 적용하여 암호화된 연결(https protocol)을 설정합니다. 또 인증서 자동 발급 도구인 Certbot을 활용하여 인증서 만료 전 자동 갱신하는 방법에 대해 기술합니다.
- 설치환경 : Linux/CentOS 7, Nginx
- CA(인증기관) : Let's Encrypt SSL
- 인증서 발급 자동화 Certbot


인증서 생성 및 발급

1. Let’s Encrypt

Let’s Encrypt는 무료 SSL/TLS 인증서를 얻고 설치할 수 있는 인증 기관으로, 웹 서버에서 암호화된 HTTPS를 사용할 수 있게 해 줍니다. 또한, Certbot이라는 자동화 클라이언트를 제공하여 Apache 및 Nginx에서 인증서를 획득하고, 설치하는 전체 프로세스가 자동화되어 있습니다.
참고로 Let’s Encrypt 인증서의 경우 유효기간은 3개월(90일)로 그 기간이 짧습니다. 가장 큰 이유로는 짧은 주기의 자동 갱신을 권장하여 인증서가 무력화되더라도 그 피해를 최소화하기 위함입니다.

2. 인증 방식

인증서는 Let’s Encrypt(인증기관, CA)로부터 인증 절차를 거쳐야 인증서 발급이 가능하며, 인증 방식에는 아래 4가지 방식이 있습니다. 본 문서에서는 3번 Standalone 방식으로 진행합니니다.

  1. webroot 방식
    • 실제 돌아가고 있는 웹 서버에 특정 파일 쓰기 작업을 통해 인증하는 방식입니다. 즉, 접근할 수 있는 특정 디렉터리를 제공해서 접근이 가능한지 확인하는 방식입니다.4
    • 이를 이용하면 nginx를 중단시킬 필요가 없어진다는 장점이 존재합니다.
    • 단, 한 번에 하나의 도메인만 발급 가능하다는 단점이 존재합니다.
  2. 웹서버(Nginx) 방식
    • Nginx나 아파치와 같은 웹서버에서 직접 SSL 인증을 실시하고 웹서버에 맞는 SSL세팅값을 부여
    • 발급이나 갱신을 위해 웹서버를 중단시킬 필요가 없음
    • 인증서 갱신 시 상황에 맞게 세팅을 자동으로 업데이트
    • 사용자가 세팅을 변경할 수 있지만 자동 업데이트 시 반영되지는 않음
  3. Standalone 방식
    • certbot에서 80 포트의 standalone webserver를 따로 띄워서 인증서를 발급받는 방식입니다.
    • 즉, 80, 443 포트를 이미 열고 있다면 발급 시마다 nginx를 다시 내려야 한다는 단점이 존재합니다.
  4. DNS 방식(자동갱신 X)
    • 도메인 TXT 레코드를 이용해서 인증서를 발급받는 방식입니다.
    • 와일드카드 방식으로 인증서 발급이 가능합니다.
    • 단점은 인증서 갱신 시마다 DNS TXT 레코드 값을 변경해야 합니다.
    • 때문에 DNS가 TXT 레코드를 수정할 수 있는 API를 제공해야만 갱신을 자동으로 처리 가능합니다.

 

3. Certbot 설치

Certbot을 설치하고 Nginx 연동을 위해 python2-certbot-nginx도 설치합니다.

# EPEL 저장소 활성화를 위해 epel-repository 설치.
sudo yum -y install epel-release yum-utils

# certbot 설치.
sudo yum install certbot

# 웹서버(nginx) 플러그인 설치.
sudo yum install python2-certbot-nginx

 

4. nginx 중지

standalone 방식은 웹 서비스를 임시로 빌리기 때문에 현재 구동되고 있는 웹 서비스를 잠시 중단해야 합니다.

sudo systemctl stop nginx

 

5. 인증서 생성 및 발급

sudo certbot certonly --standalone -d domain.com,www.domain.com,api.domain.com
  • -nginx : 기본 명령에 웹 서버(ex. nginx, apache 등) 이름을 옵션 값으로 입력.
  • -standalone : 인증서 발급 방식은 옵션을 붙여 사용할 수 있습니다.(ex. standalone, webroot, manual 등)
    • -manual : 수동 발급으로 인증서를 가져와 도메인 검증을 직접 수행하며, 자동 갱신은 지원되지 않습니다.
    • —preferred-challenges dns : DNS 방식의 경우
  • -d [Domain Name] : -d 옵션은 발급할 인증서의 도메인을 입력하는 부분입니다. 여로 도메인을 사용하는 경우 -d를 계속 붙이거나 콤마(,)로 구분하여 입력합니다.(ex. -d example.com, sub1.example.com, sub2.example.com…)
  • certonly : 인증서 생성 및 갱신만 진행하는 옵션으로 인증서 관련 내용을 임의로 수정하지 않도록 주의.

 

6. 관리자 이메일 주소 입력

도메인 관리자의 이메일 주소를 입력합니다. 해당 메일로 갱신 알림 및 주요 소식들이 발송됩니다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel):

 

7. 관련 약관 동의

다음으로, 이용에 관한 동의 및 인증 기관에 등록되는 사항에 관한 동의입니다.
Y(동의) 입력.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

다음으로, 제삼자 정보제공에 관한 동의입니다.
N(미동의) 입력.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

 

8. 인증서 정상 발급

상기 절차가 문제없이 진행되면 아래와 같이 안내해줍니다.

Account registered.
Requesting a certificate for domain.com and 3 more domains
Performing the following challenges:
http-01 challenge for admin.domain.com
http-01 challenge for api.domain.com
http-01 challenge for domain.com
http-01 challenge for www.domain.com
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/domain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/domain.com/privkey.pem
   Your certificate will expire on 2022-11-02. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again. 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

Congratulations! 라는 문구가 나타나면 발급이 정상적으로 완료된 것입니다.
키 파일의 위치는 /etc/letsencrypt/live/domain.com/fullchain.pem 이며 만료일은 2022-11-02로 알려주고 있습니다.

9. 인증서 발급 내역 조회

발급된 인증서의 세부적인 정보를 확인하려면 아래 명령어를 입력합니다.

sudo certbot certificates

결과는 아래와 같습니다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: domain.com
    Serial Number: 3afe710a2714b8ed5e5a1ef2b1337e444da
    Key Type: RSA
    Domains: domain.com admin.domain.com api.domain.com www.domain.com
    Expiry Date: 2022-11-02 01:59:25+00:00 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/domain.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/domain.com/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

 

10. nginx 설정

발급된 인증서를 아래와 같이 설정해줍니다.

server {
    # ========= 수정된 부분 =========
    # https(ssl) 접속에 대한 설정.
    listen       443 ssl http2;
    server_name  domain.com www.domain.com;
    # ============================

		# ========= 추가된 부분 =========
        	# 발급 받은 인증서 파일에 대한 경로 설정.
		# managed by Certbot(SSL)
		ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; 
		ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; 
		# include /etc/letsencrypt/options-ssl-nginx.conf;
		# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
        	# ============================

    charset utf-8;
    access_log  /var/log/nginx/access.log  main;
    error_log   /var/log/nginx/error.log   warn;

    location / {
        proxy_redirect     off;
        proxy_set_header   Host             $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://127.0.0.1:13000;
    }

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
# ========= 추가된 부분 =========
# http로 접속 시에 (일반적으로 80포트) https로 리다이렉트 되도록 설정.
server {
    listen        80;
    server_name   domain.com www.domain.com;
    return 301 https://domain.com$request_uri;
}
# ============================

끝으로, 중지했던 nginx 서비스를 다시 시작합니다.
만약 404 에러 등으로 접속되지 않는 경우 서버의 방화벽에 443(ssl) 포트가 허용되어 있는지 확인합니다.

sudo systemctl restart nginx

최종적으로 브라우저를 통해 정상적으로 인증서가 연결되었는지 확인합니다.
추가적으로 SSL Labs Server Test 로 ssl 테스트 후 리포트를 받아 볼 수 있습니다. 위 사항까지만 적용할 경우 B 등급이 나오는데, ssl_protocols TLS 버전 수정과 Diffie-Hellman Key 변경으로 상향된 등급을 받을 수도 있습니다.

인증서 자동 갱신

Let’s Encrypt 인증서는 유효기간이 90일 이기 때문에 만료 전 갱신이 필요합니다.
인증서 갱신 명령어는 아래와 같습니다.(갱신 시 nginx 서비스는 중단해야 합니다.)

sudo certbot renew

certbot에서는 인증서 갱신이 잘 작동하는지 모의 테스트할 수 있는 옵션을 제공합니다.

# 모의 테스트
sudo certbot renew --dry-run

위와 같이 만료 전 수동으로 갱신을 해도 무방하지만 갱신을 자동화할 수도 있습니다.
Linux의 crontab을 활용하여 일정 일시에 맞춰 반복적인 갱신을 구현할 수 있습니다. 인증서를 갱신하는 명령어가 주기적으로 실행될 수 있도록 아래와 같이 설정합니다.

# crontab config 편집기 실행.
sudo crontab -e

# 매월 1일 새벽 3시(서버시간 18시) 실행 설정.
0 18 1 * * sudo certbot renew --pre-hook "sudo systemctl stop nginx" --post-hook "sudo systemctl restart nginx"

# crontab 보기
sudo crontab -l

# crontab 로그 보기
sudo cat /var/log/cron

 


Conclusion

지금까지 nigix 환경에서 보안 인증서(ssl)를 적용하는 방법을 알아보았습니다.
간편한 설치와 무료라는 강점으로 많은 분들이 사용하시는 것 같습니다. 참고로 무료와 유료 ssl인증서 간에 기술적 차이점은 없다고 합니다. 다만 유료가 무료와 다른 점은 보안 인증과 관련된 문제가 발생했을 때 대신하여 일정 부분 배상을 해주는 보험 역할을 한다고 합니다. 비싼 인증서 일 수록 그 보상 범위와 규모가 커지기 때문에 큰 규모의 서비스나 보안이 중요한 웹사이트의 경우 비싼 유료 인증서를 사용하게 됩니다.
현재 무료 인증서를 사용해도 크게 문제되지 않아 당분간은 무료로 사용할 예정입니다.
-
본 글은 개인적 기록을 목적으로 작성하였습니다.
작게나마 도움 되셨기를 바라며, 더 좋은 의견이나 잘못된 부분이 있다면 댓글을 남겨주세요~

'Server&Infra > Nginx' 카테고리의 다른 글

Linux/CentOS 7 Nginx 설치 및 설정  (0) 2022.11.18

댓글