트러블슈팅 5. DNS 를 바꿨는데 Let's Encrypt 만 옛 IP 를 볼 때: DNSSEC 질의에만 옛 값을 주는 네임서버
이번 주에 서버 여러 대를 새 노드로 옮기면서 같은 일을 네 번 겪었습니다. 메일, 비밀번호 관리자, 인증 서버, 그리고 이 블로그까지요.
순서는 매번 같았습니다. 새 노드에 서비스를 띄우고, 도메인 업체 관리 화면에서 A 레코드를 새 IP 로 바꾸고, 권한 네임서버에 직접 물어서 새 값이 나오는 걸 확인합니다.
dig +norec +short mail.pcmeister.co.kr @ns1.hosting.co.kr
새 IP 가 나옵니다. 그런데 Let’s Encrypt 는 인증서를 내주지 않았고, 구글(8.8.8.8)과 클라우드플레어(1.1.1.1)는 여전히 옛 IP 를 줬습니다. TTL 은 300초로 낮춰 두었는데 10분, 20분이 지나도 그대로였습니다.
캐시 문제라면 TTL 이 지나면 풀려야 하는데 그렇지 않았습니다. Quad9, KT DNS, OpenDNS 까지 전부 옛 IP 를 주고, mailcow 컨테이너 안의 unbound 도 옛 IP 를 보더군요. 공통점을 찾다 보니 다들 DNSSEC 검증을 하는 리졸버였습니다.
그래서 권한 네임서버에 DO 비트를 붙여서 물어봤습니다.
dig +norec +short mail.pcmeister.co.kr @ns1.hosting.co.kr A
dig +norec +dnssec mail.pcmeister.co.kr @ns1.hosting.co.kr A
첫 줄은 새 IP, 둘째 줄은 옛 IP 에 옛 TTL(600)이 나왔습니다. 같은 네임서버가 질의에 DO 비트가 있느냐 없느냐에 따라 다른 답을 주고 있었던 겁니다. 웃긴 건 이 영역은 DNSSEC 서명도 안 되어 있다는 점입니다(DS 도 DNSKEY 도 없음). 서명도 안 하는데 DNSSEC 질의 경로만 따로 늦게 반영되는 것 같습니다.
8.8.8.8 과 1.1.1.1 은 권한 서버에 물을 때 DO 비트를 붙이니 옛 값을 받아 캐시하고, Let’s Encrypt 의 검증 리졸버도 마찬가지입니다. 결국 레코드를 바꾸고 대략 50분이 지나야 DO 질의까지 새 값으로 바뀌었습니다. 비밀번호 관리자 때가 50분쯤, 인증 서버 때가 48분이었습니다.
해결이라기보다는 피해 가는 방법입니다.
- DNS 를 바꾸기 전에 새 서버의 인증서를 미리 받아 둡니다. 옛 서버 앞단이
/.well-known/acme-challenge/요청을 새 서버로 넘기게 해 두면 DNS 가 옛 서버를 가리키는 동안에도 HTTP-01 검증이 새 서버까지 갑니다. - 바꾼 뒤 50분 정도는 옛 서버가 들어온 요청을 새 서버로 넘기게 둡니다. 그래야 옛 IP 를 보는 사용자도 끊기지 않습니다.
- 반영 확인은 꼭 DO 비트를 붙여서 권한 서버 네 곳에 다 물어봅니다.
for ns in $(dig +short NS pcmeister.co.kr); do echo "$ns $(dig +norec +dnssec +short mail.pcmeister.co.kr @$ns A | head -1)"; done
이 블로그 주소를 새로 만들 때는 이걸 알면서도 순서를 거꾸로 했다가 한 번 더 당했습니다. 그 이야기는 따로 적었습니다.
메일 서버 때는 기다리는 동안 메일 서버의 자체 인증서 갱신까지 옛 IP 를 보고 실패해서, 그날만 임시로 mailcow 안의 리졸버가 이 도메인을 구글·클라우드플레어 DNS 에 묻게 돌려 두었습니다. 업체 쪽 반영이 끝난 뒤에 원래대로 되돌렸습니다.