본문 바로가기

네트워크

DNSSEC Part 8 : 검증 여부 확인 및 설정

today keys : DNSSEC, 검증 확인, 트러스트 앵커, fail-open, Windows DNS, EDE, NTP, 재서명


DNSSEC을 운영하면서 가장 흔한 착각은 "설정을 켜뒀으니 검증하고 있을 것"이라는 판단입니다. 실제로는 검증 기능이 활성화되어 있어도 트러스트 앵커가 없으면 아무것도 검증하지 않으며, 겉으로는 정상 동작하는 것처럼 보입니다.

이번 편에서는 운영 중인 DNS 서버가 실제로 검증을 수행하고 있는지 판별하는 방법부터 시작해, Windows DNS에서 트러스트 앵커를 확인하고 설정하는 절차, 그리고 장애가 발생했을 때 원인을 구분하는 방법까지 알아보겠습니다.


1. 검증 설정이 켜져 있어도 트러스트 앵커가 없으면 검증하지 않는다

앞서 살펴본 검증 3단계를 다시 떠올려보겠습니다.

Step 1.  트러스트 앵커와 루트 KSK 대조
Step 2.  KSK로 DNSKEY RRSIG 검증
Step 3.  ZSK로 하위 DS의 RRSIG 검증

앵커가 없으면 Step 1. 에서 비교할 기준값 자체가 없습니다. 대조를 시작할 수 없으니 Step 2와 Step 3으로 넘어갈 방법도 없습니다.

"검증했는데 실패"가 아니라 "검증을 시작하지 못한" 상태입니다.

리졸버는 트러스트 체인의 시작 지점이 없기 때문에 

secure도 bogus도 판정할 수 없고, 결국 모든 응답을 insecure로 취급해 그대로 통과시킵니다.

설정 트러스트 앵커 실제 동작 ad 플래그
검증 ON 있음 검증 수행 secure면 부착
검증 ON 없음 검증하지 않음 부착되지 않음
검증 OFF 무관 검증하지 않음 부착되지 않음

 

검증  설정이 On이라고 하더라도 트러스트 앵커가 없다면, 검증 설정이 Off된 것과 구분되지 않습니다.

즉, 설정 화면에는 검증이 켜져 있다고 표시되는데 실제 동작은 꺼둔 것과 동일합니다.

앵커가 없을 때 응답을 차단하는 방식(fail-closed)으로 동작한다면,  전 도메인이 조회 불가 상태가 됩니다.

실수 하나가 전면 장애로 이어질 수 있기 때문에 대부분의 구현이 fail-open을 택합니다.

가용성 측면에서는 합리적인 선택이지만,

운영자가 "우리는 검증하고 있다"고 믿는 상태로 방치될 수 있다는 점에서 위험합니다.

 

2. 리졸버가 실제로 DNSSEC 검증을 수행하는지 확인

dig 명령어 수행 시, '@리졸버 서버IP' 옵션을 수행하면,

리졸버 서버로 직접 질의를 던질 수 있기 때문에 리졸버 서버와 통신이 되는 환경이라면 어디에서든 확인이 가능합니다.

첫 번째 - 의도적으로 깨진 도메인 조회

dig @<리졸버IP> dnssec-failed.org A
응답 상태(status) 판정
status: SERVFAIL 검증 수행 중
status: NOERROR + A 레코드 반환 검증하지 않음

dnssec-failed.org는 부모에 DS는 있는데 대응하는 DNSKEY가 자식 존에 없도록 설정해둔 테스트 도메인입니다.

기존 포스팅에서 다룬 키 롤오버 사고 상태를 재현해둔 것이라고 보시면 됩니다.

응답하지 않는 경우 sigfail.verteiltesysteme.net을 대신 사용할 수 있으며,

정상 대조군은 sigok.verteiltesysteme.net입니다.

zigi@ZIGI:~$ dig @8.8.8.8 dnssec-failed.org A

; <<>> DiG 9.18.39-0ubuntu0.24.04.5-Ubuntu <<>> @8.8.8.8 dnssec-failed.org A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 45267
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
; EDE: 9 (DNSKEY Missing): (No DNSKEY matches DS RRs of dnssec-failed.org)
;; QUESTION SECTION:
;dnssec-failed.org.             IN      A
zigi@ZIGI:~$ dig @168.126.63.1 dnssec-failed.org A

; <<>> DiG 9.18.39-0ubuntu0.24.04.5-Ubuntu <<>> @168.126.63.1 dnssec-failed.org A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16405
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 76ab87124951dc36010000006aa9b6ff484664d2cafed9cf (good)
;; QUESTION SECTION:
;dnssec-failed.org.             IN      A

