LabHub
배우기 러닝패스 코스

証明書は更新されたのに、ブラウザは古いものを表示した

更新したのに古い証明書が出ていく

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

인증서를 기동 때 한 번만 읽는 HTTPS 서버에 대해 갱신 사고를 재현하고, 디스크가 아니라 서버가 내보내는 인증서를 감시하는 스크립트 두 개를 만듭니다.

왜 중요한가

갱신 도구는 파일을 바꾸고 서버는 메모리를 내보냅니다. 그 사이에 재기동이 없으면 "갱신 성공" 로그와 "만료 임박" 경고가 동시에 참이 됩니다. 재료 서버 /opt/app/tlsserve.pyload_cert_chain 을 딱 한 번 부르는 파이썬 HTTPS 서버로, 실제 서버 대부분이 그렇듯 파일이 바뀌어도 다시 읽지 않습니다. 이 실습의 감시 스크립트는 채점기가 따로 띄운 서버로 양방향(같은 파일 FRESH, 다른 파일 STALE) 검사를 받습니다.

단계

  1. /root/renew/ca.key·/root/renew/ca.crt(CN=Lab Root CA)와 /root/renew/server.key, 그리고 CA 가 서명한 3일짜리 /root/renew/v1.crt(SAN DNS:www.lab.internal)를 만드세요.
  2. v1.crt/root/renew/live.crt 로, server.key/root/renew/live.key 로 복사한 뒤 python3 /opt/app/tlsserve.py --cert /root/renew/live.crt --key /root/renew/live.key --port 8443 을 띄우세요. openssl s_client 로 받은 인증서의 serial= 줄을 /root/renew/02-served.txt 에 저장하세요.
  3. 같은 키로 30일짜리 /root/renew/v2.crt 를 발급하고 live.crt 에 덮어쓰세요(갱신 도구가 하는 일). 서버는 재기동하지 마세요.
  4. 다시 s_client 로 serial=/root/renew/04-served.txt 에, curl -sk https://127.0.0.1:8443/ 의 본문을 /root/renew/04-body.txt 에 저장하세요. 디스크는 v2 인데 서버는 v1 이어야 합니다.
  5. /root/renew/certdiff.sh <인증서파일> <host:port> 를 만드세요. 디스크 파일과 서버가 내보내는 인증서의 SHA-256 지문이 같으면 FRESH 를 출력하고 0, 다르면 STALE 을 출력하고 1 로 끝나야 합니다. live.crt127.0.0.1:8443 에 대해 돌린 출력을 /root/renew/05-detect.txt 에 저장하세요.
  6. 서버를 끝내고 다시 띄운 뒤 s_client 의 serial=/root/renew/06-served.txt 에 저장하세요.
  7. /root/renew/servedcheck.sh <host:port> <초> 를 만드세요. 서버가 내보내는 인증서가 그 초 안에 만료되면 EXPIRING 을 출력하고 1, 아니면 OK 를 출력하고 0 으로 끝나야 합니다. 127.0.0.1:8443 604800 으로 돌린 출력을 /root/renew/07-monitor.txt 에 저장하세요.
  8. /root/renew/08-report.md 에 v1·v2 의 일련번호, 서버가 새 파일을 읽게 만든 방법, 감시는 디스크가 아니라 서버가 내보내는 인증서를 봐야 하는 이유를 적으세요.

참고

CA 와 3일짜리 v1

/root/renew/ 에 ca.key·ca.crt(CN=Lab Root CA)·server.key 와 3일짜리 v1.crt(SAN DNS:www.lab.internal)를 만드세요.

앞 모듈과 같은 순서입니다 — CA 자기 서명, SAN 있는 CSR, x509 -req 로 서명(-copy_extensions copy). CSR 은 3단계에서 다시 쓰니 server.csr 로 남겨 두세요.

서버가 든 인증서 읽기

v1.crt→live.crt, server.key→live.key 로 복사해 tlsserve.py 를 8443 에 띄우고, s_client 로 받은 serial= 줄을 /root/renew/02-served.txt 에 저장하세요.

서버는 nohup 으로 뒤에 두고 로그는 /root/renew/server.log 로 보내세요. s_client 출력 전체를 x509 -noout -serial 에 넘기면 serial= 한 줄이 나옵니다.

갱신 — 파일을 덮어쓴다

같은 키로 30일짜리 /root/renew/v2.crt 를 발급하고 live.crt 에 덮어쓰세요. 서버는 재기동하지 마세요.

같은 CSR 을 다시 서명하면 됩니다(-days 30). serial 이 새로 매겨지고 만료일이 늘어납니다. cp v2.crt live.crt 가 갱신 도구가 하는 일의 전부입니다.

디스크는 v2, 서버는 v1

s_client 의 serial=/root/renew/04-served.txt 에, curl -sk https://127.0.0.1:8443/ 본문을 /root/renew/04-body.txt 에 저장하세요.

서버는 기동 때 읽은 것을 계속 내보냅니다. 두 파일 모두 v1 의 serial 이 보여야 사고가 재현된 것입니다. curl 의 -k 는 자체 CA 라 검증을 끄는 것이고, 본문에는 서버가 스스로 말하는 serial 이 있습니다.

디스크와 서버를 비교하는 스크립트

/root/renew/certdiff.sh <인증서파일> <host:port> 를 만들고(같으면 FRESH·0, 다르면 STALE·1), live.crt 와 127.0.0.1:8443 에 대한 출력을 /root/renew/05-detect.txt 에 저장하세요.

두 지문을 구합니다 — 파일은 x509 -in 파일 -fingerprint -sha256, 서버는 s_client 출력을 x509 -fingerprint -sha256 에 넘겨서. 서버에서 인증서를 못 받으면 ERROR 로 2 를 돌려주면 좋습니다. 채점기는 자기 서버로 같은 파일·다른 파일 두 경우를 돌립니다.

재기동 — 서버가 새 파일을 읽는다

서버를 끝내고 다시 띄운 뒤 s_client 의 serial=/root/renew/06-served.txt 에 저장하세요.

pkill -f tlsserve.py 로 끝내고 같은 명령으로 다시 띄웁니다. 기동 때 live.crt 를 새로 읽으므로 이번에는 v2 의 serial 이 나와야 합니다.

서버가 내보내는 인증서의 만료 감시

/root/renew/servedcheck.sh <host:port> <초> 를 만들고(그 초 안에 만료면 EXPIRING·1, 아니면 OK·0), 127.0.0.1:8443 604800 의 출력을 /root/renew/07-monitor.txt 에 저장하세요.

s_client 로 받은 인증서를 임시 파일에 x509 -out 으로 저장한 뒤 -checkend <초> 를 걸면 됩니다. 디스크의 live.crt 를 보면 안 됩니다 — 채점기는 2일짜리 인증서를 든 자기 서버에 7일 창을 주어 EXPIRING 이 나오는지 봅니다.

사고 보고서

/root/renew/08-report.md 에 v1·v2 일련번호, 서버가 새 파일을 읽게 만든 방법, 감시가 서버가 내보내는 인증서를 봐야 하는 이유를 적으세요.

두 serial 은 v1.crt·v2.crt 에서 -serial 로 뽑아 그대로 넣으세요. '재기동' 이라는 말과 's_client' 가 들어가면 채점기가 결론을 찾습니다.