8 minute read

내 블로그에 HTTPS 프로토콜 지원이 필요할까? 개인 정보를 취급하지 않는다. 쿨한 척 댓글도 없애서 말 그대로 정적 사이트가 됐다. 블로깅 도구도 정적 사이트 생성기인 Jekyll을 사용하고 있다.

nil

하지만 지원하기로 했다. HTTPS가 미래라는 대세에 따르기로 했다. 안전하지 않은 사이트라고 하는 게 거슬린다. 전 정적 HTML만 서빙한다구요!

HTTPS를 지원하기 위해서 필요한 SSL/TLS 인증서

HTTPS(HyperText Transfer Protocol over Secure Socket Layer, HTTP over TLS, HTTP over SSL, HTTP Secure)는 월드 와이드 웹 통신 프로토콜인 HTTP의 보안이 강화된 버전이다. HTTPS는 통신의 인증과 암호화를 위해 넷스케이프 커뮤니케이션즈 코퍼레이션이 개발한 넷스케이프 웹 프로토콜이며, 전자 상거래에서 널리 쓰인다.

HTTPS는 소켓 통신에서 일반 텍스트를 이용하는 대신에, SSL이나 TLS 프로토콜을 통해 세션 데이터를 암호화한다. 따라서 데이터의 적절한 보호를 보장한다. HTTPS의 기본 TCP/IP 포트는 443이다.

HTTPS - ko.wikipedia.org

HTTPS는 SSL/TLS 프로토콜로 암호화해서 HTTP의 보안을 강화한다. TLS 프로토콜로 통신하기 위한 재료가 필요하다. 그중 하나가 SSL/TLS 인증서(certificate)이다. SSL은 폐기되고 TLS로 바뀌었지만 SSL 인지도가 넘사벽이다. 인지도만 따라서 SSL 인증서라고 하자니 최신 표준을 안 지키는 것 같고 TLS 인증서라고 하자니 SSL 인증서에 대한 설명을 한 번 더 해야 할 것 같다. 다들 이런 고민을 했나 보다. SSL/TLS 인증서라고 부르기도 한다. 나도 애매한 이 용어가 마음에 들어서 이렇게 불러야겠다.

SSL/TLS 인증서는 어디서 구할 수 있을까?

인증서의 역할은 클라이언트가 접속한 서버가 클라이언트가 의도한 서버가 맞는지를 보장하는 역할을 한다. 이 역할을 하는 민간기업들이 있는데 이런 기업들을 CA(Certificate authority) 혹은 Root Certificate라고 부른다.

HTTPS와 SSL 인증서 - 생활코딩 - opentutorials.org

인증서는 쉽게 만들 수 있다. 개발할 때는 자체 서명 인증서(Self-signed certificate)를 금방 만들어서 쓴다. 만들기 쉬우니 신뢰의 영역으로 문제가 바뀐다. 이 인증서를 믿을 수 있나? CA(Certificate authority)가 그 역할을 해준다. 돈 냄새가 난다. 신뢰를 만드는 건 돈이 들기 때문이다.

어떤 CA에서 인증서를 받아야 할까?

어느 CA에서 인증서를 발급받을까? - Let’s Encrypt CA

AWS(Amazon Web Services)가 가장 먼저 생각났다. 도메인을 ’Amazon Route 53’에서 구매하거나 관리하고 블로그를 모두 AWS 안으로 가져가면 HTTPS를 손쉽게 지원할 수 있다. 하지만 HTTPS 지원 때문에 호스팅 서비스까지 바꾸는 건 고민해 봐야 한다. 선택지가 하나만 있는 게 아니기 때문이다.

지금 사용하고 있는 호스팅 서비스인 카페24의 보안서버 SSL 인증서를 살펴봤다. <2024-11-02 Sat> 기준이다.

사양명 SSL Basic Positive 라이트 SSL 스탠다드 SSL 와일드카드 Positive 멀티도메인
1년 사용료 (VAT 포함) 0원 38,500원 66,000원 462,000원 143,000원
웹호스팅 설치비 (VAT 포함) 11,000원/1회 무료 무료 - -
서버호스팅 설치비 (VAT 포함) - 33,000원/1회 33,000원/1회 33,000원/1회 33,000원/1회
도메인 추가 (VAT 포함) - - - - 38,500원/개당