;; ANSWER SECTION:
dnssec-failed.org.      254     IN      A       96.99.227.255

 

두 번째 - AD 플래그 확인

dig cloudflare.com A +dnssec @<리졸버IP>

 flags줄에 'ad'가 포함되어 출력되면 DNSSEC 검증을 한 것입니다.

참고로 '@리졸버IP' 옵션은 앞에서 처럼 앞에 적용해도 되고,  예시 처럼 뒤에 적용해도 됩니다. 

;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2

여기서 흔히 혼동하는 지점이 있습니다. 응답에 RRSIG가 실려 있다고 해서 검증한 것이 아닙니다.

+dnssec 옵션은 서명 데이터를 함께 보내달라는 요청일 뿐이고, 서버는 캐시에 있는 RRSIG를 그대로 전달할 수도 있습니다.

판단 기준은 ad 플래그입니다.

zigi@ZIGI:~$ dig cloudflare.com A +dnssec @8.8.8.8

; <<>> DiG 9.18.39-0ubuntu0.24.04.5-Ubuntu <<>> cloudflare.com A +dnssec @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44673
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;cloudflare.com.                        IN      A

;; ANSWER SECTION:
cloudflare.com.         300     IN      A       104.16.132.229
cloudflare.com.         300     IN      A       104.16.133.229
cloudflare.com.         300     IN      RRSIG   A 13 2 300 20260916222555 20260914202555 34505 cloudflare.com. XcFXPEEvjgaFoxi2TY/x+CGkRMr0lhf7BItuJgQVouBlVxCdAXC4VqWE NIzMUmZCbyAbSWyQRwHNZt+cF4n1RQ==

 

zigi@ZIGI:~$ dig cloudflare.com A +dnssec @168.126.63.1

; <<>> DiG 9.18.39-0ubuntu0.24.04.5-Ubuntu <<>> cloudflare.com A +dnssec @168.126.63.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34014
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 2077d61ad536428e010000006aa9b7fa518d5e10ffe16245 (good)
;; QUESTION SECTION:
;cloudflare.com.                        IN      A

;; ANSWER SECTION:
cloudflare.com.         287     IN      A       104.16.132.229
cloudflare.com.         287     IN      A       104.16.133.229
cloudflare.com.         287     IN      RRSIG   A 13 2 300 20260916222605 20260914202605 34505 cloudflare.com. IV6fa4KVjZCELW1QXO/Mn6ORirBGMINPqhJ2kg4c4JgqGtXdbZ92v0OL cAvn+BOLbtgSh7rVz7aW/9pcjj08rw==

 

 

세 번째 - 공용 리졸버와 대조

dig dnssec-failed.org A @1.1.1.1     ← SERVFAIL 이어야 정상
dig dnssec-failed.org A @8.8.8.8     ← SERVFAIL 이어야 정상
dig dnssec-failed.org A @<리졸버IP>   ← 우리 서버

Cloudflare와 Google의 공용 리졸버는 검증을 수행하므로 대조군으로 적합합니다.

세 결과를 나란히 놓으면 우리 서버의 상태가 분명해집니다. 

앞서 8.8.8.8과 168.126.63.1의 조회 결과를 참고해 보면 확인해 볼 수 있습니다.

 

Windows 환경에서 확인하기

Windows에는 dig가 기본 포함되어 있지 않습니다. PowerShell의 Resolve-DnsName으로 같은 판별이 가능합니다.

Resolve-DnsName dnssec-failed.org -Server <리졸버IP> -Type A
결과 판정
쿼리 실패 오류 반환 검증 수행 중
A 레코드 정상 반환 검증하지 않음

AD 플래그에 해당하는 정보는 -DnssecOk 옵션으로 확인합니다.

Resolve-DnsName cloudflare.com -Server <리졸버IP> -Type A -DnssecOk

이 옵션은 DO 비트를 세워 질의하므로 응답에 RRSIG가 함께 반환됩니다.

RRSIG가 왔다는 사실만으로는 검증 여부를 알 수 없습니다.

검증 성공 여부까지 명확히 보려면 첫 번째 방법과 병행하는 편이 확실합니다.

PS C:\> Resolve-DnsName cloudflare.com -Server 8.8.8.8 -Type A -DnssecOk

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
cloudflare.com                                 A      300   Answer     104.16.132.229
cloudflare.com                                 A      300   Answer     104.16.133.229

Name        : cloudflare.com
QueryType   : RRSIG
TTL         : 300
Section     : Answer
TypeCovered : A
Algorithm   : 13
LabelCount  : 2
OriginalTtl : 300
Expiration  : 2026-09-16 오후 10:29:08
Signed      : 2026-09-14 오후 8:29:08
Signer      : cloudflare.com
Signature   : {224, 140, 63, 134...}

 

