네트워크

DNSSEC Part 5 : 키와 레코드의 계층별 생성 절차

지기(ZIGI) 2026. 9. 13. 09:25

today keys : DNSSEC, dnssec-keygen, dnssec-signzone, DS 등록, EPP, 레지스트라, 키 세리머니, 재서명


지금까지는 리졸버 입장에서 검증이 어떻게 이루어지는지를 다뤘습니다. 이번 편에서는 관점을 바꿔, 그 검증에 사용되는 키와 레코드가 실제로 어떻게 만들어지는지 살펴봅니다.

생성 절차는 계층마다 동일합니다. 키를 만들고, 존을 서명하고, DS를 부모에게 제출하는 세 단계입니다. 루트와 TLD 계층에서 이 절차가 어떻게 수행되는지 먼저 확인한 뒤, 내 도메인에 적용할 때 어떤 명령으로 무엇이 산출되는지 정리하겠습니다.


1. 모든 계층이 같은 일을 한다

앞선 편에서 검증이 계층마다 동일한 패턴으로 반복된다는 것을 확인했습니다. 생성 쪽도 마찬가지입니다.

  1. 키 쌍 생성 (KSK, ZSK)
  2. 존 서명 → RRSIG, DNSKEY, NSEC3 생성
  3. KSK 공개키의 해시(DS)를 부모 존에 제출부모가 자기 존을 서명하면서 그 DS에도 RRSIG를 붙임

루트든 com 이든 내 도메인이든 이 세 단계를 그대로 밟습니다. 달라지는 것은 부모가 누구인가뿐입니다.

계층 수행 주체 DS 제출 대상
루트 IANA / PTI 없음 (부모가 없음)
TLD (com) 레지스트리 (Verisign) 루트
도메인 도메인 소유자 레지스트라 경유 → TLD

루트만 3단계를 수행할 수 없습니다. DS를 등록할 부모가 존재하지 않기 때문입니다.

그래서 앞서 다룬 트러스트 앵커라는 예외 장치가 필요했던 것입니다.

 

2. 루트 계층 - IANA와 키 세리머니

루트 존의 키는 IANA/PTI가 관리합니다. 여기서 눈여겨볼 것은 KSK와 ZSK의 보관 방식이 완전히 다르다는 점입니다.

KSK 개인키 - 오프라인 HSM

미국 동부와 서부 두 곳의 시설에 물리적으로 격리된 HSM(하드웨어 보안 모듈) 안에만 존재합니다. 네트워크에 연결되어 있지 않으며, 키 세리머니라는 공개 행사를 통해서만 사용됩니다. 전 세계에서 선정된 신뢰당사자들이 각자 보관하는 물리 키로 금고를 열고, 전 과정이 녹화되고 감사됩니다. 통상 분기에 한 번 열립니다.

 

ZSK 개인키 - 온라인 서명 시스템

루트 존은 TLD가 추가되거나 DS가 갱신될 때마다 바뀌므로 자주 서명해야 합니다. 이쪽은 운영 시스템의 HSM에 있습니다.

 

두 키로 나눈 효과가 극단적으로 드러나는 지점

이 구조 때문에 루트의 서명 작업은 두 갈래로 나뉩니다.

  • 분기 1회 - 키 세리머니 (KSK)
    • KSK로 향후 3개월치 DNSKEY RRSIG를 미리 만들어 둠
    • 만들어진 서명 묶음을 온라인 시스템에 넘기고 KSK는 다시 금고로
  • 수시 - 일상 존 서명 (ZSK)
    • 루트 존이 갱신될 때마다 ZSK로 각 TLD의 DS에 서명
    • DNSKEY RRSIG는 세리머니에서 받아둔 것을 그대로 사용

즉 KSK는 1년에 네 번만 쓰이고, 나머지 모든 서명은 ZSK가 담당합니다.

키가 하나뿐이었다면 루트 존이 바뀔 때마다 금고를 열어야 하는, 운영이 불가능한 구조가 됐을 것입니다.

 

트러스트 앵커 배포

루트는 DS를 제출할 부모가 없으므로, KSK 공개키의 해시를 IANA가 직접 공개합니다.

이것이 앞서 다룬 root-anchors.xml이며, 형식은 DS 레코드와 동일합니다.

