[Let's encrypt] 인증서 발급 및 갱신법


웹 개발을 하면서 여러 곳의 SSL 인증서를 발급받는 곳을 알아 봤었고 그동안 ZeroSSL 을 이용해서 진행해 왔습니다.
SSL 인증서를 등록하는 방식도 여러가지 이지만 Nginx 를 이용해서 등록하는 형태로 사용해 왔었고,  3개월 무료 버전을 사용하면서 매번 갱신 주기마다 직접 작업을 해주어야 하는 부분에 귀찮음을 느끼고 부엉이 사이트를 만들면서 let's encrpt 를 이용해 자동 갱신까지 처리하도록 했습니다.

Let's Encrypt : https://letsencrypt.org


SSL (Secure Socket Layer)

  • 서버와 사용자(브라우저) 간의 통신을 할 경우 정보를 암호화 하고 도중에 해킹을 통해 정보가 유출이 된다고 하더라도 정보의 내용을 보호할 수 있는 보안 인증 솔루션 기술.  대표적으로 해킹 기법 중 '스니핑(sniffing)' 기법을 막기 위한 도구이다.


1. Let's Encrypt 소개


Let's Encryp 은 Https 의 확산이 늦어지는 것은 SSL 인증서에 있다고 보고 무료 인증서 보급을 통해 HTTPS 의 확산을 늘리겠다는 취지로 시작된 비영리 프로젝트 입니다.
Mozilla, Akamai, Cisco, eff, Identrust, 지말토(Gemalto) 와, HP 엔터프라이즈, 패스틀리(Fastly), 두다(Duda) 등이 스폰서로 참여해서 HTTPS Everywhere 를 모토로 100% 무료 SSL 인증서를 발급 해주고 있습니다.
2016 년 4월 정식 버전을 출시 했으며, 2020년 12월 기준 2.34 억개의 웹서버 인증이 진행되었습니다. 

  • 1. 인증서 발급 기간, CA(Certificate Authority) 중 점유율이 가장 높은 곳은 IdenTrust로 2020년 12월 기준으로 42%가 넘습니다(42.3%)
  • 2. IdenTrust 다음으로는 DigitCert Group(15.7%) > Sectigo(14.1%) > GoDaddy(5.4%) > GlobalSign(2.3%)
  • 3. Let's Encrypt 점유율은 생각보다 낮아서 0.1 % 에 불과
  • 4. 하지만 Let's Encrypt 사용이 아래 그래프에서 보듯이 매우 빠르게 증가하고 있습니다.



Let's Encrypt 의 정책은 독특합니다. 앞에서 HTTPS 의 확산을 비영리 단체로 소개했듯이 Let's Encrypt  은 서버 운영자들이 인증 관리를 철저히 하지 못한다는 점을 염려(?)해 인증서 설치부터 재발행(갱신) 까지 다 책임진다는 자세로 인증관련 업무를 진행하고 있습니다. 


인증기관이 90일로 상대적으로 짧은 것은 보안 상황이 계속 변동 되므로 이를 반영해 갱신할 수 있도록 짧게 잡았으며 대신 자동으로 인증서가 연장(재발행) 되는 기능을 사용하도록 권장하고 있습니다. 


  • HTTPS Everywhere 를 추구하는 비영리 프로젝트
  • 스폰서:  Mozila, Akamai, Cisco, eff ,Identrust
  • IdenTrust cross-sign 됨
  • SSL 인증서 100% 무료화
  • 인증기관 연장 및 인증서 재발급 무료
  • 사용편리성: 콘솔상에서 인증서 발급/갱신/설치/ 자동화
  • 멀티도메인 지원, SAN 기능(여러 도메인을 한 인증서로 묶어주는 기능) 지원




2. Let's Encrypt SSL 인증서 발급 방법 4가지

let's Encrypt SSL 인증서 발급 방법은 webfoot 와 standalone, DNS 의 3가지 방식이 있습니다. 인증서 발급은 사이트에서 인증기관인 Let's Encrypt 에 접속해 이 사이트의 유효성을 검증하는 과정을 거치며 이 과정을 아래 3가지 방법 중 하나를 선택해 진행할 수 있습니다.



  • 1. Webroot : 사이트 디렉터리 내에 인증서 유효성을 확인할 수 있는 파일을 업로드하여 인증서를 발급하는 방

 - 실제 작동하고 있는 웹서버의 특정 디렉터리의 특정 파일 쓰기 작업을 통해서 인증

 - 이 방식의 장점은 nginx를 중단시킬 필요가 없음

 - 이 방법의 단점은 인증 명령에 하나의 도메인 인증서만 발급 가능


  • 2. web Server

- Nginx 나 Apach 와 같은 웹서버에서 직접 SSL 인증을 실시하고 웹서버에 맞는 SSL 세팅값을 부여

- 발급이나 갱신을 위해 웹 서버를 중단시킬 필요가 없음 

- 인증서 갱신 시 상황에 맞게 세팅을 자동으로 업데이트

- 사용자가 세팅을 변경할 수 있지만 자동 업데이트 시 반영되지는 않음.


  • 3. StandAlone : 사이트 작동을 멈추고 이 사이트의 네트워킹을 이용해 사이트 유효성을 확인해 Let's Encrypt SSL 인증서를 발급하는 방식.

- 80 포트로 가상 standalone 웹서버를 띄워 인증서를 발급

- 이 방식은 동시에 여러 도메인을 발급 받을 수 있음

- 그렇지만 인증서 발급 전에 Nginx 를 중단하고 발급 완료 후 다시 Nginx 를 시작해야 함.




3. Let's Encrypt 인증서 생성하기

시스템 구성 환경 


- Debian GNU/Linux 11

- Nginx/1.18.0

- Next.js 

- .Net Core 7



Let's Encrypt 에서 제공하는 소프트웨어 클라이언트 lets encrypt 를 사용하면 쉽고 편하게 적용할 수 있습니다.


아파치 서버에서는 완전 자동으로 SSL 인증을 획득하고 적용할 수 있도록 되어있지만, Nginx 서버에서는 이러한 자동화가 상대적으로 늦게 적용되는 것 같습니다.

Nginx 에서의 자동화 방법은 없는 것은 아니므로 뒤에서 다루도록 하겠습니다.


Nginx 에서 let's Encrypt 인증서 생성에는 몇가지 조건이 있습니다.


  • root 접근 권한을 가지고 있어야 한다 (즉 서버를 운영하고 있어야 하므로 일반 웹 호스팅은 안된다는 의미)
  • Let's Encrypt  가 아직은 공식적으로 Nginx 를 지원하지 않은 상태이므로 아파치보다는 상대적으로 매뉴얼 작업이 필요합니다.



3.1 SSL 인증을 위한 Certbot tool 설치

Let's Encrypt SSL 인증서 발급은 Certbot 을 이용합니다.


sudo apt update sudo apt-get install letsencrypt -y


3.2 certbot 으로 인증서를 생성

이렇게 Certbot tool 이 설치 되었다면 SSL 인증을 시작해 보도록 하겠습니다.

우선 웹서버를 중단 시킵니다. 이는 80 포트를 사용하지 않도록 만들기 위한 것 입니다.

실행하는 디렉터리 위치에 따로 영향은 없지만 root 로 이동해서 진행해 봅니다.


cd /root sudo service nginx stop



이제 certbot 명령을 이용해 SSL 인증을 시작합니다. standalone 명령을 사용하고 도메인 이름만으로 인증이 진행되는 -d 옵션을 사용합니다.

* 이때 도메인은 가비아 같은 곳을 통해서 실제 존재해야 합니다.


certbot certonly --standalone -d owl-dev.me -d www.owl-dev.me -d backend.owl-dev.me



그러면 아래 질문들이 나오면서 인증이 진행됩니다. 첫번째로 이메일 주소를 입력하라고 나옵니다. 이메일을 입력해야 다음 단계로 넘어갈 수 있으니 연락을 받을 수 있는 이메일을 입력합니다.  


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) :