SSL Basic이 있다. 이걸로 충분할 것 같다. 섣불리 결제하지 말고 스크롤을 내려봐야 한다.

SSL Basic 유의사항

  • SSL Basic 상품은 Let’s Encrypt 인증서의 발급과 설치, 그리고 호스팅 서비스 종료일까지의 자동 연장을 포함하는 관리 서비스입니다.
  • SSL Basic 상품 구매 없이도 Let’s Encrypt 인증서의 발급, 설치 및 연장 작업을 직접 수행할 수 있습니다.
  • SSL Basic 상품 구매 시 인증서 발급기관(ISRG)의 Let’s Encrypt 이용 약관에 동의하는 것으로 간주합니다.
  • 10G 광아우토반 FullSSD+ 웹호스팅 PHP8 환경에 신청할 수 있습니다. (자이언트플러스 사양 제외)
  • 웹호스팅에 연결된 도메인 중 카페24에서 구매한 도메인에 설치할 수 있습니다.

보안서버 SSL 인증서 - 스페셜호스팅 - 카페24 호스팅 - hosting.cafe24.com

카페24에서 구매한 도메인인 경우에만 가능하다. AWS처럼 SSL 인증서는 인질 세트인가? 무료 SSL 인증서를 도메인 서비스와 같은 유료 서비스에 묶는다.

1년 동안 38,500원으로 ’Positive 라이트’ 상품을 결제해서 마음 편히 HTTPS 지원해 볼까 했지만 바로 유료 서비스를 쓰면 억울하다. ’Let’s Encrypt’ 비영리 CA에서 무료 인증서를 발급받자. 단점은 짧은 인증 유효 기간이다. 90일만 유효한 인증서를 발급해준다. 지금은 크게 문제 되지 않는다. 블로그 글을 배포하는 과정이 자동화가 되지 않았기 때문이다. 배포 스크립트를 직접 실행하고 있다. 일주일에 블로그 글 배포를 항상 하니깐 인증서를 갱신해서 업로드하는 게 크게 힘들지 않을 것 같다.

Certbot으로 인증서 발급

Certbot is a free, open source software tool for automatically using Let’s Encrypt certificates on manually-administrated websites to enable HTTPS.

Certbot은 수동으로 관리하는 웹사이트에서 Let’s Encrypt 인증서를 자동으로 사용하여 HTTPS를 활성화하는 무료 오픈 소스 소프트웨어 도구입니다.

About Certbot - certbot.eff.org

Let’s Encrypt 인증서를 발급받으려면 certbot 프로그램을 사용해야 한다.

  1. Obtaining a certificate: automatically performing the required authentication steps to prove that you control the domain(s), saving the certificate to etc/letsencrypt/live and renewing it on a regular schedule.
  2. Optionally, installing that certificate to supported web servers (like Apache or nginx) and other kinds of servers. This is done by automatically modifying the configuration of your server in order to use the certificate.

  3. 인증서 받기: 도메인을 제어하고 있음을 증명하기 위해 필요한 인증 단계를 자동으로 수행하고, 인증서를 /etc/letsencrypt/live/에 저장하고 정기적으로 갱신합니다.
  4. 선택 사항으로 해당 인증서를 지원되는 웹 서버(예: Apache 또는 nginx) 및 기타 종류의 서버에 설치합니다. 이는 인증서를 사용하기 위해 서버의 구성을 자동으로 수정하여 수행됩니다.

User Guide — Certbot 2.12.0.dev0 documentation - eff-certbot.readthedocs.io

certbot은 인증서 받기는 물론 웹 서버에 인증서를 사용하기 위한 구성까지 자동으로 해준다. 하지만 카페24에서는 조작할 수 없으므로 certbot으로 인증서 받기만 한다. certonly --manual 옵션을 사용해야 한다.

cerbot 설치

macOS를 기준으로 Homebrew로 설치한다.

brew install certbot

소유 증명 방법 선택

무료로 인증서를 발급해 준다고 했지 아무한테나 발급해 준다고는 안 했다. 호락호락하지 않다. SSL/TLS 인증서를 발급받을 도메인을 내가 소유하고 있다는 걸 증명해야 한다. /.well-known/acme-challenge/ 디렉터리에 certbot이 시키는 대로 파일을 복사해서 소유를 증명하는 ’http challenge’가 있고 ’DNS TXT 레코드’에 cerbot이 시키는 대로 값을 기록해서 소유를 증명하는 ’dns challenge’가 있다.