각 리졸버 운영자가 이 값을 가져와 설정에 반영하면 신뢰의 시작점이 만들어집니다.

 

3. TLD 계층 - 레지스트리

com 존은 Verisign이 운영합니다. 

  1. Verisign이 com의 KSK/ZSK 쌍 생성
  2. com 존 서명 → DNSKEY, RRSIG, NSEC3 생성
  3. com KSK 공개키의 해시를 계산해 IANA/PTI에 제출
  4. IANA가 루트 존 파일에 com DS 레코드를 추가
  5. 루트 존 서명 시 그 DS에 루트 ZSK로 RRSIG가 붙음

마지막 단계를 짚어둘 필요가 있습니다. RRSIG는 누가 등록하는 것이 아닙니다.

Verisign이 제출하는 것은 DS 값 하나뿐이고,

그 DS에 붙는 RRSIG는 루트 운영자가 자기 존을 정기적으로 서명하는 과정에서 자동으로 만들어집니다.

이 원칙은 아래 도메인 계층에서도 똑같이 적용됩니다. 우리가 부모에게 제출하는 것도 DS 하나뿐입니다.

 

4. 도메인 계층 (1) - 키 생성

이제 직접 수행하는 절차입니다. zigispace.net 존에 DNSSEC을 적용한다고 가정하겠습니다. 부모는 net입니다.

dnssec-keygen -a ECDSAP256SHA256 -f KSK -n ZONE zigispace.net
dnssec-keygen -a ECDSAP256SHA256 -n ZONE zigispace.net

-f KSK 옵션의 유무가 KSK와 ZSK를 가릅니다. 실행하면 키마다 파일이 두 개씩 생성됩니다.

Kzigispace.net.+013+45678.key       ← 공개키 (DNSKEY 레코드 형태)
Kzigispace.net.+013+45678.private   ← 개인키 (서명 전용, 외부 유출 금지)

파일명에서 읽을 수 있는 정보가 있습니다.

구간 값 의미
존 이름 Kzigispace.net. 이 키가 속한 존
알고리즘 번호 013 ECDSA P-256 (RSA/SHA-256이면 008)
키 태그 45678 이 키의 식별 번호

키 태그는 공개키 값으로부터 계산되는 16비트 체크섬입니다.

앞서 RRSIG의 Key Tag 필드에서 본 그 값으로,

리졸버에게 "DNSKEY가 여러 개일 때 이 번호를 가진 키로 검증하라"고 알려주는 역할을 합니다.

 

두 파일이 생성된다는 점도 확인해두시면 좋습니다.

KSK와 ZSK가 각각 공개키와 개인키로 이루어진 한 쌍이라는 사실이 여기서 드러납니다.

 

한 가지 더, 키는 존 단위로 생성됩니다.

존 안에 이름이 몇 개든 레코드가 몇 개든 KSK 한 쌍과 ZSK 한 쌍이면 충분합니다.

RRset마다 키를 나눴다면 레코드가 늘어날 때마다 DS를 다시 등록해야 하는 구조가 됐을 것입니다.

 

5. 도메인 계층 (2) - 존 서명

평문 존 파일을 입력받아, DNSSEC 레코드가 추가된 새 존 파일을 만들어내는 일괄 작업입니다.

서명 전 존 파일은 이렇게 생겼습니다.

zigispace.net.      IN  SOA  ns1.zigispace.net. admin.zigispace.net. ( ... )
zigispace.net.      IN  NS   ns1.zigispace.net.
www.zigispace.net.  IN  A    10.10.10.10
blog.zigispace.net. IN  A    10.10.10.20

서명을 실행합니다.

dnssec-signzone -o zigispace.net \
  -k Kzigispace.net.+013+45678 \
  zigispace.net.zone \
  Kzigispace.net.+013+12345

-k 뒤가 KSK, 마지막 인자가 ZSK입니다. 결과물은 zigispace.net.zone.signed 파일이며, 내용은 이렇게 바뀝니다.

