인증서 실무
TLS와 인증서의 원리를 이해했으니, 이제 실무에서 인증서를 어떻게 발급하고 관리하는지 살펴보겠습니다.
Let's Encrypt와 자동 갱신
Let's Encrypt는 무료로 TLS 인증서를 발급하는 비영리 CA입니다. 2015년 출시 이후, 전 세계 HTTPS 보급률을 극적으로 높인 프로젝트입니다.
핵심은 무료라는 점보다 ACME(Automatic Certificate Management Environment) 프로토콜을 통해 도메인 검증, 발급, 갱신, 폐기를 자동화한다는 점입니다. 짧은 유효 기간은 수동 관리에는 부담이지만, 자동 갱신과 ACME Renewal Information(ARI)을 전제로 하면 키 유출이나 잘못된 발급의 영향 기간을 줄이는 데 도움이 됩니다.
| 특징 | 설명 |
|---|---|
| 무료 | 비용 부담 없이 누구나 HTTPS 적용 |
| 자동화 | ACME 프로토콜로 발급/갱신 자동화 |
| 현재 기본 유효 기간 90일 | 짧은 수명으로 노출 기간 축소, 더 짧아질 예정 |
| DV 인증서만 | 도메인 소유 확인만 (기업 신원 확인 없음) |
| 와일드카드 | DNS-01로 *.example.com 발급 가능 |
# Certbot으로 Let's Encrypt 인증서 발급 (Nginx)
sudo certbot --nginx -d example.com -d www.example.com
# 인증서 갱신 테스트 (실제 갱신하지 않음)
sudo certbot renew --dry-run
# 자동 갱신 예약 확인 (배포판에 따라 systemd timer가 이미 활성화됨)
systemctl list-timers | grep certbot
# cron을 직접 쓴다면 매일 확인하고, 갱신이 필요할 때만 renew되게 둠
echo "17 3 * * * certbot renew --quiet --deploy-hook 'systemctl reload nginx'" | sudo crontab -
# 발급된 인증서 확인
sudo certbot certificates
# Certificate Name: example.com
# Domains: example.com www.example.com
# Expiry Date: 2024-04-15 (VALID: 89 days)
# DNS-01 Challenge로 와일드카드 인증서 발급
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.example.com" -d "example.com"대부분의 클라우드 서비스(AWS ACM, Cloudflare, Vercel)는 인증서를 자동으로 발급하고 갱신해 주므로, 개발자가 직접 Certbot을 실행할 일은 점점 줄어들고 있습니다.
다만 “자동”이라고 해서 무조건 방치해도 된다는 뜻은 아닙니다. DNS 검증 레코드, 로드 밸런서 연결, 만료 알림, 배포 후 reload 동작, 인증서 체인 변경을 모니터링해야 합니다.
자체 서명 인증서
개발 환경에서 HTTPS를 테스트하려면 인증서가 필요한데, 매번 Let's Encrypt를 사용하기는 번거롭습니다. 이때 자체 서명 인증서(Self-Signed Certificate)를 만들어 사용합니다.
CA 서명 인증서
Root CA → 중간 CA → 서버 인증서
↑ CA가 서명
→ 브라우저가 Root CA를 신뢰 → 체인 검증 성공 → 자물쇠 ✓
자체 서명 인증서
서버 인증서
↑ 자기 자신이 서명
→ 브라우저 신뢰 저장소에 없음 → 검증 실패 → 경고! ✗# OpenSSL로 자체 서명 인증서 생성 (SAN 포함)
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout server.key -out server.crt -days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# 생성된 인증서 내용 확인
openssl x509 -in server.crt -noout -text | head -20
# mkcert 사용 (로컬 CA 설치로 경고 없이 개발)
# 1. 로컬 CA 설치 (최초 1회)
mkcert -install
# 2. localhost용 인증서 생성
mkcert localhost 127.0.0.1 ::1
# → localhost+2.pem (인증서)
# → localhost+2-key.pem (개인키)
# 3. Node.js에서 사용
# const https = require('https');
# const options = {
# cert: fs.readFileSync('localhost+2.pem'),
# key: fs.readFileSync('localhost+2-key.pem')
# };자체 서명 서버 인증서를 공개 서비스에 그대로 쓰면 브라우저와 클라이언트가 신뢰할 수 없어 경고가 발생합니다. 프로덕션에서는 공개 Web PKI 인증서나 조직 내부에서 관리하는 사설 CA를 클라이언트 신뢰 저장소에 배포하는 방식이 필요합니다.
SNI
SNI(Server Name Indication)는 TLS 핸드셰이크에서 클라이언트가 접속하려는 호스트명을 서버에 알려주는 확장입니다.
SNI의 가장 큰 이슈는, 클라이언트가 접속하려는 호스트명이 일반적으로 평문 ClientHello 안에 들어간다는 것입니다. 인증서 선택을 위해 서버가 TLS 핸드셰이크 초기에 이름을 알아야 하기 때문입니다.
프라이버시 수준
SNI (평문) ▓░░░░░░░░░░ 낮음 도메인 노출
ESNI (과도기) ▓▓▓▓▓▓░░░░░ 중간 ECH 이전 실험적 접근
ECH (표준화) ▓▓▓▓▓▓▓▓▓▓ 높음 ClientHelloInner 암호화
(Inner/Outer 구조)ECH(Encrypted Client Hello)는 민감한 ClientHelloInner를 암호화하여, 관찰자가 SNI와 일부 협상 정보를 바로 보지 못하게 하는 TLS 확장입니다. 클라이언트는 보통 DNS HTTPS/SVCB 레코드에 담긴 ECHConfig를 통해 서버의 공개 설정을 얻습니다. 다만 DNS 질의 자체가 평문이면 그 단계에서 도메인이 노출될 수 있으므로, 실제 프라이버시는 암호화된 DNS와 배포 환경까지 함께 봐야 합니다.
mTLS (상호 인증)
일반적인 웹 TLS에서는 주로 서버만 인증서를 제시합니다. mTLS(Mutual TLS)는 서버뿐 아니라 클라이언트도 인증서를 제시해 양쪽 신원을 TLS 계층에서 검증하는 방식입니다.
mTLS는 “접속 주체가 누구인지”를 강하게 확인하는 데 유용하지만, 그 주체가 어떤 작업을 할 수 있는지는 별도의 인가 정책으로 판단해야 합니다. 인증서 발급, 폐기, 회전, 키 보호, 서비스 ID 매핑까지 운영 체계가 함께 필요합니다.
| 사용 시나리오 | 설명 | 예시 |
|---|---|---|
| 마이크로서비스 | 서비스 간 상호 인증 | Istio, Linkerd 서비스 메시 |
| 금융 API | 핀테크 서비스 신원 증명 | Open Banking API |
| IoT | 기기 인증 | 스마트홈, 의료 기기 |
| Zero Trust | 네트워크 접근 제어 | BeyondCorp, Cloudflare Access |
| 내부 시스템 | 관리 도구 접근 제한 | DB 관리 콘솔 |
# 1. CA 개인키와 인증서 생성
openssl req -x509 -newkey rsa:4096 -nodes \
-keyout ca.key -out ca.crt -days 3650 \
-subj "/CN=My Internal CA"
# 2. 클라이언트 개인키와 CSR 생성
openssl req -newkey rsa:2048 -nodes \
-keyout client.key -out client.csr \
-subj "/CN=service-a"
# 3. CA로 클라이언트 인증서 서명
openssl x509 -req -in client.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 365
# 4. mTLS로 서버 접속 테스트
curl --cert client.crt --key client.key \
--cacert ca.crt https://internal-api.company.com/health도구 대상 특징
───────────────────────────────────────────────
cert-manager Kubernetes 자동 발급/갱신, Let's Encrypt 연동
Vault PKI 전체 인프라 HashiCorp, 동적 인증서 발급
SPIFFE/SPIRE 마이크로서비스 서비스 ID 기반, mTLS 자동화
AWS ACM AWS 서비스 무료, ALB/CloudFront 자동 적용다음 절에서는 네트워크에서 발생하는 보안 위협과 방어 전략을 살펴보겠습니다.