주의할 점

재귀 허용 대역이 아닌 곳에서 질의하면 REFUSED가 반환되는데, 이는 검증 여부와 무관한 별개 결과입니다.

또한 방화벽이 53번 포트를 리다이렉트하는 환경에서는 @ 뒤에 지정한 서버가 아닌 다른 서버가 응답할 수 있으므로,

출력 마지막의 SERVER: 줄을 확인하시기 바랍니다.

 

3. Windows DNS에서 검증 설정과 트러스트 앵커 확인·등록하기

앞 장에서 검증하지 않는 것으로 판별된 서버가 있다면, 이제 해당 장비에 접속해 원인을 확인할 차례입니다.

Windows DNS를 기준으로 설명하지만, 확인해야 할 항목은 어떤 제품이든 동일합니다.

검증 기능 활성화 여부트러스트 앵커 보유 여부 두 가지입니다.

확인 - PowerShell

Get-DnsServerSetting -All | Select-Object EnableDnsSec

Get-DnsServerTrustAnchor -Name "." |
  Format-Table KeyTag, TrustAnchorState, CryptoAlgorithm -AutoSize

첫 번째 명령은 검증 기능 스위치를, 두 번째는 실제 앵커 보유 여부를 확인합니다. 두 번째가 더 중요합니다.

TrustAnchorState 값의 의미는 다음과 같습니다.

상태 의미
Valid 정상 사용 중
AddPend RFC 5011 자동 갱신으로 추가 대기 중 (홀드다운 기간)
Revoked 폐기 표시된 키
Missing 앵커가 없음

명령이 아예 오류를 반환하는 경우도 있습니다.

Get-DnsServerTrustAnchor : Failed to enumerate the trust anchors for
the input trust point . on server ...

이는 루트에 대한 신뢰 지점 자체가 등록되지 않았다는 의미로  fail-open 상태에 해당합니다.

확인 - GUI

DNS 관리자에서 서버를 우클릭해 속성을 열고 고급 탭의 'Enable DNSSEC validation for remote responses' 항목을 확인합니다. 앵커는 서버 노드 아래 Trust Points 항목에서  '.'을 펼쳐 볼 수 있습니다.

서명 관련 레코드가 보이지 않는다면 '보기 → 고급'이 켜져 있는지 확인해보시면 됩니다.

설정 - 앵커 가져오기

dnscmd /RetrieveRootTrustAnchors

이 명령은 data.iana.org로 HTTPS 접속이 필요합니다.

폐쇄망이거나 프록시를 경유하는 환경에서는 실패하므로, 먼저 연결성부터 확인하는 편이 빠릅니다.

Test-NetConnection data.iana.org -Port 443

가져오기가 완료되면 서비스를 재시작하고 다시 확인합니다.

Restart-Service DNS
Get-DnsServerTrustAnchor -Name "."

Windows Server 2012 이후 버전은 RFC 5011 자동 갱신을 지원하므로,

최초 한 번 가져오면 이후 루트 키가 바뀌어도 자동으로 반영됩니다.

다만 그 자동 갱신 역시 외부 연결이 전제이므로,

방화벽 정책 변경 후 조용히 실패하고 있지는 않은지 주기적으로 확인할 필요가 있습니다.

관련 이벤트는 이벤트 뷰어의 Applications and Services Logs → DNS Server에서 확인할 수 있습니다.

 

4. 조회 경로에서 실제로 검증을 수행하는 장비 찾아내기

우리 서버가 검증하지 않는다고 해서 안심할 수 없습니다.

조회 경로 어딘가에 검증하는 장비가 있으면 그곳에서 문제가 발생합니다.

 

포워더를 사용하는 경우 - 상위 리졸버 확인

로컬에서 검증하지 않고 상위로 전달만 한다면 우리 장비의 앵커는 무관합니다.

대신 상위 리졸버가 bogus 판정을 내리면 SERVFAIL이 그대로 내려옵니다.

점검 대상이 우리 장비가 아니라 포워딩 대상이 되는 것입니다.

포워딩 대상에 직접 질의해 같은 방식으로 판별합니다.

dig dnssec-failed.org A @<포워더 IP>

포워더가 여러 단계로 연결되어 있다면 각 단계를 순서대로 확인해야 합니다.

어느 단계에서 SERVFAIL이 시작되는지가 곧 검증을 수행하는 지점입니다.

 

경로상 중간 장비 - 응답 출처 확인

방화벽이나 DNS 보안 게이트웨이가 DNSSEC 검증 기능을 갖고 있는 경우가 있습니다.

이런 장비는 질의를 가로채 대신 응답하기도 하므로, 우리가 지정한 서버가 실제로 답했는지부터 확인해야 합니다.

