Docker로 간단하게 Let's Encrypt 와일드카드 인증서 발급받기

이 포스트에서는 Docker를 이용하여 의존성 없이 쉽고 빠르게 인증서를 발급 받는 방법을 설명합니다.

2019. 01. 12. #docker #security

You can read this post in English.

Let's Encrypt는 웹 사이트에 붙힐 수 있는 HTTPS 인증서를 무료로 제공하는 인증 기관입니다. 누구나 복잡한 과정과 비싼 비용 없이 암호화된 웹 서비스를 구축할 수 있도록 만들자는 목적으로 설립되었습니다. (Wikipedia 문서)

let's encrypt logo

Let's Encrypt의 인증서를 발급 받는 방법은 여러가지가 있지만, 그 중에서도 공식 클라이언트인 certbot을 이용하는 방법이 가장 유명합니다. 하지만 certbot은 python 및 몇몇 네이티브 라이브러리에 의존성이 있고, OS마다 패키지의 maintain 속도가 조금씩 다르다보니 예상치 못한 동작을 하며 발급이 번거로워지는 경우가 종종 있습니다. 특히 작년에 공개된 Let's Encrypt 와일드카드 인증서의 경우, 아직 대부분의 OS 환경에서는 발급이 불가능한 상황입니다.

이 포스트에서는 Docker를 이용하여 의존성 없이 쉽고 빠르게 와일드카드 인증서를 발급 받는 방법을 설명합니다.

Certbot의 도메인 소유 인증 절차

본격적인 발급 절차에 앞서, certbot이 어떻게 도메인의 소유권을 확인하는지 알아봅시다. 웹 서버를 통하는 방법과, DNS 레코드를 통한 방법 등 크게 두 가지로 나뉘어집니다.

웹 서버를 통한 도메인 인증

Certbot이 직접 웹 서버를 띄운 뒤, URL을 통해 해당 웹 서버로 접속을 시도하여 도메인의 소유를 검증하는 방법입니다.

예를 들어 yourdomain.com이라는 도메인의 인증서를 발급받고자 한다면, certbot은 yourdomain.com/.well-known/acme-challenge URL을 통해 여러분의 서버에 접속하여 실제 발급을 시도 중인 서버가 맞는지 확인하게 됩니다.

  • 장점
    • 대부분의 경우에 쉽고 간단합니다. 명령어 한 줄로 인증서 발급부터 nginx, haproxy 등의 리버스 프록시 인증서 셋팅까지 자동으로 해주거든요.
  • 단점
    • 운영중인 환경에서 인증서를 발급받기 난감합니다. 그 이유는, 80(443) 포트로 직접 웹 서버가 떠야하기 때문입니다. 운영중인 서비스에서 두 포트 중 하나만 사용한다면 괜찮지만, 만약 두 포트를 모두 사용하고 있다면 인증서를 발급 받기 위해 서비스를 잠시 내려야하는 치명적인 단점이 있습니다.
    • 방화벽이 엄격하게 설정된 경우에는 발급 과정이 번거롭습니다. Certbot은 접속할 URL 경로를 수동으로 지정할 수 없기 때문에, 위에서 언급한 .well-known/acme-challenge 경로를 열어주어야합니다.

DNS를 통한 도메인 인증

대부분의 서비스에서 많이 사용하는 방식입니다. 인증 토큰을 TXT 레코드로 등록하여 도메인의 소유권을 인증합니다.

  • 장점
    • 서버의 설정을 전혀 건드릴 필요가 없습니다. 때문에 운영중인 환경에서도 쉽게 발급이 가능합니다.
  • 단점
    • DNS 레코드를 등록해주는 절차가 번거로울 수 있습니다. 개인 단위에서는 문제가 없겠지만, 단체나 회사에서 관리하는 도메인의 경우 레코드를 건드리는게 불가능할 수도 있고요.
    • DNS 전파 시간을 기다려야하는 점도 귀찮은 점 중 하나입니다.

이 포스트의 목표는 운영 환경을 최대한 손대지 않고 간단하게 발급받는 것이므로, 두 번째 방법인 DNS를 통해 인증을 시도하도록 하겠습니다.

인증서 발급받기

Certbot에서는 공식적으로 certbot/certbot docker 이미지를 지원하고 있습니다. Python 기반의 베이스 이미지에, 필요한 각종 라이브러리가 설치되어있으므로 여러분의 서버나 컴퓨터에는 아무것도 설치를 할 필요가 없습니다.

인증서를 발급 받는 커맨드는 다음과 같습니다.

docker run -it --rm --name certbot \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  certbot/certbot certonly -d '*.yourdomain.com' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

