제목 그대로다. 웹 사이트나 웹 서비스를 운영할 때 이 세 단어를 글자 그대로만 알아둬도 프롬프트를 2~3번은 아낄 수 있다. HTTPS, SSL, Let's Encrypt. 80포트니 443포트니 이런 건, 그 이후에 자연히 따라오는 정보들이다. 거꾸로도 가능하다. 80포트와 443포트만 알아둬도 저 셋은 따라온다. 그렇게치면 포트 번호까지 다섯 단어를 알아둬야 하는걸까?
우선, 이전 글에 이어서 바로 설정해서 쓸 내용을 먼저 옮긴다.
Let's Encrypt SSL/TLS 구축 및 HSTS 보안 활성화
가장 간단히 쓰는 HTTP-01 챌린지 방식이다. 이 방식으로 설정하면 애초에 Nginx 설정까지 자동으로 다 입력된다.
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d 도메인 -d 도메인
# 갱신 크론 데몬 자동 동작 테스트 (Systemd 연동)
sudo certbot renew --dry-run
서버에 자동 갱신 타이머가 켜져 있는지 확인하는 가장 확실한 방법은 2가지다.
systemctl status certbot.timer
또는
cat /etc/cron.d/certbot
과거에는 crontab에 따로 등록해 두기도 했다. 적당히 인증서 만료 시점에 갱신 상태를 확인해서 crontab 수동 설정 없이 갱신되는지 직접 확인하는 노고는 한두번 하는 것이 안전하다.
/etc/nginx/sites-available/default
Nginx에 자동으로 설정값이 들어가는 것과 별개로, 다른 운영 요소들을 위해 수정해야 할 일이 추후에 더 생길 것을 대비하기 위해 SSL 인증서 패스 경로 호출 위치는 미리 파악해 두는 것이 좋다.
server {
listen 80 default_server;
listen [::]:80 default_server;
return 301 https://$server_name$request_uri; # HTTPS 강제 리다이렉션
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
# SSL 인증서 패스 경로 연동
ssl_certificate /etc/letsencrypt/live/도메인/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/도메인/privkey.pem;
# 30일 HSTS 안정성 테스트 적용 (서브도메인 포함)
add_header Strict-Transport-Security "max-age=2592000; includeSubDomains" always;
# HSTS 헤더 정책 강제 적용 (1년)
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
root /a36/wordpress;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
}
}
HSTS는 단계별로 기간을 늘려가며 preload 옵션 없이 시작하는 것이 좋다고 한다. 우선, 기본 설정은 여기까지다.
만약 렛츠 인크립트가 아니라 유료 SSL 인증서를 쓴다면, 적용 매뉴얼은 해당 업체에서 제공해준다. 인증서 파일을 넣는 위치는 크게 다르지 않으므로 어렵지 않게 적용할 수 있다.
Let's Encrypt
렛츠 인크립트에 대한 설명이나 사용법 등은 쉽게 찾을 수 있다. 위에서 쓴 HTTP-01 챌린지 이외에도 DNS-01 챌린지 방식도 많이 쓴다. AI한테 묻기 전에 공식 문서를 꼭 한번 보는 것을 추천한다. 혹은 공식 문서 링크를 기준으로 AI한테 묻는 것을 추천한다.
자동 갱신
다만, 인증서 자동 갱신 설정을 위해 따라 붙는 요건이 가장 간단한 건 HTTP-01 챌린지 방식이다. DNS-01 챌린지 방식에서 자동 갱신을 적용하려면, DNS 제공사의 API를 활용해서 도메인 설정을 매 갱신에 맞춰서 자동으로 적용하도록 추가 작업을 붙여야 한다. 다만, 와일드카드 인증서를 적용할 수 있는 방법이므로 수시로 도메인을 추가하는 수준으로 규모가 커질 땐 꼭 고려하는 것이 좋다.
자동 갱신 주기도 과거에는 90일 단위였었다. 그런데 앞으로는 이 주기가 짧아진다.
결국 자동 갱신을 얼마나 편하게 적용할 수 있느냐가 운영 편의성에 영향을 준다.
로컬 호스트에서는 SSL을 해소할 수 있는가
해소할 수는 있다. 귀찮을 뿐이다. 그래서 귀찮음을 이겨내지 않으면, 테스트 환경을 단순히 로컬 호스트에 구성하면, 라이브 환경과 차이가 생기기 마련이다. 그러다보니 애초에 따로 별도 서버를 테스트 서버로 마련하고 서브 도메인을 테스트용으로 활용하면 SSL 관련한 귀차니즘 스트레스는 해소할 수 있다. 대신, 그 테스트 서버가 유료라면 비용을 추가 지불해야 한다.
이 귀찮음에 대한 내용도 렛츠 인크립트 공식 문서에 가이드가 있다.
HSTS
위에서 잠깐 등장했던 HSTS는 쉽게 말하면 강제로 HTTPS로 접속하도록, 접속자 브라우저에 저장해서 사용하도록 한다. 궁극적으로 HSTS 관리 기관에 도메인을 등록하면, 사용자 대부분이 사용하는 브라우저에 기본 내장 시킬 수도 있다.
내가 운영하는 라이브 서버에서는 HTTPS 접속으로 강제하기 위해 Nginx 설정 파일에 서버 블록 3개를 추가 할애해서 사용한다. www에서 오는 트래픽, 숫자IP로 들어오는 트래픽, 80포트로 들어오는 트래픽 등등을 모조리 HTTPS에 붙은 기본 도메인으로 리다이렉트하도록 넣어놨다. 여기에서도 HSTS를 추가로 넣을 수 있다.
HSTS 설정으로 인해 보안성을 높이는 이야기와 설명은 AI에게 양보하고, 이게 100%가 아닌 상황에 대해서만 살짝 언급하겠다.
HSTS는 '브라우저가 서버로부터 헤더를 받은 적이 있다'는 사실을 로컬 저장소(Profile/Cache)에 기록해두고 쓰는 캐싱 메커니즘이기 때문에, 세션과 환경의 변화에 따라 동작이 달라진다.
단순 크롤러나 AI 에이전트의 경우 (HSTS 무시)
Python requests, urllib, scrapy, Node.js의 axios, curl 등 단순 HTTP 클라이언트 라이브러리나 API 기반 봇들은 웹 표준 브라우저 엔진이 아니므로 HSTS 헤더(Strict-Transport-Security) 자체를 완전히 무시한다. 그래서 따로 Nginx에 추가해둔 서버 블록 설정이 HTTPS로 이들을 리다이렉트하도록 일조한다.
헤드리스 브라우저
AI 사용량이 늘면서 Puppeteer, Playwright, Selenium 등 헤드리스 브라우저 접근량도 함께 증가했다. 크로미움(Chromium)이나 파이어폭스(Firefox) 엔진을 백그라운드에서 실행하는 헤드리스 브라우저들은 실제 브라우저와 동일한 렌더링 엔진과 네트워크 엔진을 사용하므로 기본적으로 HSTS 스펙을 지원한다. 하지만 사용자마다 생명 주기(Lifecycle)나 프로필 보존 여부에 따라 차이는 생길 수밖에 없다.
브라우저 로컬 저장소에 기록하는 방식이니, 기록하지 않고 매번 새로 읽는 브라우저라면 매번 HSTS 설정값을 새롭게 저장하고 지워진다.
Preload
Preload 옵션을 쓸 수 있는 단계까지 올라간다면, 나아질까? 어차피 구멍은 있기 마련이다. 그래도 이런 세상이 있음은 알고 있으면 언젠가는 쓰는 날이 오려나?
어쨌든, 이왕 HSTS를 쓰기 시작한다면 최종적으로 HSTS Preload 리스트에 도메인을 공식 등록하는 단계까지 진행하는 것이 진정한 의미의 HSTS 강제화다. Preload 등록 최소 조건은 꽤나 엄격하다. 또한, 한순간의 실수로 브라우저에서 도메인이 영구 차단되는 결과도 생길 수 있으므로, 최대한 유연하게 테스트 기간을 가진 후에 Preload 리스트 등록에 도전하는 것이 좋을 것이다.
HTTPS가 당연한 세상이다
국내 뿐 아니라, 해외에도 여전히 HTTPS가 적용되지 않은 사이트는 많다. AI로 웹 페이지를 만들어서 마구잡이로 배포 가능한 현 시점에선, 무궁무진한 케이스가 생길 수 있고 난립하고 있다.
과거에는 HTTPS가 데이터 도청, 데이터 변조, 사이트 위조로 부터 보안을 지켜준다고 말했었다. 하지만 렛츠 인크립트 등장 이후 사이트 위조를 막는다는 의미는 논리적으로는 무력화됐지 않은가 한다. 비슷한 모양의 도메인과 디자인으로 렛츠 인크립트를 써서 HTTPS 적용해두면, 구분하기 쉽지 않으니까. HTTPS는 피싱 사이트를 막지도 못하고, 서버 해킹을 보호해주지도 못하고, 사용자 PC 악성 코드 감염도 막지 못한다.
그럼에도 불구하고, 나와 서버 사이에 오가는 데이터 도청은 최소한으로라도 막아준다는 것만으로도 당연히 적용해서 웹 서비스를 제공하는 것이 옳다고 할 수 있지 않을까.