dig dnssec-failed.org A @<리졸버IP>

출력 마지막의 SERVER: 줄을 확인합니다.

;; SERVER: 10.10.10.53#53(10.10.10.53) (UDP)

@ 뒤에 지정한 주소와 다른 값이 표시된다면 경로 어딘가에서 질의가 가로채이고 있다는 뜻입니다.

이 경우 리졸버 설정을 아무리 확인해도 실제 동작과 맞지 않으므로, 네트워크 경로부터 정리해야 합니다.

같은 질의를 서로 다른 대역의 단말에서 실행해 결과가 달라지는지 비교해보는 것도 도움이 됩니다.

특정 대역에서만 SERVFAIL이 발생한다면 그 경로에 검증을 수행하는 장비가 있다는 신호입니다.

 

5. SERVFAIL이 발생했을 때 EDE 코드로 원인 구분하기

검증이 실패해 SERVFAIL이 반환됐을 때, 그 원인을 알려주는 것이 EDE(Extended DNS Errors) 필드입니다.

최신 버전의 dig는 별도 옵션 없이 이 값을 표시합니다.

; EDE: 9 (DNSKEY Missing)
코드 의미 주요 원인
6 DNSSEC Bogus 서명 검증 실패
7 Signature Expired RRSIG 유효기간 만료, 재서명 누락
8 Signature Not Yet Valid 서명 시작 시각이 미래, 시간 오차
9 DNSKEY Missing DS에 대응하는 DNSKEY 없음, 롤오버 사고
10 RRSIGs Missing 서명이 있어야 하는데 없음
12 NSEC Missing 부재 증명 레코드 누락

7번과 8번이 특히 중요합니다. 둘 다 시간과 관련된 실패로, 서명 자체는 정상인데 유효기간 판정에서 걸린 경우입니다.

NTP 동기화는 필수 요건

RRSIG에는 유효기간이 박혀 있고, 리졸버는 자신의 시스템 시각으로 이를 판정합니다.

서버 시계가 며칠 틀어져 있으면 정상 서명도 만료되었거나 아직 유효하지 않은 것으로 오판합니다.

증상이 "특정 도메인이 아니라 여러 도메인에서 동시에 SERVFAIL"이라면 시간 동기화를 먼저 확인해보시기 바랍니다.

원인을 찾기 까다로운 장애 유형입니다.

 

6. 내 존을 서명해 운영할 때 권한 서버에서 점검할 항목

여기까지는 검증하는 쪽 이야기였습니다. 내 존을 서명해 운영 중이라면 반대쪽도 점검이 필요합니다.

서명 만료 확인

dig <내도메인> SOA +dnssec +multi

RRSIG의 Expiration 값이 충분히 여유가 있는지 확인합니다.

재서명이 정상 동작하지 않으면 이 값이 점점 현재 시각에 가까워집니다.

 

부모의 DS와 내 KSK 일치 확인

dig <내도메인> DS +short
dig <내도메인> DNSKEY +short

DS의 Key Tag와 DNSKEY 중 257로 시작하는 줄의 키 태그가 일치해야 합니다. 

dnssec-dsfromkey로 직접 계산해 대조할 수도 있습니다.

 

외부에서 검증되는지 확인

delv @1.1.1.1 <내도메인> A

; fully validated가 출력되어야 정상입니다.

내 서버에서 보는 것과 외부 리졸버가 보는 것이 다를 수 있으므로, 반드시 외부 기준으로 확인해야 합니다.

 

체인 전체 시각화

https://dnsviz.net/d/<내도메인>/dnssec/

키와 DS의 연결 관계, 만료 임박 여부까지 그래프로 확인할 수 있습니다. 정기 점검 도구로 활용하기 좋습니다.

 

7. 검증 측과 서명 측 점검 체크리스트

검증하는 쪽 (재귀 리졸버)

□ dig dnssec-failed.org 로 실제 검증 여부 확인 (설정값이 아닌 실측)
□ 트러스트 앵커 존재 및 상태 확인
□ 앵커 자동 갱신 지원 여부 및 갱신 경로(외부 HTTPS) 연결성 확인
□ NTP 동기화 상태 확인
□ 포워더를 쓴다면 포워딩 대상도 동일하게 점검
□ 경로상 중간 장비의 DNSSEC 기능 여부 확인

서명하는 쪽 (권한 서버)

□ RRSIG 만료 여유 확인, 자동 재서명 동작 확인
□ 부모의 DS와 내 KSK 일치 확인
□ 외부 리졸버 기준으로 fully validated 확인
□ 키 롤오버 시 순서와 대기 시간 준수

 

※ 참고 자료 (Reference Links)