API를 제공하는 DNS 서비스를 사용한다면 ’dns challenge’도 고려해 볼 수 있겠지만 지금 사용하고 있는 서비스에는 그런 거 없다. 파일을 복사하는 게 스크립트로 짜기 쉬워서 ’http challenge’ 방식으로 소유를 증명한다. --preferred-challenges http 옵션을 사용하면 된다.

RSA key type을 사용

디폴트로 설정하면 ESDSA 키타입으로 공개키와 개인키를 만든다. 카페24는 RSA 키타입만 지원하므로 --key-type rsa 옵션을 추가해야 한다.

hook을 사용해 소유 증명에 사용하는 파일 자동 생성 및 정리

http challenge를 할 거라서 /.well-known/acme-challenge/ 디렉터리에 certbot이 시키는대로 파일을 만들어야 한다. 귀찮은 과정인데 hook을 옵션으로 제공해서 스크립트로 해결할 수 있다.

certbot certonly \
    --manual \
    --manual-auth-hook /path/to/http/authenticator.sh \
    --manual-cleanup-hook /path/to/http/cleanup.sh \
    -d secure.example.com

소유 증명을 하기 전후에 호출하는 hook 스크립트를 설정할 수 있다. 다음과 같은 순서로 호출된다

  1. --manual-auth-hook 옵션으로 정의한 파일이 있으면 실행
    • 위 예제에서는 /path/to/http/authenticator.sh 스크립트 실행
  2. http 또는 dns challenge 검증
  3. --manual-cleanup-hook 옵션으로 정의한 파일이 있으면 실행
    • 위 예제에서는 /path/to/http/cleanup.sh 스크립트 실행

hook 스크립트에서 사용할 수 있는 환경 변수를 참고해서 짤 수 있으나 예제 스크립트를 조금만 고쳐서 쓰면 된다. http challenge는 파일을 복사하면 돼서 별로 수정할 것도 복잡할 것도 없다.

--manual-auth-hook 옵션으로 사용할 파일 내용이다. 인증서를 만드는 머신과 설치해야 하는 머신이 달라서 ssh 프로그램으로 파일을 생성한다.

#!/bin/bash

ssh user@home.com "mkdir -p /user/www/.well-known/acme-challenge"
ssh user@home.com "echo $CERTBOT_VALIDATION > /user/www/.well-known/acme-challenge/$CERTBOT_TOKEN"

.well-known/acme-challenge 디렉터리가 없을 때를 대비해서 생성부터 하고 소유 증명에 사용할 파일을 생성한다.

다음은 --manual-cleanup-hook 옵션으로 사용할 파일 내용이다.

#!/bin/bash
ssh user@home.com "rm -f /user/www/.well-known/acme-challenge/$CERTBOT_TOKEN"

검증 후에 호출하는 파일이다. 소유 증명에 사용한 파일을 삭제한다.

수동 인증서 발급에 사용하는 스크립트

아래는 사용하고 있는 스크립트다.

#!/bin/sh

set -e

cd "$(dirname "$0")/.."

if ! command -v certbot > /dev/null; then
    echo "FAILED: 'certbot' is not installed. brew install certbot"
    exit 1
fi

mkdir -p .local/certbot/config
mkdir -p .local/certbot/work
mkdir -p .local/certbot/logs

certbot certonly \
    --manual \
    --preferred-challenges=http \
    --config-dir .local/certbot/config \
    --work-dir .local/certbot/work \
    --logs-dir .local/certbot/logs \
    --manual-auth-hook script/authenticator.sh \
    --manual-cleanup-hook script/cleanup.sh \
    --agree-tos \
    --key-type rsa \
    -m user@home.com \
    -d home.com \
    -d www.home.com

open https://hosting.cafe24.com/?controller=myservice_ssl_custom

ssh 프로그램을 사용하고 있어서 sudo를 사용하지 않아도 되게 디렉터리를 설정했다. sudo를 사용하게 기본 설정을 사용한다면 root 계정 ssh 키를 만들고 원격 머신에 authorized_keys를 등록해야 한다. 마지막엔 카페24 인증서 등록 페이지를 웹브라우저로 열게 했다. 어차피 방문할 거 스크립트에 추가했다.

