Apache와 IIS 인증서 교체 절차
Nginx 교체 절차는 앞 글에 적었다. Apache도 설정이 파일 경로를 가리키는 방식이라 거의 같고, 다른 점만 알면 된다. IIS는 구조가 아예 다르다. 인증서가 파일이 아니라 Windows 인증서 저장소에 들어 있다.
| Apache / Nginx | IIS | |
|---|---|---|
| 인증서 위치 | 파일 경로 (설정이 가리킴) | Windows 인증서 저장소 |
| 개인키 | 별도 파일 | 인증서와 함께 저장소에 |
| 교체 단위 | 파일 덮어쓰기 + 리로드 | 저장소 임포트 + 바인딩 변경 |
| 흔한 사고 | 파일 바꾸고 리로드 누락 | 저장소에 넣고 바인딩 안 바꿈 |
사고의 모양은 결국 같다. 새 인증서를 준비해 놓고 옛 인증서를 계속 내보낸다.
Apache
기록, 검증, 원자적 교체, 설정 검증, 리로드, 서빙 지문 대조로 이어지는 순서는 Nginx와 같다. 명령만 다르다.
apachectl configtest # nginx -t 에 해당
apachectl graceful # 무중단 리로드 (nginx -s reload 에 해당)
# systemd 환경이면
systemctl reload apache2 # Debian 계열
systemctl reload httpd # RHEL 계열
graceful은 처리 중인 요청을 마치고 워커를 교체한다. restart는 끊는다. 인증서를 바꾸는 데 restart를
쓸 이유는 Apache에서도 없다.
체인 지정
Apache에서 가장 큰 함정은 체인을 지정하는 방식이 버전마다 다르다는 점이다.
# 2.4.8 이상 — fullchain 을 한 파일로
SSLCertificateFile /etc/ssl/certs/fullchain.pem
SSLCertificateKeyFile /etc/ssl/private/privkey.pem
# 2.4.8 미만 — 체인을 따로
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateChainFile /etc/ssl/certs/chain.pem
SSLCertificateKeyFile /etc/ssl/private/privkey.pem
SSLCertificateChainFile은 2.4.8에서 deprecated 됐지만 여전히 동작한다. 사고는 옛 설정을 복사해 쓰면서
ChainFile 갱신을 빼먹을 때 난다. leaf는 새것, 체인은 옛것이 되고, 발급사가 중간 인증서를 바꿨다면 그대로
체인 오류다.
mod_md
Apache 2.4.30+는 ACME 클라이언트를 내장하고 있다. certbot 없이 MDomain example.com 설정만으로 발급과
갱신이 된다. 새로 구축한다면 검토해 볼 만하다. 다만 갱신한 인증서를 적용하려면 graceful이 필요한 건 같다.
IIS
IIS의 인증서는 컴퓨터 계정의 인증서 저장소에 있다. 사이트 설정에는 파일 경로 대신 지문(thumbprint)이 적혀 있고, IIS는 그 지문을 가진 인증서를 저장소에서 꺼내 쓴다. 그래서 교체는 두 단계다. 새 인증서를 저장소에 임포트하고, 사이트 바인딩이 새 인증서를 가리키게 바꾼다. 임포트만 하고 끝내면 새 인증서는 저장소에 얌전히 들어 있고 옛것이 계속 서빙된다.
지금 상태 기록
# 지금 바인딩된 인증서의 지문
Get-WebBinding -Protocol https | ForEach-Object {
$_.certificateHash + " " + $_.bindingInformation
}
# 외부에서 본 서빙 지문 (교체 후 대조용)
# openssl 이 있는 아무 곳에서:
# openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -fingerprint -sha256
PFX로 임포트
IIS는 개인키가 들어 있는 PFX(PKCS#12)를 쓴다. PEM(fullchain + key)으로 받았다면 먼저 변환한다.
openssl pkcs12 -export -out cert.pfx \
-inkey privkey.pem -in fullchain.pem \
-passout pass:임시비밀번호
PFX를 만들 때 fullchain을 넣어야 한다. 중간 인증서가 PFX에 들어 있어야 임포트할 때 중간 인증 기관 저장소에도 같이 들어가고, IIS가 체인을 완성해 보낼 수 있다.
$pw = Read-Host -AsSecureString # 임시비밀번호 입력
Import-PfxCertificate -FilePath .\cert.pfx `
-CertStoreLocation Cert:\LocalMachine\My -Password $pw
# 임포트 확인 + 새 지문 확보
Get-ChildItem Cert:\LocalMachine\My |
Sort-Object NotAfter -Descending |
Select-Object -First 3 Subject, NotAfter, Thumbprint
저장소는 Cert:\LocalMachine\My(개인)가 맞다. CurrentUser에 넣으면 IIS 서비스 계정이 못 본다. 임포트는
됐는데 목록에 없다면 흔히 이것 때문이다.
바인딩 교체
$thumb = "새_인증서_지문"
$binding = Get-WebBinding -Name "Default Web Site" -Protocol https
$binding.AddSslCertificate($thumb, "My")
IIS 관리자에서는 사이트 → 바인딩 → https 편집 → SSL 인증서 드롭다운에서 새것을 고른다. 이 드롭다운은 “식별
이름”만 보여 줘서 신·구 인증서가 같은 이름으로 두 줄 나오고, 만료일은 안 보인다. GUI로 할 거면 교체 전에 옛
인증서의 식별 이름을 바꿔 두면(예: 뒤에 -old) 고를 때 헷갈리지 않는다.
바인딩 교체는 재시작 없이 바로 적용된다. iisreset은 필요 없고, 오히려 전체 사이트를 끊는다.
서빙되는 인증서 확인
저장소에 들어간 것 말고 실제로 나가는 인증서를 봐야 한다. 바인딩부터 확인한다.
# 바인딩이 새 지문을 가리키는지
Get-WebBinding -Protocol https | Select-Object bindingInformation, certificateHash
그다음 처음에 기록한 외부 지문과 비교한다. 지문이 그대로면 다른 사이트에 바인딩했거나, SNI 구성에서 다른 바인딩이 응답하고 있는 것이다.
옛 인증서는 며칠 둔다
교체하고 나면 옛 인증서를 저장소에서 바로 지우고 싶어진다. 적어도 며칠은 둔다. 남아 있으면 롤백이 바인딩 되돌리기 한 줄로 끝나고, 지웠으면 임포트부터 다시 해야 한다.
# 며칠 뒤, 문제 없으면
Remove-Item Cert:\LocalMachine\My\옛_지문
교체 후 체인 확인
Apache는 ChainFile을 안 바꿔서, IIS는 PFX에 체인을 안 넣어서 중간 인증서가 빠진다. 경로는 달라도 결과는 같다. 확인은 서버 종류와 상관없이 이 명령 하나로 한다.
openssl s_client -connect example.com:443 -servername example.com \
-verify_return_error </dev/null 2>&1 | grep "Verify return code"
0 (ok)가 아니면 브라우저별 체인 오류가 이미 시작된 것이다.
도메인만 넣으면 바로 확인해 주는 진단 툴도 있다.