그 다음 단계는 서비스 약관 동의 내용으로 모든 서비스가 그러하듯이 Y 를 누르지 않으면 서비스를 이용할 수 없기에 A 를 누릅니다


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 at https://acme-v02.api.letsencrypt.org/directory (A)gree/(C)ancel: A



마지막 질문은 재단에 이메일 주소를 공유할 것인지 질문 합니다. 


Would you be willing 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: Y



그러면 다음과 같이 진행되고 인증을 축하 한다는 메시지가 나옵니다.


Obtaining a new certificate Performing the following challenges: http-01 challenge for example.com http-01 challenge for www.example.com Waiting for verification… Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/example.com/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/example.com/privkey.pem Your cert will expire on 2021-03-25. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew <em>all</em> 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



인증이 완료되면 웹 서버를 재기동 합니다.


sudo service nginx restart



3.3 Nginx 에 ssl 인증서 연동.

ssl 인증서 완료 시, 알려준 생성 위치의 파일 경로를 확인해서 nginx 설정 파일에 아래처럼 설정해 준다.


cd /etc/nginx/sites-available sudo vim default



server { # SSL configuration listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; client_max_body_size 10M; ssl_certificate "/etc/letsencrypt/live/www.owl-dev.me/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/www.owl-dev.me/privkey.pem"; ssl_dhparam "/etc/nginx/ssl/dhparams.pem"; add_header Strict-Transport-Security "max-age=31536000"; server_name www.owl-dev.me; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost:3000; } } server { # SSL configuration # listen 443 ssl http2; listen [::]:443 ssl http2 ; client_max_body_size 10M; ssl_certificate "/etc/letsencrypt/live/backend.owl-dev.me/fullchain.pem"; ssl_certificate_key "/etc/letsencrypt/live/backend.owl-dev.me/privkey.pem"; ssl_dhparam "/etc/nginx/ssl/dhparams.pem"; server_name backend.owl-dev.me; location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_pass https://localhost:5001; } }



설정 완료 후, 문법 이상 유무 확인 하는 명령어 입력 후 이상 없으면 reload 해준다


sudo nginx -t sudo nginx -s reload



3.4. SSL 인증서 갱신 

Let's Encrypt 무료 SSL 인증서는 3개월 단위로 인증서가 발급됩니다. 3개월 마다 수동으로 이를 업데이트 하려면 많은 신경을 써야하고 바쁘다 보면 그냥 지나칠 경우도 있습니다.

이번 부엉이 개발자 사이트를 개발하는데 이 인증서를 사용한 이유도 바로  Let's Encrypt 가 인증서 자동 갱신 방법을 제공하고 있어서 입니다.


우선 쉘 스크립트 파일을 만듭니다. 크론 실행이 가장 안정적으로 작동하는 경우는 /bin 폴더에 쉘 스크립트 파일이 있는 경우라서 이 폴더에 쉘 스크립트 파일을 만듭니다. 


cd /bin sudo vim letsencrypt.sh



여기에 아래와 같은 내용을 추가합니다.


#!/bin/sh sudo service nginx stop sudo certbot renew > /home/pi/Desktop/le_renew.log fuser -k 80/tcp sudo service nginx start



이 자동 쉘 스크립트 파일에 권한을 부여합니다.


sudo chmod +x letsencrypt.sh



이어 크론탭을 열어 편집 상태로 만듭니다.


sudo crontab -e



아래처럼 일정 시간마다 반복 작업하도록 배치잡을 등록합니다


30 4 * * 0 letsencrypt.sh



저장하고 나와서는 크론을 다시 실행 시킵니다.


sudo service cron start





추가. )  DNS 를 이용한 인증서 발급