zigispace.net.      IN  SOA     ns1.zigispace.net. admin.zigispace.net. ( ... )
zigispace.net.      IN  RRSIG   SOA ... 12345 zigispace.net.      ← 추가
zigispace.net.      IN  NS      ns1.zigispace.net.
zigispace.net.      IN  RRSIG   NS ... 12345 zigispace.net.       ← 추가
zigispace.net.      IN  DNSKEY  257 3 13 mdsswUyr...              ← 추가 (KSK 공개키)
zigispace.net.      IN  DNSKEY  256 3 13 oJB1W6WN...              ← 추가 (ZSK 공개키)
zigispace.net.      IN  RRSIG   DNSKEY ... 45678 zigispace.net.   ← 추가 (KSK로 서명)
www.zigispace.net.  IN  A       10.10.10.10
www.zigispace.net.  IN  RRSIG   A ... 12345 zigispace.net.        ← 추가
blog.zigispace.net. IN  A       10.10.10.20
blog.zigispace.net. IN  RRSIG   A ... 12345 zigispace.net.        ← 추가
<해시>.zigispace.net. IN NSEC3  ...                               ← 추가
<해시>.zigispace.net. IN RRSIG  NSEC3 ... 12345 zigispace.net.    ← 추가

원본 레코드는 그대로 두고 그 옆에 서명 관련 레코드를 채워 넣는 작업입니다. 파일 크기가 보통 3~5배로 늘어납니다.

한 번의 실행으로 만들어지는 네 가지

산출물 서명 키 내용
RRSIG (일반) ZSK 개인키 모든 RRset에 하나씩
DNSKEY - KSK·ZSK 공개키를 게시
RRSIG (DNSKEY용) KSK 개인키 유일하게 KSK를 쓰는 곳
NSEC3 체인 ZSK 개인키로 서명 부재 증명용

여기에 더해 존 파일 바깥에 dsset-zigispace.net. 파일이 하나 생성됩니다. 부모에게 제출할 DS 값입니다.

zigispace.net. IN DS 45678 13 2 4F7A2B91C3E85D06FA1B...

DS는 KSK 공개키의 해시이므로, 사실 존 서명과 무관하게 키 파일만 있으면 계산할 수 있습니다.

dnssec-dsfromkey -2 Kzigispace.net.+013+45678.key

dnssec-signzone이 dsset- 파일을 만들어주는 것은 편의 기능일 뿐, "서명해야만 DS가 생긴다"는 의존 관계는 없습니다.

RRSIG는 몇 개가 생기는가

앞서 서명의 최소 단위가 RRset이라고 했으므로, RRSIG 개수도 거기서 결정됩니다.

RRSIG 개수 = (고유한 이름+타입 조합 수) + (NSEC3 체인 항목 수) + 1(DNSKEY용)

위 예제라면 SOA, NS, www A, blog A 네 개에 DNSKEY용 하나를 더해 최소 다섯 개이고, 여기에 NSEC3 항목 수만큼 늘어납니다.

 

 

6. 도메인 계층 (3) - DS 제출

마지막 단계입니다. 여기서 주의할 점은 DS 레코드를 내 존 파일에 쓸 수 없다는 것입니다.

DS는 부모 존에 있어야 하고, 부모 존은 내가 관리하는 대상이 아니기 때문입니다.

세 계층을 거친다

  1. Step 1. 등록자 (도메인 소유자, 우리) :  레지스트라 콘솔에 DS 입력
  2. 레지스트라 (가비아, 후이즈 등 도메인 판매 업체) :  EPP 프로토콜로 전달
  3. 레지스트리 (.net이면 Verisign, .kr이면 KISA) : TLD 존 파일에 DS 레코드 추가

우리가 직접 상호작용하는 것은 레지스트라뿐이고, 나머지는 백엔드에서 처리됩니다.

EPP는 레지스트라와 레지스트리 사이의 등록 정보 전달용 프로토콜입니다.

입력하는 값

레지스트라 콘솔의 DNSSEC 항목에서 DS의 네 필드를 입력합니다.

필드 값 의미
Key Tag 45678 KSK 식별 번호
Algorithm 13 ECDSA P-256
Digest Type 2 SHA-256
Digest 4F7A2B91... KSK 공개키의 해시

일부 레지스트라는 DS 대신 DNSKEY 값을 입력받아 자기들이 해시를 계산해주기도 합니다.

순서를 지켜야 한다

여기가 실무에서 가장 주의할 지점입니다.