인증서 발급 결과

...
Successfully received certificate.
Certificate is saved at: /Users/ohyecloudy/.local/certbot/config/live/home.com/fullchain.pem
Key is saved at:         /Users/ohyecloudy/.local/certbot/config/live/home.com/privkey.pem

이렇게 공개키(fullchain.pem)와 비밀키(privkey.pem)가 생긴다.

인증서 갱신

위에서 사용하는 스크립트를 그대로 사용해도 괜찮다. 알아서 renew를 할 것인지 물어본다.

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the certificate (may be subject to CA rate limits)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2

2를 입력하고 갱신한 인증서를 카페24 인증서로 등록한다.

카페24 인증서 등록

nil

인증서관리 > 외부인증서 관리 페이지를 방문해서 위에서 만든 공개키(fullchain.pem) 내용을 인증서(SSL CRT)에 붙여 넣고 인증서 확인을 누른다. 비밀키(privkey.pem) 내용을 개인키(private key)에 붙여 넣고 신청하면 된다.

HTTP를 HTTPS로 리다이렉션 세팅

HTTPS 프로토콜을 지원하게 됐으니 HTTP로 되어 있는 예전 링크를 타고 들어오면 HTTPS로 리다이렉션되게 하자. Apache HTTP Server로 웹호스팅 서비스가 세팅되어 있어서 .htaccess 파일을 수정했다.

검색하면 아래와 같은 코드가 가장 많이 보인다.

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

하지만 카페24에서 이렇게 하면 동작하지 않는다. 대신 X-Forwarded-Proto 헤더를 사용해서 확인해야 한다.

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

잘 동작한다. HTTP 프로토콜로 접속하면 프로토콜만 빼고 나머지는 유지한채 HTTPS 프로토콜로 교체한다. 왜 X-Forwarded-Proto 헤더 정보로 검사를 해야 할까?

X-Forwarded-Proto (XFP) 헤더는 클라이언트가 당신의 프록시 또는 로드 밸런서에 접속하는 데에 사용했던 프로토콜(HTTP 또는 HTTPS)이 무엇인지 확인하는 사실상의 표준 헤더입니다. 당신의 서버 접근 로그들은 서버와 로드 밸런서 사이에서 사용된 프로토콜을 포함하고 있습니다. 그러나 클라이언트와 로드밸런서에 사용한 프로토콜은 포함되어 있지 않습니다. 클라이언트와 로드밸런서 간의 사용된 프로토콜을 확인하기 위해서, X-Forwarded-Proto 요청 헤더가 사용될 수 있습니다.

X-Forwarded-Proto - HTTP - MDN - developer.mozilla.org

카페24에서 호스팅하는 웹서버와 클라이언트 사이에 로드 밸런서나 프록시가 있어서 HTTPS 변수로는 확인이 안 됐다. X-Forwarded-Proto 헤더가 사실상 표준 헤더라니 안심하고 이걸로 확인해도 되겠다.

마치며

정적 사이트 생성기로 만든 블로그지만 HTTPS 프로토콜 지원이라는 대세를 따르기로 했다. 이제 ohyecloudy.com에 방문하면 ’안전하지 않은 사이트’란 경고 문구가 나오지 않는다.

HTTPS를 지원하기 위해서는 SSL/TLS 인증서가 필요하다. 카페24에서 일 년에 38,500원을 내면 인증서를 사용할 수 있는 서비스를 제공한다. 유료 서비스를 사용하는 대신 Let’s Encrypt 비영리 CA에서 무료 인증서를 발급받아 사용하기로했다. 유효기간이 90일인 인증서만 발급받을 수 있는 게 단점이다. 아니 지금 나처럼 자동화를 지원하지 않는 카페24 같은 웹호스팅 서비스를 사용하는 사람에게는 단점이다. 자동화만 할 수 있으면 유효기간 90일은 문제가 되지 않는다.

일주일에 한 번 정기적으로 블로그 포스트를 발행하고 있어서 인증서 갱신도 같이 챙길 수 있을 것 같다. 지금 하고 있는 반자동에 하나 더 얹을 뿐이다. 반자동도 스노볼링이 된다. 그래서 인증서를 발급받는 스크립트를 만드는 것으로 마무리했다.

nil

38,500 Positive 라이트 값을 Let’s Encrypt 재단에 기부했다. 땡큐~

링크