우선 docker run의 옵션을 살펴봅시다.

  • -it : interactive + tty. 요약하자면 터미널을 통해 컨테이너와 상호작용하겠다는 플래그입니다. Certbot은 발급 과정 중에 커맨드라인을 통해 유저가 입력해야하는 정보들이 있으므로 반드시 필요합니다.
  • --rm : 작업을 종료하고 컨테이너가 내려가면 자동으로 그 컨테이너를 삭제합니다.
  • -v '...' : 인증서가 저장될 경로를 볼륨으로 장착합니다. 호스트의 경로는 꼭 위와 같을 필요는 없지만, 많은 자동화 스크립트들이 위 경로에 인증서가 존재한다는 전제로 작동하므로 유지하는게 좋습니다.

다음은 certbot 명령어의 옵션을 살펴봅시다.

  • -d '*.yourdomain.com' : 인증서를 발급받을 도메인입니다. 여기서는 와일드카드 인증서를 예시로 들었지만, 도메인 인증서 또한 동일한 방식으로 발급이 가능합니다.
  • --manual --preferred-challenges dns : 위에서 언급했던 두 가지 방식 중, DNS를 통해 도메인을 인증하겠다는 플래그입니다.
  • --server https://~~~ : 발급을 요청할 let's encrypt 서버 주소입니다. 참고로 와일드카드 인증서는 v02 서버에서만 발급이 가능합니다.

발급 과정은 다음과 같습니다. 우선 위의 커맨드로 발급을 시작합니다. (yourdomain.com 부분을 여러분의 도메인으로 바꿔야한다는 점에 유의하세요!)

>>> docker run ......

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

이메일 주소를 입력합니다. 여기서 입력한 주소로 인증서 갱신 및 보안 관련 이메일이 전송됩니다.

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

EFF 재단에 이메일 주소를 공유함에 동의/거절합니다.

Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for yourdomain.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o:

인증서 발급을 시도한 머신의 IP 주소가 공개적으로 기록될 수 있음을 유의하라는 문구입니다. 만약 IP 주소가 공개되는게 꺼려지신다면 발급을 중단하세요. 대부분의 경우에는 머신의 IP 주소가 곧 DNS상의 A 레코드 주소이기 때문에 문제가 없을 것입니다.

여기서 Y를 누르면 DNS 레코드로 등록할 토큰이 발급됩니다.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.yourdomain.com with the following value:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

AAAA... 에 해당하는 위치에 발급된 토큰을 _acme-challenge.yourdomain.com 도메인의 TXT 레코드로 등록해줍니다.

도메인 전파에는 다소 시간이 소요되므로, dig 등의 커맨드를 통해 도메인이 잘 전파되었는지 확인한 후 엔터를 눌러야합니다. 아직 전파가 안된 경우에는 발급 절차를 다시 수행해야하고, 재시도 횟수에는 제약이 있으므로 전파 시간을 여유롭게 잡는게 좋습니다.

마지막으로 엔터를 누르면,

Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/yourdomain.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/yourdomain.com/privkey.pem
   Your cert will expire on 2019-04-12. 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

인증서 발급이 완료되었습니다!

인증서 갱신

발급된 인증서는 단 3개월간 이용이 가능합니다. 이렇게 기간이 짧은 이유는

  1. 인증서 갱신의 자동화를 권장하고
  2. 만약의 사태에 인증서가 무력화되더라도 영향 기간을 3개월 이하로 줄일 수 있기 때문입니다.

이러한 취지에 맞게 인증서 갱신을 crontab 등을 통해 자동화 할 것을 추천드립니다.

Certbot을 통해 발급한 인증서는 마찬가지로 certbot 커맨드를 통해 갱신할 수 있습니다.

>>> docker run -it --rm --name certbot \
  -v '/etc/letsencrypt:/etc/letsencrypt' \
  -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
  certbot/certbot renew --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/yourdomain.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

The following certs are not due for renewal yet:
  /etc/letsencrypt/live/yourdomain.com/fullchain.pem expires on 2019-04-12 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

발급할 때 사용했던 커맨드의 도메인 부분을 renew로만 변경해주면 됩니다. 방금 발급한 인증서는 아직 갱신이 가능한 날짜가 되지 않았다고 뜨네요.

.

.

.

이렇게 docker를 이용하여 커맨드 단 하나로 간단하게 인증서를 발급받는 방법에 대해 살펴보았습니다. 여러분의 사이트에 아직도 HTTPS 인증서가 달려있지 않다면 지금 바로 시도해보세요.

크리에이티브 커먼즈 라이선스

이 저작물은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

© 2011 - 2020 Do Hoerin, LYnLab