올바른 순서:  서명된 존을 먼저 서비스에 반영 → 그 다음 DS 등록
잘못된 순서:  DS를 먼저 등록 → 서명된 존을 나중에 반영

순서를 뒤집으면 부모는 "이 존은 서명되어 있다"고 광고하는데 실제 권한 서버는 서명 없는 응답을 내보내게 됩니다.

검증 리졸버 입장에서는 이것이 정확히 bogus 상태입니다.

bogus는 SERVFAIL로 차단되므로, 도메인 전체가 조회되지 않습니다.

서명하지 않은 것보다 나쁜 결과입니다.

 

7. 존 서명은 언제 실행하는가

존 서명은 최초 1회로 끝나는 작업이 아닙니다. 실행 계기가 네 가지 있습니다.

① 최초 적용 - DNSSEC을 처음 켤 때. 지금까지 설명한 절차입니다.

② 존 내용 변경 - 레코드를 추가하거나 값을 바꾸면 해당 RRset의 RRSIG도 새로 만들어야 합니다.
                           특히 이름이 추가·삭제되면 정렬 순서가 바뀌므로 앞뒤 NSEC3 레코드까지 함께 갱신됩니다.

변경 전:  blog → mail
새 이름 hello 추가
변경 후:  blog → hello → mail   (세 레코드 모두 재생성)

③ 서명 만료 전 재서명 - 레코드가 전혀 바뀌지 않아도 RRSIG의 유효기간이 끝나기 전에 다시 서명해야 합니다.
                                             이것을 놓치면 존 전체가 bogus로 떨어집니다.

항목 일반적인 값
RRSIG 유효기간 14~30일
재서명 시점 만료까지 25~33% 남았을 때
실제 재서명 간격 수일 ~ 1주

만료 직전이 아니라 여유를 두는 이유는, 이미 캐시에 들어간 서명도 유효기간 안에 있어야 하고 재서명이 실패했을 때 복구할 시간이 필요하기 때문입니다.

④ 키 롤오버 - ZSK를 교체하면 그 키로 서명된 모든 RRSIG를 다시 만들어야 합니다.
                           반면 KSK 교체는 DNSKEY의 RRSIG만 바뀌지만, 부모 존의 DS를 다시 등록해야 합니다.
                           자주 바꾸는 키와 그렇지 않은 키를 나눈 이유가 여기서도 드러납니다.

 

이러한 DNS 존 서명을 매번 수동으로 하는 것은 실질적으로 쉽지 않기 때문에 실무에서는 자동화를 통해서 자동으로 처리 되도록 해야 합니다. 

 

8. 생성물 총정리

지금까지 다룬 값들이 어떤 재료로 어디서 만들어지는지 한 표로 정리하면 다음과 같습니다.

항목 생성용 데이터 연산 저장 위치
KSK / ZSK - 키 쌍 생성 개인키는 서버, 공개키는 DNSKEY
DNSKEY KSK·ZSK 공개키 없음 (게시) 자기 존
RRSIG (일반) RRset + 메타데이터 ZSK 개인키로 서명 자기 존
RRSIG (DNSKEY용) DNSKEY RRset + 메타데이터 KSK 개인키로 서명 자기 존
NSEC3 존 안의 모든 이름 해시 후 정렬 자기 존
DS KSK 공개키 해시 부모 존
트러스트 앵커 루트 KSK 공개키 해시 후 별도 배포 리졸버 설정

📌 한 줄 요약: 부모에게 제출하는 것은 DS 하나뿐이고, DNSKEY·RRSIG·NSEC3는 모두 각 존이 자기 데이터를 서명하면서 자동으로 생성됩니다.

 

9. 직접 확인해보기

계층별로 같은 구조가 반복되는지 확인

위에서 아래로 차례로 조회하면 세 계층이 동일한 구성을 갖는 것을 볼 수 있습니다.

dig . DNSKEY +short
dig com DNSKEY +short
dig cloudflare.com DNSKEY +short

각 계층 모두 257(KSK)과 256(ZSK) 두 줄이 나옵니다. 알고리즘 번호는 계층마다 다를 수 있습니다.

