续期了,发出去的仍是旧证书
한국어 원문으로 표시합니다.
목표
인증서를 기동 때 한 번만 읽는 HTTPS 서버에 대해 갱신 사고를 재현하고, 디스크가 아니라 서버가 내보내는 인증서를 감시하는 스크립트 두 개를 만듭니다.
왜 중요한가
갱신 도구는 파일을 바꾸고 서버는 메모리를 내보냅니다. 그 사이에 재기동이 없으면 "갱신 성공" 로그와 "만료 임박" 경고가 동시에 참이 됩니다. 재료 서버 /opt/app/tlsserve.py 는 load_cert_chain 을 딱 한 번 부르는 파이썬 HTTPS 서버로, 실제 서버 대부분이 그렇듯 파일이 바뀌어도 다시 읽지 않습니다. 이 실습의 감시 스크립트는 채점기가 따로 띄운 서버로 양방향(같은 파일 FRESH, 다른 파일 STALE) 검사를 받습니다.
단계
/root/renew/ca.key·/root/renew/ca.crt(CN=Lab Root CA)와/root/renew/server.key, 그리고 CA 가 서명한 3일짜리/root/renew/v1.crt(SANDNS:www.lab.internal)를 만드세요.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에 저장하세요.- 같은 키로 30일짜리
/root/renew/v2.crt를 발급하고live.crt에 덮어쓰세요(갱신 도구가 하는 일). 서버는 재기동하지 마세요. - 다시 s_client 로
serial=을/root/renew/04-served.txt에,curl -sk https://127.0.0.1:8443/의 본문을/root/renew/04-body.txt에 저장하세요. 디스크는 v2 인데 서버는 v1 이어야 합니다. /root/renew/certdiff.sh <인증서파일> <host:port>를 만드세요. 디스크 파일과 서버가 내보내는 인증서의 SHA-256 지문이 같으면FRESH를 출력하고 0, 다르면STALE을 출력하고 1 로 끝나야 합니다.live.crt와127.0.0.1:8443에 대해 돌린 출력을/root/renew/05-detect.txt에 저장하세요.- 서버를 끝내고 다시 띄운 뒤 s_client 의
serial=을/root/renew/06-served.txt에 저장하세요. /root/renew/servedcheck.sh <host:port> <초>를 만드세요. 서버가 내보내는 인증서가 그 초 안에 만료되면EXPIRING을 출력하고 1, 아니면OK를 출력하고 0 으로 끝나야 합니다.127.0.0.1:8443 604800으로 돌린 출력을/root/renew/07-monitor.txt에 저장하세요./root/renew/08-report.md에 v1·v2 의 일련번호, 서버가 새 파일을 읽게 만든 방법, 감시는 디스크가 아니라 서버가 내보내는 인증서를 봐야 하는 이유를 적으세요.
참고
- s_client 는 표준 입력을 기다리므로
echo | openssl s_client -connect 127.0.0.1:8443 -servername www.lab.internal 2>/dev/null | openssl x509 -noout -serial처럼 씁니다. - 서버 끝내기:
pkill -f tlsserve.py. 다시 띄울 때는nohup ... &로 뒤에 두세요. - 스크립트 안에서 받은 인증서를 파일로 잠시 저장하려면
openssl x509 -out <임시파일>로 받으면 됩니다. - 흔한 실수: 4단계 전에 서버를 재기동하면 사고가 사라집니다. 7단계의 감시 스크립트가 디스크 파일을 보면 채점기의 서버에서 떨어집니다.
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' 가 들어가면 채점기가 결론을 찾습니다.