Let's Encrypt OCSP 종료 후 남은 설정 점검하기
이 글의 순서 10개 절
Let’s Encrypt의 OCSP는 이미 끝났다. 인증서에서 OCSP URL이 빠진 게 2025-05-07,
응답기가 꺼진 게 2025-08-06이다. 옛 OCSP 호스트 r11.o.lencr.org는 지금
DNS에서 NXDOMAIN으로 나온다.
Let’s Encrypt는 웹사이트와 방문자에게는 영향이 없다고 안내했고, 실제로 큰 혼란 없이 지나갔다. 문제는 그 뒤에 남은 설정이다. 1년 넘게 아무도 열어 보지 않은 renewal 설정, 스테이플링 지시어, OCSP에 기대는 헬스체크가 아직 서버에 남아 있다. 그래서 OCSP 종료는 서비스 장애보다 감시와 자동화의 오작동으로 드러난다. 갱신이 조용히 멈추거나, 검사가 멀쩡한 서버를 실패로 보고한다.
끝난 것과 남은 것
| 항목 | 지금 상태 | 운영자가 할 일 |
|---|---|---|
| OCSP 응답기 | 2025-08-06 종료 | 없음 |
| 인증서의 OCSP URL | 2025-05-07 이후 발급분에는 없음 | OCSP 주소를 하드코딩한 설정·스크립트 제거 |
| OCSP Must-Staple | 2025-05-07부터 요청이 모두 거부됨 | ACME 클라이언트 설정에서 제거 |
| 폐기 정보 | CRL로만 게시 (*.c.lencr.org, HTTP 80) |
아웃바운드 방화벽이 CRL 다운로드를 막지 않는지 확인 |
| 서버의 OCSP 스테이플링 | 스테이플할 응답이 없음 | nginx·Apache 설정 정리 (급하진 않음) |
| OCSP 기반 모니터링 | 오탐 발생 | curl --cert-status 같은 검사 제거 |
급한 건 Must-Staple과 모니터링이다. 스테이플링 설정은 그대로 둬도 서비스는 돈다.
Must-Staple 설정
가장 먼저 본다. Certbot은 이 설정이 남아 있으면 갱신에 실패한다. acme.sh는 3.1.2(2025-11-29)
이상이면 Let’s Encrypt 프로덕션 API로 갱신할 때 Le_OCSP_Staple을 자동으로 지운다. 3.1.1 이하에
머문 설치본이나, --issue에 --ocsp/--ocsp-must-staple을 넘기는 스크립트는 여전히 실패한다.
Must-Staple은 RFC 7633의 TLS Feature 확장(OID 1.3.6.1.5.5.7.1.24)에 status_request를 넣은
것이다. OpenSSL 설정 파일에서는 tlsfeature = status_request로 쓴다. ACME 클라이언트가 이 확장을
넣어 요청하면 Let’s Encrypt는 거부한다.
ACME 클라이언트는 발급 때 준 옵션을 설정 파일에 저장해 두고 갱신 때 그대로 다시 쓴다.
| 클라이언트 | 발급 옵션 | 남는 설정 |
|---|---|---|
| Certbot | --must-staple |
/etc/letsencrypt/renewal/*.conf의 must_staple = True, 전역 cli.ini의 must-staple = true |
| acme.sh | --ocsp-must-staple (--ocsp) |
도메인 설정의 Le_OCSP_Staple='1' (3.1.2 이상은 LE 갱신 때 자동 삭제) |
Certbot은 renewal 설정 말고도 /etc/letsencrypt/cli.ini, ~/.config/letsencrypt/cli.ini를
매번 읽는다. cli.ini에서는 옵션을 대시로(must-staple) 적으니 밑줄 패턴만 찾으면 놓친다.
grep -rnE 'must[-_]staple' /etc/letsencrypt/ ~/.config/letsencrypt/ 2>/dev/null
acme.sh --version
grep -rn 'Le_OCSP_Staple' ~/.acme.sh/ # --config-home 을 바꿨다면 그 경로 (도커 이미지는 /acme.sh)
찾으면 그 줄을 지우고(cli.ini의 must-staple 줄 포함), 이후 발급과 갱신에서 --must-staple을
빼고 실행한다. Certbot은 지운 뒤 certbot renew --dry-run으로 갱신이 통과하는지 확인한다.
Certbot에는 --staple-ocsp라는 옵션도 있다. 이름은 비슷하지만 Must-Staple과는 다른 옵션으로,
웹서버의 스테이플링 설정을 켠다. 이쪽은 급하지 않다.
갱신 실패가 이 원인이 아니라면 Let’s Encrypt 자동갱신이 실패하는 흔한 이유에서 나머지 패턴을 확인한다.
폐기 통지는 ARI로 넘어갔다
OCSP가 없어지면서 “내 인증서가 폐기됐으니 빨리 바꾸라”는 신호도 다른 길로 오게 됐다. Certbot
4.1.0(2025-06-10)부터 ARI(ACME Renewal Info)를 지원한다. ARI가 더 이른 갱신 시점을 알려 주면
renew_before_expiry 설정보다 그 값을 우선한다. Certbot 변경 기록에는 이 동작이 폐기 통지
때문이며 OCSP 폐지를 염두에 뒀다고 적혀 있다. 5.0.0(2025-09-02)부터는 ARI가 준 Retry-After 값도
저장한다.
certbot --version
4.1.0보다 낮으면 올리는 쪽을 검토한다.
OCSP에 기대던 모니터링과 클라이언트
실제 장애는 여기서 난다.
curl –cert-status
--cert-status는 서버가 스테이플한 OCSP 응답을 검증하는 옵션이다. 응답이 아예 없어도 검증 실패로
처리한다. OpenSSL과 GnuTLS 백엔드에서만 지원한다.
curl -sS --cert-status -o /dev/null https://example.com/
2026-09-24에 letsencrypt.org에 실행하면 이렇게 끝난다.
curl: (91) No OCSP response received
Let’s Encrypt 인증서를 쓰는 사이트는 정상인데도 매번 실패한다. 헬스체크 스크립트, 모니터링 도구의 커스텀 체크, CI의 배포 후 검증에서 이 옵션을 찾아 뺀다.
OCSP를 직접 조회하던 스크립트
openssl ocsp로 응답기에 직접 묻던 스크립트나, OCSP URL을 설정에 고정해 둔 도구도 있다. 옛
호스트는 이제 이름 해석이 안 된다.
dig r11.o.lencr.org +noall +comments | grep -o 'status: [A-Z]*'
status: NXDOMAIN이 나온다. dig +short는 NXDOMAIN과 조회 실패를 똑같이 빈 출력으로 보여 주므로
상태는 이렇게 본다. 스크립트에서 o.lencr.org를 검색하면 남은 자리를 찾을 수 있다. 폐기 여부를
계속 확인해야 한다면 CRL로 바꾼다.
# 인증서의 CRLDP 에서 CRL 샤드를 받아 발급자와 갱신 시각 확인
curl -s -o crl.der "$(openssl x509 -in cert.pem -noout -ext crlDistributionPoints | grep -o 'http://[^ ]*')" \
&& openssl crl -inform DER -in crl.der -noout -issuer -lastupdate -nextupdate -crlnumber
# CRL 로 leaf 인증서의 폐기 여부 검증
openssl verify -crl_check -crl_download -untrusted chain.pem leaf.pem
-crl_download는 CRLDP를 따라가 CRL을 자동으로 받는다. 받아 둔 파일을 쓰려면 PEM으로 바꿔
-CRLfile에 준다. OpenSSL 3.x는 crl.der를 바로 줘도 된다.
openssl crl -inform DER -in crl.der -out crl.pem
openssl verify -crl_check -CRLfile crl.pem -untrusted chain.pem leaf.pem
-ext 옵션은 OpenSSL 1.1.1 이상에서 쓸 수 있다. macOS 기본 openssl(LibreSSL)은 -ext와
-crl_download를 지원하지 않으니 Homebrew openssl@3 등을 쓴다.
Java
JSSE는 기본적으로 폐기를 확인하지 않는다. 기본값은 이렇다.
| 속성 | 종류 | 기본값 | 의미 |
|---|---|---|---|
com.sun.net.ssl.checkRevocation |
System property (-D) |
false |
JSSE의 폐기 확인 |
ocsp.enable |
Security property | false |
OCSP 사용 |
com.sun.security.enableCRLDP |
System property (-D) |
false |
인증서의 CRLDP를 따라가 CRL 확인 (호환성 때문에 꺼져 있음) |
ocsp.enable은 -D로는 먹지 않는다. $JAVA_HOME/conf/security/java.security에 쓰거나,
-Djava.security.properties=<파일>로 덮어쓰거나, 코드에서 Security.setProperty()로 설정한다.
폐기 확인을 켜지 않았다면 영향이 없다. 켰다면 설정을 다시 봐야 한다. 폐기 확인과
ocsp.enable을 모두 켜면 OCSP를 먼저 쓰고 CRL로 넘어간다(failover). OCSP URL이 없는
Let’s Encrypt 인증서는 결국 CRL로 확인하게 되므로 CRLDP를 따라가게 해야 한다.
java -Dcom.sun.net.ssl.checkRevocation=true -Dcom.sun.security.enableCRLDP=true -jar app.jar
코드에서 PKIXRevocationChecker를 쓴다면 PREFER_CRLS(CRL 우선), SOFT_FAIL(확인 불가 시 통과)
같은 옵션이 있다. 폐기 확인을 켜고 ocsp.enable=true(java.security)만 설정한 앱이라면, OCSP 실패
뒤 CRL failover가 실제로 일어나는지 스테이징에서 Let’s Encrypt 인증서로 재현해 본다.
VPN 같은 비브라우저 소프트웨어
Let’s Encrypt는 공지에서 일부 비브라우저 소프트웨어는 영향을 받을 수 있다고 했다. VPN처럼 브라우저가 아닌 통신에 Let’s Encrypt 인증서를 쓴다면, 인증서에 OCSP URL이 없어도 정상 동작하는지 확인하라는 안내다. 폐기 확인 방식을 설정할 수 있는 제품이면 OCSP 전용으로 묶여 있지 않은지 본다.
아웃바운드 방화벽
Let’s Encrypt 안내에 따르면 인증서에 CRL URL이 들어가면서 일부 TLS 클라이언트가 Let’s Encrypt에서 CRL을 받아 갈 수 있게 됐고, 아웃바운드 방화벽이 엄격한 환경은 영향을 받을 수 있다.
서버에서 외부로 나가는 HTTP를 막아 둔 환경이라면, 폐기 확인을 하는 클라이언트가 있는 구간에서
*.c.lencr.org로 나가는 HTTP(80) 요청이 허용되는지 확인한다. 실제 CRL 호스트는 ye2.c.lencr.org
같은 하위 도메인이라 FQDN c.lencr.org만 허용하면 막힌다. 하위 도메인 와일드카드로 허용하고,
CDN이 섞여 있으니 IP 허용 목록은 피한다. 체인 보완(AIA fetch)을 하는 클라이언트가 있으면
*.i.lencr.org도 허용한다. 위의 CRL 다운로드 명령이 그대로 테스트가 된다.
웹서버 스테이플링 설정
급하지 않다. Let’s Encrypt 직원은 커뮤니티 답변에서 웹서버 설정을 미리 바꿀 필요는 없다고 했다.
인증서에서 OCSP URL이 빠지면 스테이플링은 그냥 동작하지 않는다. nginx는 WARN, Apache는 error 레벨
로그를 남기지만 둘 다 기동은 계속된다. 따로 봐야 할 것은 옛 OCSP 주소를 고정한
SSLStaplingForceURL이다(아래 Apache 절).
그래도 치우는 게 낫다. 로그에 매번 같은 경고가 쌓이고, 다음 사람이 스테이플링이 켜져 있다고 잘못 판단한다.
nginx
ssl_stapling on인데 인증서에 OCSP URL이 없으면 nginx는 WARN 로그를 남기고 그 인증서의
스테이플링을 건너뛴다.
"ssl_stapling" ignored, no OCSP responder URL in the certificate "..."
ssl_stapling_responder에 옛 OCSP 주소를 적어 두었다면 설정을 읽을 때 이름 해석에 실패해
"ssl_stapling" ignored, host not found in OCSP responder ... 경고를 남기고 스테이플링을
건너뛴다. 기동은 되지만 설정만 남아 헷갈리게 한다.
# 남아 있는 스테이플링 관련 지시어
nginx -T 2>/dev/null | grep -nE 'ssl_stapling|ssl_stapling_responder|ssl_stapling_file|ssl_trusted_certificate|resolver'
# 경고가 실제로 찍히는지 (no OCSP responder URL, host not found 모두)
grep -F '"ssl_stapling" ignored' /var/log/nginx/error.log
| 지시어 | 역할 | Let’s Encrypt 인증서만 쓰는 server 블록에서 |
|---|---|---|
ssl_stapling |
스테이플링 사용 (기본 off) | 끄거나 줄 삭제 |
ssl_stapling_verify |
응답 검증 (기본 off) | 같이 삭제 |
ssl_stapling_responder |
AIA의 OCSP URL을 덮어씀 (http만 지원) | 옛 LE OCSP 주소가 들어 있으면 삭제 |
ssl_stapling_file |
미리 받아 둔 DER 응답 파일 사용 | 삭제. 파일을 갱신하던 cron도 같이 정리 |
ssl_trusted_certificate |
스테이플 응답 검증용 체인 | 다른 용도가 없으면 삭제 |
resolver |
OCSP 호스트 이름 해석 | 다른 용도로 쓸 수 있으니 확인 후 판단 |
한 서버에서 다른 CA 인증서를 같이 서빙한다면 그 인증서에 OCSP URL이 있는지 먼저 본다.
openssl x509 -in other-cert.pem -noout -ocsp_uri
출력이 있으면 그 인증서에는 스테이플링이 여전히 의미가 있다. 스테이플링 설정은 server 블록 단위로 손본다.
수정한 뒤에는 nginx -t로 문법을 확인하고 리로드한다. 리로드 절차는
Nginx 인증서 교체와 무중단 리로드에, nginx TLS 설정
전반은 Nginx 가이드에 있다.
Apache
mod_ssl은 OCSP URI가 없고 SSLStaplingForceURL도 없는 인증서에 대해 [ssl:error] 레벨로 이런
로그를 남긴다. 기동은 계속된다.
AH02218: ssl_stapling_init_cert: no OCSP URI in certificate and no SSLStaplingForceURL set
여러 vhost가 한 인증서를 공유하면 두 번째 vhost부터는 AH02814로 나오고, 호출부에서
Unable to configure certificate ... for stapling(AH02604 또는 AH02567)도 error로 같이 남긴다.
error 레벨에 알림을 걸어 두었다면 재시작할 때마다 알림이 온다.
grep -rnE 'SSL(Use)?Stapling' /etc/apache2 /etc/httpd 2>/dev/null
grep -rnE 'AH0(2218|2814|2604|2567)' /var/log/apache2 /var/log/httpd 2>/dev/null
| 지시어 | 역할 | 조치 |
|---|---|---|
SSLUseStapling |
스테이플링 사용 (기본 off) | Let’s Encrypt 인증서만 쓰면 off |
SSLStaplingCache |
응답 캐시 (서버 전역) | 모든 vhost에서 SSLUseStapling을 끈 뒤에만 삭제. 하나라도 On이 남으면 AH01958로 기동이 실패하고, apachectl configtest로는 잡히지 않는다 |
SSLStaplingForceURL |
OCSP 응답자 URI 강제 | 옛 LE OCSP 주소가 있으면 삭제 (아래 경고) |
그 밖의 SSLStapling* |
타임아웃·오류 처리 등 | 스테이플링을 모두 끄면 같이 정리 |
끄는 순서는 이렇다.
- 모든 vhost에서
SSLUseStapling을 off로 바꾼다 grep -rn 'SSLUseStapling' /etc/apache2 /etc/httpd결과가 모두 off인지 확인한다SSLStaplingCache와 나머지SSLStapling*지시어를 지운다- 재시작 후 error_log를 확인한다
점검 명령 모음
# 1. 인증서에 OCSP URL 이 있는가 (LE 는 비어 있어야 정상)
openssl x509 -in cert.pem -noout -ocsp_uri
# 2. AIA·CRLDP·Must-Staple 확장 한 번에 (OpenSSL 1.1.1+, LibreSSL 불가)
openssl x509 -in cert.pem -noout -ext authorityInfoAccess,crlDistributionPoints,tlsfeature
# 3. 서버가 OCSP 응답을 스테이플하는가 (LE 는 no response 가 정상, LibreSSL 은 빈 출력)
echo | openssl s_client -connect example.com:443 -servername example.com -status 2>/dev/null | grep -i -A3 'OCSP'
# 4. ACME 클라이언트에 Must-Staple 이 남았는가 (acme.sh 는 3.1.2+ 권장)
grep -rnE 'must[-_]staple' /etc/letsencrypt/ ~/.config/letsencrypt/ 2>/dev/null
acme.sh --version
grep -rn 'Le_OCSP_Staple' ~/.acme.sh/
# 5. 웹서버 스테이플링 설정
nginx -T 2>/dev/null | grep -nE 'ssl_stapling|ssl_stapling_responder|ssl_stapling_file|ssl_trusted_certificate|resolver'
grep -rnE 'SSL(Use)?Stapling' /etc/apache2 /etc/httpd 2>/dev/null
# 6. CRL 을 받을 수 있는가 (방화벽 확인 겸)
curl -s -o crl.der "$(openssl x509 -in cert.pem -noout -ext crlDistributionPoints | grep -o 'http://[^ ]*')" \
&& openssl crl -inform DER -in crl.der -noout -issuer -lastupdate -nextupdate -crlnumber
# 7. 옛 OCSP 호스트 (status: NXDOMAIN 이 정상)
dig r11.o.lencr.org +noall +comments | grep -o 'status: [A-Z]*'
지금 Let’s Encrypt 인증서에 들어 있는 것
2026-09-24에 letsencrypt.org의 인증서(발급자 CN=YE2)를 직접 확인했다.
openssl x509 -in cert.pem -noout -ext authorityInfoAccess,crlDistributionPoints
Authority Information Access:
CA Issuers - URI:http://ye2.i.lencr.org/
X509v3 CRL Distribution Points:
Full Name:
URI:http://ye2.c.lencr.org/96.crl
AIA에는 CA Issuers만 있고 OCSP 항목이 없다. openssl x509 -noout -ocsp_uri는 아무것도 출력하지
않는다. openssl s_client -status는 스테이플된 응답이 없다고 나온다. 문구는 no response(s) sent
비슷한데 OpenSSL 버전마다 조금 다르다. LibreSSL은 응답이 없으면 OCSP 관련 줄을 아예 출력하지
않으니 빈 출력도 스테이플 없음이다.
CRLDP가 가리키는 샤드를 받아 보면 이렇다. 2026-09-24 14:23 UTC 재발급 전에 받은 값이다. 샤드는 재발급될 때마다 크기, 항목 수, 날짜가 바뀌니 볼 것은 lastUpdate~nextUpdate 간격(약 9일)이다.
| 항목 | 값 |
|---|---|
| 크기 (DER) | 60,588 바이트 |
| 폐기 항목 수 | 1,552 개 |
| lastUpdate | 2026-09-23 |
| nextUpdate | 2026-10-02 |
lencr.org 아래 호스트는 두 종류다.
*.c.lencr.org: CRL. Let’s Encrypt가 발급했다가 폐기한, 아직 만료되지 않은 인증서 목록*.i.lencr.org: 중간(issuer) 인증서 사본
BR은 CRL 게시 주기도 정해 뒀다. 인증서에 OCSP 포인터가 없으면 최소 4일마다 CRL을 새로 게시해야 하고, 인증서를 폐기로 기록하면 24시간 안에 새 CRL을 내야 한다.
프로필별 차이
Let’s Encrypt 프로필 문서에는 “Let’s Encrypt does not support OCSP”라고 적혀 있다.
| 프로필 | 유효기간 | 폐기 정보 |
|---|---|---|
classic |
90일 | CRL |
tlsserver |
45일 | CRL |
shortlived |
160시간 | CRL |
shortlived는 BR의 단기 인증서에 해당한다. 2026-03-15 이후 발급분 기준으로 유효기간 7일 이하인
인증서다. BR은 단기 인증서에 CRLDP를 요구하지 않는다. 지금은 Let’s Encrypt가 여기에도 CRL URL을
넣고 있지만, 문서에는 이게 바뀔 수 있다고 적혀 있다.
브라우저는 폐기를 어떻게 확인하나
OCSP가 없어졌다고 폐기 확인이 사라진 건 아니다. 주요 브라우저는 이미 온라인 조회 대신 미리 받아 둔 폐기 목록을 로컬에서 확인하는 쪽으로 옮겨 갔다.
| 브라우저 | 주 수단 | 온라인 OCSP 조회 |
|---|---|---|
| Chrome | CRLSets (+ 스테이플된 OCSP 응답 존중) | 기본값으로 하지 않음 |
| Firefox 데스크톱 | CRLite (137부터) | DV 인증서는 하지 않음 (142 발표), EV는 함 |
Chrome
Chrome의 주 폐기 확인 수단은 CRLSets다. 기본값으로 스테이플된 OCSP 응답도 존중한다. 2024년부터는 CCADB에 공개된 CRL의 보안상 중요한 폐기 대부분을 CRLSets로 강제하고, 대부분의 폐기는 며칠 안에 사용자에게 도달한다.
기본값으로는 CRL이나 OCSP URL로 온라인 조회를 하지 않는다. EV 인증서 온라인 확인도 2022년 프라이버시 문제로 껐다. 엔터프라이즈 정책으로 바꿀 수는 있다.
EnableOnlineRevocationChecks: soft-fail OCSP 조회RequireOnlineRevocationChecksForLocalAnchors: 로컬 신뢰 앵커(사내 CA 등)에 hard-fail
두 정책 모두 문서에 향후 제거될 수 있다고 적혀 있다.
Firefox
Firefox는 137부터 모든 데스크톱(Windows, Linux, macOS)에서 CRLite를 켰다. CT 로그에 올라간 인증서 중 폐기된 것 전체를 압축한 데이터를 12시간마다 갱신해 로컬에서 조회한다. 다운로드는 평균 하루 약 300KB다(45일마다 4MB 스냅샷, 그 사이는 델타).
Mozilla는 Mozilla Hacks 글로 Firefox 142의 DV 인증서 OCSP 조회 중단을 발표했다. 142 릴리스 노트에는 이 내용이 없다. 같은 글에서 OCSP 조회가 중앙값 기준으로 TLS 핸드셰이크를 100ms 동안 막는다고 밝혔다. 동작 자체는 소스 기본값으로 확인할 수 있다.
security.pki.crlite_mode기본값2: CRLite 결과를 강제한다- 이 모드에서 Mozilla 루트에 체인되는 DV 인증서는 OCSP를 조회하지 않는다
(
security.OCSP.require=true면 예외) - EV 인증서는 계속 OCSP를 조회한다
- Android의 CRLite 채널 기본값은
compat로, 우선순위 폐기만 담는다
브라우저마다 검증 경로가 다른 문제는 체인 오류에서도 똑같이 나타난다. 크롬은 되는데 파이어폭스만 인증서 오류에 따로 적었다.
단기 인증서
CRLSets도 CRLite도 폐기가 퍼지기까지 시간이 걸린다. 폐기 전파를 빠르게 하는 대신 인증서 수명
자체를 줄이는 방법도 있다. Let’s Encrypt shortlived 프로필은 160시간짜리 인증서를 발급하고,
BR은 이런 단기 인증서에 폐기 정보를 요구하지 않는다.
대가는 갱신 여유다. 160시간은 7일이 안 된다. 갱신 자동화가 며칠만 멈춰도 만료된다. 갱신 감시가 갖춰져 있지 않다면 그쪽부터 만든다.
종료까지의 일정
| 날짜 | 일 |
|---|---|
| 2023-07-13 | CA/B Forum SC063 투표 종료. OCSP는 선택, CRL은 필수로 |
| 2023-08-17 / 2024-03-15 | SC063이 Baseline Requirements에 채택 / 발효 (BR 2.0.1) |
| 2024-07-23 | Let’s Encrypt, OCSP 종료 의향 공지 |
| 2024-12-05 | 구체적 종료 일정 공지 |
| 2025-01-30 | Must-Staple 요청 거부 시작 (예외 계정 있음) |
| 2025-03-12 | 인증서에 CRL URL(CRLDP) 추가. 이때는 OCSP URL도 같이 들어감 |
| 2025-05-07 | 인증서에서 OCSP URL 제거. Must-Staple 요청은 예외 없이 거부 |
| 2025-08-06 | OCSP 응답기 종료 |
2025-01-30의 예외는 2024-10-18 이후 Must-Staple 인증서를 요청한 적이 있는 계정이다. 이 계정들은 2025-05-07까지 유예를 받았고, 나머지 계정의 요청은 바로 거부됐다.
응답기를 끈 2025-08-06에는 OCSP URL이 든 Let’s Encrypt 인증서가 이미 하나도 남아 있지 않았다. URL을 뺀 지 90일이 넘어서 그런 인증서는 모두 만료된 상태였다. 응답기를 꺼도 깨질 인증서가 없도록 순서를 짠 것이다.
SC063 투표는 한쪽으로 기울었다. 인증서 발급자 28곳이 찬성하고 1곳이 반대했으며, 인증서 소비자(Google, Mozilla, Apple)는 모두 찬성했다.
왜 끝냈나
프라이버시
OCSP로 폐기 여부를 물으면 응답기를 운영하는 CA는 어느 IP가 어느 사이트에 접속하는지 바로 알게 된다. Let’s Encrypt는 이 정보를 남기지 않았지만, CA가 일부러 남기지 않아도 법적으로 수집을 강제당할 수 있다.
운영 비용
OCSP는 자원을 많이 썼다. 2025-08-06 종료 공지에 따르면 2025년 트래픽이 가장 많았을 때는 월 약 3,400억 건을 처리했다. CDN에서 초당 14만 건 이상, 오리진에서 초당 1만 5천 건이다.
Let’s Encrypt는 2022년 9월부터 CRL을 운영했다. Apple과 Mozilla 루트 프로그램이 2022-10-01 전까지 CRL 발급과 CCADB 공개를 요구했기 때문이다. 걸림돌은 크기였다. 당시 활성 인증서가 2억 개를 넘어서 전부 폐기하면 CRL 하나가 8GB를 넘는다. 그래서 CRL을 여러 조각(샤드)으로 나눠 게시한다.
규정과 Must-Staple
SC063 이후 공개 CA에게 OCSP는 선택 사항이 됐다. 2024-07 공지 당시 OCSP를 여전히 요구하던 루트
프로그램은 Microsoft 하나였다. 현재 Microsoft Trusted Root Program 요건(GitHub Requirements.md
3.1.10·3.2.3)은 end-entity 인증서에 OCSP URL과 CRL 배포 지점(CDP) 중 하나 이상만 있으면 된다고
적고 있다. OCSP URL이 없으면 CRL 파일을 10MB 미만으로 유지하라고 권고한다.
Must-Staple을 없앤 이유도 공지에 나와 있다.
- 여러 해가 지나도 브라우저 지원이 넓어지지 않았다
- 주요 웹서버의 OCSP 스테이플링 구현이 여전히 다운타임 위험을 안고 있었다
- CRL은 웹서버 설정을 따로 하지 않아도 모든 사이트에 프라이버시 이점을 준다
이런 CA 쪽 정책 변화는 CA 업계 동향에 계속 올린다. 지금 서비스 중인 인증서의 만료일과 체인 상태는 진단 툴에 도메인을 넣으면 바로 볼 수 있다. 갱신이 조용히 멈추는 걸 미리 알고 싶으면 도메인 5개까지는 무료 만료 감시 구독으로 걸어 둘 수 있다.
참조
- Let’s Encrypt: Ending OCSP Support in 2025 (2024-12-05)
- Let’s Encrypt: Intent to End OCSP Service (2024-07-23)
- Let’s Encrypt: OCSP Service Has Reached End of Life (2025-08-06)
- Let’s Encrypt: 2025 연말 서한
- Let’s Encrypt: A New Life for Certificate Revocation Lists (2022-09-07)
- Let’s Encrypt: Profiles
- Let’s Encrypt: lencr.org
- Let’s Encrypt Community: Support for OCSP Must-Staple now disabled
- Let’s Encrypt Community: Adding CRL URLs to certificates
- Let’s Encrypt Community: Removing OCSP URLs from certificates
- Let’s Encrypt Community: Ending OCSP support in 2025: webserver configuration
- CA/B Forum: Baseline Requirements (TLS Server Certificates)
- CA/B Forum: Ballot SC063v4: Make OCSP optional, require CRLs, and incentivize automation
- Microsoft Trusted Root Program: Program Requirements (GitHub)
- Chromium: Security FAQ
- Mozilla Hacks: CRLite: Fast, private, and comprehensive certificate revocation checking in Firefox
- Firefox 소스: StaticPrefList.yaml
- RFC 7633: X.509v3 TLS Feature Extension
- nginx: ngx_http_ssl_module
- nginx 소스: ngx_event_openssl_stapling.c
- nginx: Command-line parameters
- Apache HTTP Server: mod_ssl
- Apache httpd 소스: ssl_util_stapling.c
- Apache httpd 소스: ssl_engine_init.c
- Certbot 소스: CLI 옵션 정의
- Certbot 소스: 설정 파일 경로(constants.py)
- Certbot: CHANGELOG
- acme.sh 소스
- curl: man page
- Oracle: Java PKI Programmer’s Guide (JDK 21)
- Oracle: JSSE Reference Guide (JDK 21)
- OpenSSL: openssl-x509
- OpenSSL 1.1.1: x509
- OpenSSL: openssl-s_client
- OpenSSL: openssl-crl
- OpenSSL: openssl-verify
- OpenSSL: x509v3_config