Apache·IIS 인증서 교체 절차 — 파일 방식과 저장소 방식의 차이

Nginx 교체 절차는 앞 글에서 다뤘다. Apache 는 Nginx 와 거의 같은 파일 방식이라 짧게 차이점만 짚고, 이 글의 대부분은 구조가 근본적으로 다른 IIS 에 쓴다.

핵심 차이 하나만 기억하면 된다:

Apache / Nginx IIS
인증서 위치 파일 경로 (설정이 가리킴) Windows 인증서 저장소
개인키 별도 파일 인증서와 함께 저장소에
교체 단위 파일 덮어쓰기 + 리로드 저장소 임포트 + 바인딩 변경
흔한 사고 파일 바꾸고 리로드 누락 저장소에 넣고 바인딩 안 바꿈

같은 사고가 이름만 바꿔 반복된다 — “새것을 준비했는데 옛것이 서빙된다”.

Apache — Nginx 와 다른 점만

절차(기록 → 검증 → 원자적 교체 → 설정 검증 → 리로드 → 서빙 지문 대조)는 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)을 가진 인증서를 써라”로 되어 있다. 그래서 교체는 두 단계다:

  1. 새 인증서를 저장소에 임포트
  2. 사이트 바인딩이 새 인증서를 가리키게 변경

1번만 하고 끝내면 저장소에 새 인증서가 얌전히 들어있는 채로 옛것이 계속 서빙된다.

1. 현재 상태 기록

# 지금 바인딩된 인증서의 지문
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

2. 임포트 — PFX 로

IIS 는 개인키가 포함된 PFX(PKCS#12) 를 쓴다. PEM(fullchain + key)으로 받았다면 변환부터:

openssl pkcs12 -export -out cert.pfx \
  -inkey privkey.pem -in fullchain.pem \
  -passout pass:임시비밀번호

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 서비스 계정이 못 본다 — “임포트는 됐는데 목록에 없다”의 단골 원인.

3. 바인딩 교체

$thumb = "새_인증서_지문"
$binding = Get-WebBinding -Name "Default Web Site" -Protocol https
$binding.AddSslCertificate($thumb, "My")

IIS 관리자 GUI로 하면: 사이트 → 바인딩 → https 편집 → SSL 인증서 드롭다운에서 새것 선택. 드롭다운은 “식별 이름”으로만 보여서 신·구 인증서가 같은 이름으로 두 줄 나온다. 만료일이 안 보이므로, GUI 로 할 때는 교체 전에 옛 인증서의 “식별 이름”을 바꿔두면(예: 뒤에 -old) 실수를 차단할 수 있다.

바인딩 교체는 재시작 없이 즉시 적용된다. iisreset 은 필요 없다 — 오히려 전체 사이트를 끊는다.

4. 검증 — 저장소 말고 서빙을

# 바인딩이 새 지문을 가리키는지
Get-WebBinding -Protocol https | Select-Object bindingInformation, certificateHash

그리고 1번에서 기록한 외부 지문과 대조한다. 지문이 그대로면 바인딩을 다른 사이트에 했거나, SNI 구성에서 다른 바인딩이 응답하고 있는 것이다.

5. 옛 인증서 정리 — 바로 지우지 말 것

교체 직후 옛 인증서를 저장소에서 지우고 싶어지는데, 최소 며칠은 둔다. 롤백이 “바인딩 되돌리기” 한 줄이 되기 때문이다. 옛 인증서를 지웠으면 롤백도 임포트부터 다시다.

# 며칠 뒤, 문제 없으면
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) 가 아니면 브라우저별 체인 오류가 이미 시작된 것이다. 도메인만 넣으면 바로 확인해주는 진단 툴도 있다.