위에 방식으로 처리하면 대부분 SSL 인증서를 발급받을 수 있지만,  개인 집에서 공유기를 통해 해당 인증서를 받으려고 시도할 경우, 상황에 따라서 ISP 업체에서 공인 IP 에 대한 80 포트 방화벽을 막아둬서 발급이 안될 수가 있습니다.

해당 경우는 이 가비아 같은 DNS 활용해서 발급할 수 있습니다

이 방식은 와일드 카드 방식으로 인증서 발급이 가능하며, 도메인이 연결된 DNS 의 TXT 레코드를 이용해 인증하는 방식입니다. 때문에 서버 관리자가 도메인 DNS 를 관리/수정 해주어야만 하기에 조금 번거로울 수 있습니다.

  • * 인증서 갱신시 마다 DNS 에 TXT 값을 변경해주어야 합니다.


certbot certonly --manual -d *.[도메인] -d [도메인] --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory


[옵션]

--manual : 수동으로 과정을 진행한다

-d : 등록할 도메인을 지정한다. 기존에 사용하던 도메인이름과 와일드 카드 도메인 2개를 입력한다 

--preferred-challenges : DNS를 이용한 인증서 발급방식을 사용하기 위한 옵션이다.

dns-01 : DNS 를 이용한 preferred-challenges 를 사용 시 이 옵션을 사용해야 한다,.

--server : Let's Encrypt 의 ACME (자동화된 인증서 관리 환경) 서버 주소 입력



위 명령을 수행하면 DNS 서버에 _acme-challenge.domain.com 이름의 TXT 레코드를 추가하라고 나오게 되는데 사용중인 도메인 서버에 TXT 레코드에 아래 제시된 Value 를 가비아 같은 도메인 서버에추가합니다.


  • * 해당 TXT 값을 가비아 같은 DNS 에 등록 이전에 Enter 를 누루면 안됩니다.


[가비아에서 해당 정보 입력]




레코드 등록 후 엔터를 눌러 발급을 진행하 주면 아래 경로에 인증서가 발급된 것을 확인할 수 있습니다.


cd /etc/letsencrypt/archive