zigi@ZIGI:~$ dig @8.8.8.8 . DNSKEY +short
257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN R1AkUTV74bU=
257 3 8 AwEAAa96jeuknZlaeSrvyAJj6ZHv28hhOKkx3rLGXVaC6rXTsDc449/c idltpkyGwCJNnOAlFNKF2jBosZBU5eeHspaQWOmOElZsjICMQMC3aeHb GiShvZsx4wMYSjH8e7Vrhbu6irwCzVBApESjbUdpWWmEnhathWu1jo+s iFUiRAAxm9qyJNg/wOZqqzL/dL/q8PkcRU5oUKEpUge71M3ej2/7CPqp dVwuMoTvoB+ZOT4YeGyxMvHmbrxlFzGOHOijtzN+u1TQNatX2XBuzZNQ 1K+s2CXkPIZo7s6JgZyvaBevYtxPvYLw4z9mR7K2vaF18UYH9Z9GNUUe ayffKC73PYc=
256 3 8 AwEAAeCYD6Z7WWKVLeuWgowKP+3g+Gs1cnLKq7a3CaQxQpv8bfuFVI0W nG33qaSH/Mw9IBgifrdzf4XY/DQLnyBJ9MfaOyAWuEaEmYJ+GQPiwVVf stGwSA1McfFJUttTgq2Huu74KARhtA8wPo/N3XcyYQtNhz+qCM5NBb3e cx/naw6sYab9LxS6f2cU0q03++BP5Ks0Uef8WJCa/1izCYE+vMkwoltV +tENa3hpXiZ7jle/xdgaZrPi5ZGmyLVI34g1XVYrNlsCCTmNvFQIfzW5 STFQFsQpizczyFn9r3LzSxxPCNwdlCG84bER0BmdwqbF6Tanv+FxMOav rahkj4wIy5k=
zigi@ZIGI:~$ dig @8.8.8.8 com DNSKEY +short
256 3 13 o6onp+t66olg3PFhuIXaaatogT3OrqHrqt48IkYGuxwW8tSnQVMGyO+T Smp8sTRtkD9km+N/VQvvtqVM8ra9/Q==
257 3 13 tx8EZRAd2+K/DJRV0S+hbBzaRPS/G6JVNBitHzqpsGlz8huE61Ms9ANe 6NSDLKJtiTBqfTJWDAywEp1FCsEINQ==
zigi@ZIGI:~$ dig @8.8.8.8 cloudflare.com DNSKEY +short
257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+ KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==
256 3 13 oJMRESz5E4gYzS/q6XDrvU1qMPYIjCWzJaOau8XNEZeqCYKD5ar0IRd8 KqXXFJkqmVfRvMGPmM1x8fGAa2XhSA==

이어서 DS도 같은 순서로 조회해봅니다.

dig com DS +short
dig cloudflare.com DS +short

com의 DS는 Verisign이 IANA에 제출한 값이고, cloudflare.com의 DS는 레지스트라를 거쳐 등록된 값입니다.

출처는 다르지만 형식은 동일합니다.

 

DNSKEY에서 DS를 직접 계산해보기

DS가 정말로 KSK 공개키의 해시인지 검산할 수 있습니다.

dig cloudflare.com DNSKEY > key.txt
dnssec-dsfromkey -2 -f key.txt cloudflare.com

출력된 값을 dig cloudflare.com DS +short 결과와 비교하면 일치합니다. 

 

루트 트러스트 앵커 확인

IANA가 공개하는 앵커 값은 아래에서 받을 수 있습니다.

https://data.iana.org/root-anchors/root-anchors.xml

파일 안의 <Digest> 값과 dig . DNSKEY +short로 받은 KSK를 dnssec-dsfromkey로 계산한 값이 일치하는지 확인해보면, 리졸버가 1단계에서 수행하는 대조가 어떤 것인지 체감할 수 있습니다.

 

10. 참고 자료 (Reference Links)

여기까지 DNSSEC의 구성과 동작, 생성 절차를 모두 다뤘습니다. 다음 편에서는 지금까지의 내용을 하나로 모아, 클라이언트가 도메인 하나를 조회할 때 실제로 어떤 패킷이 오가는지를 처음부터 끝까지 추적해보겠습니다. 어떤 값을 어디서 받아 무엇과 대조하는지가 전부 드러나게 됩니다.