RFC 8737
1. Let's Encrypt의 ALPN-01 검증을 통과하려면 이 스펙을 구현한 구현체가 필요하다.
그 중 하나가 dehydrated이다.
https://github.com/lukas2511/dehydrated
GitHub - dehydrated-io/dehydrated: letsencrypt/acme client implemented as a shell-script – just add water
letsencrypt/acme client implemented as a shell-script – just add water - dehydrated-io/dehydrated
github.com
2. 깃허브에서 필요한 스크립트와 설정 파일들을 내려받는다. 디렉터리 위치는 달라도 된다.
# 최종 발급될 인증서 저장 위치 생성
mkdir /etc/nginx/certs/
# ALPN 챌린지를 위해 dehydrated가 사용하는 위치 생성
mkdir /var/www/dehydrated/
# dehydrated 설치 및 응답기가 사용하는 디렉터리 생성
mkdir -p /etc/dehydrated/alpn-certs/
cd /etc/dehydrated/
# dehydrated 다운로드
wget https://raw.githubusercontent.com/lukas2511/dehydrated/master/dehydrated
chmod u+x dehydrated
# 설정 파일 다운로드
wget https://raw.githubusercontent.com/lukas2511/dehydrated/master/docs/examples/config
echo "mydomain.net" > domains.txt
3. domains.txt에 본인의 도메인 주소를 적는다.
오직 도메인 주소만 적는다.
4. 설정 파일이 좀 긴데, 필요한 부분을 설정해야 한다.
본인은 nginx를 사용할 것이라 CERTDIR을 이렇게 설정했다. CERTDIR은 최종적으로 발급된 인증서가 저장될 위치이다. {BASEDIR} 등의 설정이 가능한데, 복잡성을 줄이고 싶다면 절대 경로를 추천한다.
CHALLENGETYPE="tls-alpn-01"
ALPNCERTDIR="/etc/dehydrated/alpn-certs"
CERTDIR="/etc/nginx/certs"
5. 이제 Let's Encrypt에 ALPN 요청과 응답을 주고받기 위한 ALPN 응답기가 필요하다. 아래 링크로 가서 샘플 코드를 복사하여 저장한다.
필자는 alpn-responder.py라고 저장했다.
https://github.com/dehydrated-io/dehydrated/blob/master/docs/tls-alpn.md#example-responder
import ssl
import socketserver
import threading
import re
import os
ALPNDIR="/etc/dehydrated/alpn-certs"
PROXY_PROTOCOL=False
FALLBACK_CERTIFICATE="/etc/ssl/certs/ssl-cert-snakeoil.pem"
FALLBACK_KEY="/etc/ssl/private/ssl-cert-snakeoil.key"
''' 중략 '''
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 10443
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler, bind_and_activate=False)
server.allow_reuse_address = True
try:
server.server_bind()
server.server_activate()
server.serve_forever()
except:
server.shutdown()
여기서 Let's Encrypt의 검증을 받으려면 443 포트로 진행해야 한다. 따라서 10443을 443으로 바꿔준다.
또한, 우분투 24.04 LTS에는 /etc/ssl/certs/ 디렉터리에 ssl-cert-snakeoil 이라는 셀프사인 인증서가 없기 때문에 따로 설치해 주어야 한다.
sudo apt install ssl-cert
6. 응답기를 실행한다. 443 포트를 사용하므로 sudo로 실행하여야 한다.
chmod u+x alpn-responder.py
sudo ./alpn-responder.py &> /dev/null &
7. dehydrate를 아래처럼 실행한다. 처음 실행하면 사용자 등록 및 동의사항을 물어본다.
./dehydrated --register --accept-terms
8. 다시 dehydrate를 아래처럼 실행한다.
./dehydrated -c -f config
9. ALPN-01 챌린지를 통과하면 아래처럼 서명된 인증서와 개인키, 인증서 체인 파일이 설정한 위치에 저장된다.
필자는 설정 오류로 6번 만에 통과했다. 한 시간에 5회 이상 시도하면 30분 밴 당한다.
me@server:/etc/nginx/certs/mydomain.net$ ls -l *.pem
-rw------- 1 root root 1234 May 16 07:46 cert-0000000000.pem
lrwxrwxrwx 1 root root 12 May 16 07:46 cert.pem -> cert-0000000000.pem
-rw------- 1 root root 1234 May 16 07:46 chain-0000000000.pem
lrwxrwxrwx 1 root root 12 May 16 07:46 chain.pem -> chain-0000000000.pem
-rw------- 1 root root 1234 May 16 07:46 fullchain-0000000000.pem
lrwxrwxrwx 1 root root 12 May 16 07:46 fullchain.pem -> fullchain-0000000000.pem
-rw------- 1 root root 123 May 16 07:46 privkey-0000000000.pem
lrwxrwxrwx 1 root root 12 May 16 07:46 privkey.pem -> privkey-0000000000.pem
fullchain.pem이랑 privkey.pem만 가져다 쓰면 된다. privkey는 정말 잘 관리해야 한다.
10. Nginx 설정하기
server {
listen 443 ssl;
server_name mydomain.com;
ssl_certificate /etc/nginx/certs/mydomain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/mydomain.com/privkey.pem;
...
11. 그러면 갱신할 때는 어떻게 하나요?
[6. 응답기 실행] → [8. hydrated 실행] → [nginx -t && nginx -s reload] 순으로 하면 됩니다.
12. 왜 쉬운 HTTP validation 안쓰고 어렵게 하나요?
SKT 공유기 사용중이라 TCP 80 포트포워딩이 안 돼서 그랬습니다.