DNSSEC 라이브 구축 및 유지 보수 with BIND 9

Configure DNSSEC on BIND 9 name server


0. 개요

DNS(Domain Name system)는 문자로 되어있는 "도메인 주소"를 "IP주소"로 바꾸기 위한 Application Layer 프로토콜입니다.

하지만 불행히도 인터넷 초창기 DNS가 만들어지던 시절에는 보안에 관한 인식이 그리 높지가 않아, DNS는 보안성을 고려하지 않은 채 개발되었습니다.
시간이 지남에 따라 DNS cache poisoning, DNS amplication attack 등 DNS의 취약점을 악용하는 사례가 발생하기 시작했고, 웹이나 메일 등을 사용하기 위해선 DNS가 필수임 등을 감안하면 이는 치명적인 문제가 되고 말았습니다.

DNS 취약점에 대한 피해 사례가 급증함에 따라 DNS의 보안 문제를 해결하기 위한 방안이 여럿 개발되었습니다.


DNSSEC(Domain Name System Security Extensions)은 DNS의 여러 공격 방안 중 "DNS poisoning attack"을 방지하기 위한 표준 기술입니다.

DNSSEC은 기존 DNS에 공개키 암호화 방식의 전자서명 메커니즘을 도입하여 도메인 질의응답 과정의 위/변조를 방지합니다.
DNSSEC이 적용되는 경우, authoritative 네임서버는 caching 네임서버(Resolver)에게 전자서명이 되어 있는 레코드 값을 응답함으로써 iterative 질의 과정 속에서 질의응답 데이터의 위/변조를 보호할 수 있습니다.


DNSSEC을 구축한다고 해서 모든 DNS 공격으로부터 자유로워지는 건 아닙니다.

DNSSEC은 DDos나 Amplication/Reflection 공격류 방어 메커니즘이 아니며, 사용자(Stub Resolver)의 host 변조 공격이나 phishing 공격을 방어할 수 없습니다.
또한 Caching 네임서버가 DNSSEC 검증을 수행하지 않거나, Resolver와 Stub Resolver 사이 DNS-over-TLS 및 DNS-over-HTTPS 기술이 적용되어 있지 않은 경우 역시 제3자의 공격에 노출될 수 있습니다.

만약 DNSSEC을 도입하고자 하는 경우, DNSSEC 및 자신이 관리하는 네트워크에 대한 충분한 이해가 필요합니다.


KISA(한국인터넷진흥원)에서는 DNSSEC 가이드라인을 배포하고 있습니다. DNSSEC에 관하여 자세한 정보가 필요하신 분은 https://krnic.or.kr/jsp/resources/dns/dnssecInfo/dnssecInfo.jsp 를 확인하시기 바랍니다.

추가로, KISA에서는 DNSSEC 적용 및 관리 가이드라인을 배포하고 있습니다.
https://krnic.or.kr/jsp/infoboard/library.jsp 에 들어가신 다음 "DNSSEC 도입적용 및 운영관리 가이드 배포" 글에서 확인할 수 있습니다.




1. 구축

구축 환경은 다음과 같습니다.

User

개인 PC(Windows 10 Home)


Cache DNS

CloudFlare+APNIC DNS(1.1.1.1 or 1.0.0.1)

168.126.63.1 등 일부 ISP 업체의 Cache 네임서버는 DNSSEC 검증을 수행하지 않습니다.
저는 Cloudflare와 APNIC가 합작하여 만든 Cache 네임서버 1.1.1.1을 사용하였습니다.
ncpa.cpl(윈도우), /etc/resolv.conf(리눅스)에서 설정이 가능합니다.


Master/Slave DNS

CentOS 7, BIND 9.9

Master DNS와 Slave DNS는 분리되어 있고, Master DNS 서버의 경우 Hidden으로 운영되어 외부에 노출되지 않습니다.

여러 Slave DNS 서버에서 AXFR을 이용하여 Zone 파일을 Master DNS로부터 받아간 후 authoritative 네임서버 역할을 수행합니다.

이 포스팅은 기본 BIND 설정 후 존 파일이 라이브로 반영이 되어 있는 상황을 가정합니다.

BIND9.9 이상 버전 사용을 권장합니다.


Domain Name

현재 제 개인도메인(dwer.kr)에는 DNSSEC이 적용되어 있습니다.
이 포스팅은 제 개인도메인을 배경으로 합니다.

이와 별개로 이 포스팅에서는 여러분의 이해를 돕기 위해 example.com을 예시를 들겠습니다.



구축 순서는 다음과 같습니다.

Step 1. Key 생성 (ZSK / KSK)
Step 2. BIND 설정
Step 3. Zone 서명
Step 4. 네임서버에 반영
Step 5. DS 레코드 등록
Step 6. 검증



Step 1. Key 생성 (ZSK / KSK)

DNSSEC에서 필요한 Key는 두 가지 타입이 있습니다.

1. 존 서명키(ZSK, Zone Signing Key)
2. 키 서명키(KSK, Key Signing Key)

두 Key의 가장 큰 차이점은 바로 상위 Zone과 관련이 있느냐입니다.

ZSK의 경우 언제든지 네임서버에서 교체가 가능합니다.
KSK의 경우 Key의 교체가 일어나는 경우 반드시 상위 Zone에서 DS 레코드를 업데이트를 해야 합니다.

자세한 설명은 Step 5에서 하겠습니다.


ZSK 및 KSK 파일을 생성합니다.

1
2
dnssec-keygen -3 -/dev/random -a RSASHA256 -1024 example.com.
dnssec-keygen -3 -/dev/random -a RSASHA256 -2048 -f KSK example.com.
cs


반드시 도메인명 맨 끝에 dot(.) 붙이세요!!!!!!
그리고 만들어진 Key 파일들을 모두 한 폴더에 모으시기 바랍니다.

[옵션]
-3 : NSEC3 사용을 위한 옵션(유지보수 단계에서 설명)
-r : 난수 생성을 위한 옵션입니다. 만약에 /dev/random 혹은 /dev/urandom이 없다면, 키보드로 난수를 직접 입력하셔야 합니다.
-a : 키 생성시 알고리즘을 선택합니다. 저는 RSASHA256 알고리즘을 선택했습니다. DSA, RSASHA512 등 타 알고리즘을 사용하셔도 무관합니다.
-b : key의 크기를 n bit로 지정합니다.
-f : KSK 생성시에만 옵션으로 지정합니다.

[옵션-기한]
-P : Zone에 반영할 시점
-A : 서명 시작 시점
-I : 서명 중지 시점
-D : Zone에서 삭제할 시점

ex) -I 20160401000000 -D 20160501000000  => 16/4/1에 서명을 중단하고, 16/5/1에 Zone에서 삭제


만약 기한 옵션을 선택하지 않으면 해당 Key 파일의 만료일은 없습니다. 즉 영원히 해당 Key 사용이 가능합니다.

기한 옵션을 사용하는 경우 여러 Key를 생성하되 마지막 Key는 만료일을 지정하지 않거나 만료일 부근 관리자의 조치가 필요합니다.
기한 옵션 사용시 Zone 반영 시점~서명 시작 시점, 서명 중지 시점~Zone 삭제 시점은 DNS가 안정적으로 운용될 수 있도록 충분한 시간적 여유(일주일~한달)가 필요합니다.
(Cache DNS에서 DNSKEY, RRSIG 레코드 등의 정보가 교체되는 데에 시간이 필요합니다)


KISA 권고 사항은 ZSK를 1년에 한번 교체 / KSK를 5년에 한번 교체 입니다.

Key를 정상적으로 생성하였을 경우 최소한 다음과 같이 Public Key 2개, Private Key 2개가 생성이 되어있어야 합니다. (ZSK Key 1개, KSK Key 1개 생성한 경우)





Step 2.  BIND 설정

/etc/named.conf 에 다음 항목을 추가합니다.

1
2
dnssec-enable yes;
dnssec-validation yes;
cs


/etc/named.rfc1912.zones에 다음 항목들을 업데이트해야 합니다.
(기존에 zone 등록을 해두었다고 가정)

zone "example.com" IN {
        type master;
        file "example.com.zone";

        auto-dnssec maintain;
        key-directory "KEY 폴더위치";
        inline-signing yes;
};

참고로, key-directory는 /var/named/ 안쪽에 있는 것이 좋습니다. (SELINUX 차단 가능성)


다음 2개의 옵션은 DNSSEC 반영전에도 필수적으로 있는 부분입니다.
type master;    // master DNS에서 작업하는 사안입니다.
file "example.com.zone";    // Zone 파일을 지정합니다.

다음 3개의 옵션은 DNSSEC 반영으로 인해 추가하셔야 하는 부분입니다.
auto-dnssec maintain;    // BIND에서 DNSSEC 관리
key-directory "KEY 폴더위치";    // KEY 파일이 있는 폴더 위치를 지정합니다.
inline-signing yes;    // BIND 9.9부터 지원되는 기능입니다. (유지 보수 단계에서 설명)

파일 위치는 OS나 Version 차이로 인해 일부 차이가 있을 수 있습니다.

만약 BIND 버전이 9.9 미만이면 inline-signing 기능이 제공되지 않습니다. 이 경우 inline-signing 부분을 주석처리 하시기 바랍니다. 또 file 항목을 example.com.zone 이 아닌example.com.zone.signed 을 지정하셔야 합니다.

이 포스팅도 inline-signing 적용을 기준으로 하되, 안하는 경우도 설명해드리고 있습니다.




Step 3.  Zone 서명

1
dnssec-signzone --K KEY폴더위치 -3 salt00 -o example.com. example.com.zone
cs


inline-signing 기능을 사용하시면(BIND9.9 이상),

이 명령어로 생성된 .signed 파일은 반드시 지우시기 바랍니다. (안 지우면 에러납니다)

반드시 도메인명 맨 끝에 dot(.) 붙이세요!!!!!!


[옵션]
-S : BIND가 알아서 필요한 Key 파일을 찾음. 사실상 필수 옵션.
-K : Key 파일들이 있는 폴더 위치 지정
-3 : NSEC3 chain용 salt값. 6자리 소문자 및 숫자를 임의로 지정하시면 됩니다. ex) 0a0a0a, zzz999
-o : 대상 도메인

-S 옵션이 없으면 매우 귀찮아집니다 ㅎㅎ.........
KEY 파일들이 있는 폴더 위치, 도메인명, Zone 파일 위치만 잘 맞춘다면 다음과 같은 화면이 나옵니다.



DNSKEY 레코드, RRSIG 레코드, DS 레코드 등은 BIND가 알아서 계산한 후 결과물을 .signed 파일에 저장합니다.

사용자는 example.com.zone 만 수정하고 dnssec-signzone 만 하면 됩니다.
example.com.signed 는 알아서 생성되는 파일입니다.
.signed 파일을 열어보시면 이해가 쉽습니다.



Step 4.  네임서버에 반영

1
sudo service named restart
cs


이건 어렵지 않을 거라 생각합니다 ㅎㅎ

BIND 설정이 완료되면 데몬을 재실행합니다. 의외로 이 Step을 자주 까먹습니다.


Step 5.  DS 레코드 등록

아마 많은 분들이 이 부분 때문에 저의 블로그를 찾아주시는 게 아닌가 싶네요.

어려운 단계는 아닌데, 불가능할 수 있습니다.
DNSSEC을 적용하고자 하는 도메인의 TLD, 도메인이 등록되어 있는 Registrar에 따라 달라지는 부분입니다.

그리고 반드시 수행해야 하는 절차입니다. 이 절차를 패스하면 DNSSEC은 라이브로 반영되지 않습니다.


참고) TLD는 Top-Level Domain의 약자입니다. com, net, org, kr 등이 있습니다.
참고) Registrar는 도메인 등록대행사를 의미합니다. 한국에서는 가비아, 아이네임즈, 후이즈 등이 있습니다. AWS route53, Google Domains 도 Registrar의 역할을 수행합니다.


​상위 Zone에 DS 레코드를 등록해야 DNSSEC이 정상적으로 작동합니다.

그런데 문제가 상위 Zone은 KR로 예시를 들면 b.dns.kr~g.dns.kr에 반영되어 있습니다.
즉 Registry에서 직접 관리하는 Zone을 의미합니다.
당연히 DS 레코드 등록은 자신의 DNS 서버에서 뭔가 건드리는 게 아닙니다.

참고) Registry는 TLD를 운영하는 업체/기관입니다. KR 도메인의 경우 KISA, COM 도메인의 경우 Verisign에 해당합니다.


DS 레코드를 등록하는 방법은 TLD 별로 다릅니다.
저는 수많은 TLD 중 대한민국 도메인의 대부분을 차지하고 있는 .COM, .KR을 기준으로 DS 레코드 등록법에 대해 소개해드리겠습니다.

우선 DS 레코드 값을 확인해야 하는데, DS 레코드 값은 확인하기 쉽습니다.

Zone 파일이 있는 곳에 dsset-도메인명 이라는 파일이 있을 겁니다.
해당 파일을 열면 DS 레코드 값을 확인할 수 있습니다.



DS 레코드는 "FQDN IN DS 키태그값(5자리 숫자) 알고리즘번호 Digest타입 Digest" 순으로 이루어져 있습니다.

보통 한 개의 KSK 당 2개의 DS 레코드 값이 생깁니다. ZSK와는 상관이 없습니다.
KSK 랑 DS 레코드가 붙어 다닌다고 보시면 됩니다. 즉 KSK가 변경되면 자연스레 DS 레코드 값도 변경이 됩니다.

KSK 교체하는 방법은 유지 보수 단계에서 설명해드리겠습니다.


이제 DS 레코드를 상위 Zone에 반영할 단계입니다.
KR/COM 외의 TLD의 경우 도메인을 등록하신 Registry/Registrar에게
DS 레코드 등록 방법을 문의하시기 바랍니다. (각 TLD마다 등록 방법이 다릅니다)


[COM 도메인 기준]
.com 도메인은 Registrar에서 DS 레코드 등록을 하면 됩니다. 도메인 등록 대행사의 홈페이지로 가셔서 해당 업체의 정책대로 DS 레코드를 등록하시면 됩니다.
잘 모르시는 경우 해당 업체의 담당자에게 연락하시기 바랍니다.


[KR 도메인 기준]
.kr 도메인은 Registry에 직접 DS 레코드 등록 요청을 해야 합니다.
KR 도메인의 Registry인 KISA(한국인터넷진흥원)에 등록 요청을 하셔야 합니다.

DS 레코드 값과 KSK 공개키 파일을 domop@nic.or.kr 으로 제출하시면 됩니다.
(2018-07-31 기준)

KSK 비밀키와 ZSK는 제출하지 않아도 됩니다. (KSK나 ZSK 비밀키를 KISA에 제출하시는 것도 Key 외부 유출에 해당됩니다)

이와 관련된 문의는 in_dnssec@nic.or.kr 혹은 02-405-6464로 하시면 됩니다.
KISA에서 배포하는 DNSSEC 적용 및 관리 가이드라인에 관련 내용이 적혀있습니다.



만약 특정 TLD 자체가 DNSSEC을 지원하지 않는다면, DS 레코드 등록은 불가능합니다.
(물론 그만큼 많이 쓰지 않는 TLD일 확률이 높습니다)

이 Step 이 잘 이해가 가지 않으시다면, 다음 링크를 참고해보시기 바랍니다.
https://cloud.google.com/community/tutorials/dnssec-cloud-dns-domains
https://support.dnsimple.com/articles/cloudflare-ds-record/
https://sg.godaddy.com/help/add-a-ds-record-23865



Step 6. 검증

DS 레코드 등록을 완료하셨다면 모든 과정을 다 수행하신 겁니다! 수고하셨습니다!

혹여 DNSSEC 구축에 실패하신 분들을 위해 DNSSEC이 적용되어 있는 샘플 도메인을 알려드리겠습니다.

example.com  (진짜 example.com입니다!!!!)
safedns.kr


DNSSEC이 정상인지를 확인하려면 우선 DS 레코드가 정상적으로 등록되어 있는지 확인해야 합니다.
도메인 정보 조회 서비스인 whois.kr로 들어가셔서 도메인 조회를 하시면 DS 레코드 등록 여부를 알 수 있습니다.

.KR 샘플

.COM 샘플


DS 레코드 등록에 문제가 없다면,
직접 세팅하신 파트에서 문제가 있는지를 검사해야 합니다.

다음 링크를 이용하여 검사가 가능합니다.
http://dnssec-debugger.verisignlabs.com/
http://dnsviz.net/

 DNSSEC 구축에 성공한 경우

DS 레코드 등록에 실패한 경우

DNSSEC이 잘못 적용되어 있는 경우


DS 레코드가 등록이 되어 있으나 잘못된 DNSSEC이 적용되어 있는 샘플 도메인을 알려드리겠습니다.
dnssec-failed.org (고의로 잘못된 DNSSEC을 적용한 도메인입니다)


만일

DS 레코드가 등록이 되어 있는데 DNSSEC 인증 과정에 문제가 있는 경우,

Cache DNS 서버(Resolver)는 이를 변조된 데이터로 간주하고 Client(Stub Resolver)에게 값이 없다고 전달합니다.

즉 해당 도메인에 대한 레코드들이 Zone 파일에 기재가 되어 있더라도 Client에게 제공되지 않음에 따라

DNS 서비스에 장애가 발생합니다!



단, 이렇게

DNSSEC 검증을 수행하지 않는 Cache DNS 서버(Resolver)를 사용하면,

DNSSEC 인증 과정에 문제가 있더라도 레코드 값을 전달하게 됩니다.

(1.1.1.1은 DNSSEC 검증을 수행하며, 168.126.63.1은 DNSSEC 검증을 수행하지 않습니다)




2. 유지 보수

2017.09 제가 처음 DNSSEC을 구축하고 운용하면서 삽질을 하던 기억이 납니다.
기억나는 것들을 적어봅니다.

Inline-Signing

inline-signing은 Zone 서명을 자동화하는 기능입니다.

만일 inline-signing이 지원되지 않는 BIND9.9 미만인 경우,
Zone 변경시 다음 절차를 수행해야 합니다.

1. example.zone 파일에서 필요한 부분 수정(zone 파일 수정)
2. example.zone SOA 레코드에서 serial 값을 늘림
3. bind 데몬 reload(라이브로 반영)

존 서명 후 데몬을 reload 하면 update된 serial로 slave에게 nofity 메시지가 갑니다.
-> slave DNS서버는 master에게서 새로운 Zone File을 받아갑니다.

참고로, 사용자가 관리하는 serial 값과 실제 BIND9가 관리하는 serial 값은 다릅니다.
(사용자의 serial이 100이고 현재 라이브로 적용되어 있는 serial이 102 라면,
사용자가 serial을 101로 업데이트하면 BIND가 serial 값을 103으로 자동으로 늘립니다)


만약 inline-signing을 사용함에도 불구하고, 수동으로 Zone을 변경/적용할 경우
이 Step을 진행하면 됩니다.




서명키 생성 & 관리 -> 설치 단계에서 Step 1에 해당합니다.
서명처리 -> 설치 단계에서 Step 3에 해당합니다.


Permission

Zone 파일 및 Key 파일 등은 당연히 bind가 읽을 권한이 있어야 합니다.
하지만 이외의 유저에게는 굳이 읽기 권한을 부여할 필요가 없습니다.
특히나 private Key는 유출되지 않도록 잘 관리해야 합니다.

저의 경우 다음과 같이 권한 세팅을 하였습니다.
zone 파일 -> 644, named:named
public key 파일 -> 644 named:named
private key 파일 -> 600 named:named

CentOS 7 기준으로 이렇게 세팅하시면 별도의 권한 문제는 발생하지 않습니다.

단 Zone 파일이나 Key 파일이 /var/named 밖에 있는 경우,
SELinux가 enforcing 등의 이유로 BIND 실행이 안될 수 있습니다.


RRSIG Expired Issue  (+ inline-signing)

DNSSEC을 라이브로 적용하는 경우, Zone 파일을 최소 한달에 한 번 이상 서명해야 합니다.

만약 BIND 9.9 이상으로써 inline-signing 기능을 사용하면,
BIND9가 알아서 서명을 해주기 때문에 상관 없습니다.

만약 BIND 9.9 미만으로써 inline-signing 이 적용되어 있지 않다면,
최소한 한 달에 한번 이상, 직접 Zone을 서명해야 합니다.


이유는 DNSSEC의 RRSIG 레코드에 있습니다.
RRSIG 레코드의 유효기간은 Zone 서명 후 한달입니다.

이 한달의 기간은 모든 DNSSEC 에 적용되어 있는 정책으로,
임의로 수정시 Resolver가 잘못된 DNSSEC 으로 간주합니다.


KISA - DS 레코드 등록 유지

지금도 그런지는 모르겠으나,
KISA에서 DS 레코드를 등록한 KR 도메인들을 모니터링하다가 이상을 감지하면
1. 해당 도메인 관리자에게 통보를 하거나
2. 상위 Zone에서 DS 레코드를 자동으로 삭제하는 것 같습니다.

2018.04에 제가 운영하는 네임서버 전체에 장애가 있었는데,
그때 DS 레코드가 상위 Zone에서 사라지는 일이 발생했었습니다.

담당자님께 그 이유를 물어보니 KISA의 경우
DNSSEC이 적용되어 있는 도메인들을 모니터링하다가 DNSSEC 이상을 감지하면,
DNS 장애를 방지하기 위해 자동으로 DS 레코드 삭제를 하는 프로세스가 있다고 합니다.

이 문제는 그때 KISA 담당자님께서 제 도메인에 대한 DS 레코드를 재등록해주셔서 해결했습니다.


KSK / ZSK 교체

KISA 가이드라인에 해당 내용이 상세하게 잘 나와있어 올려드립니다.


ZSK도 비슷한 느낌으로 교체하시면 됩니다.
단 ZSK 교체 시에는 DS 레코드 교체가 필요하지 않습니다.

더 간단히 요약하면
1. KSK
KSK를 생성하고 미리 Zone에 반영 -> 새로운 DS 레코드를 상위 Zone에 반영 -> 기존 DS 레코드를 상위 Zone에서 삭제 -> 기존 KSK를 Zone에서 삭제

2. ZSK
ZSK를 생성하고 미리 Zone에 반영 -> 기존 ZSK를 Zone에서 삭제

이때 Cache DNS 서버, TTL 등을 고려하여 적절한 여유 기간을 선택하시는 것이 좋습니다.


Slave 서버에서 할 일

1
2
dnssec-enable yes;
dnssec-validation yes;
cs

 Slave 서버에서 할 일은 없습니다.
왜나하면 서명된 Zone 파일이 master DNS 서버에서 오기 때문에 별도의 세팅을 수정할 필요는 없습니다.

단, DNSSEC 활성화가 되어 있지 않다면 위 항목을 /etc/named.conf 에 추가해야 합니다.


NSEC3

NSEC3 레코드는 "부재"를 의미하는 레코드입니다.
자세한 설명은 별도 포스팅을 참고하시기 바랍니다.
https://dev.dwer.kr/2020/03/nsec3-with-bind9.html




3. 후기

대부분의 도메인 관리자들이 DNSSEC을 도입하지 않기 때문에 DNS가 오염된 세상에 살고 있지만, DNSSEC이 널리 보급되어 안전하게 DNS가 사용되었으면 하네요.

기존 BIND를 운영하는 것도 분량이 만만치 않은데, DNSSEC까지 도입하니까 관리하는 양이 엄청 많아지는 느낌이네요.
그래도 저는 최소한 제 개인 도메인에 있어서는 완벽히 cache posioning 을 방지하고 싶어서 도입했습니다.
제 보잘것없는 기술력이 조금이나마 늘어난 기분은 드네요.

이상 기나긴 "BIND를 활용한 DNSSEC 라이브 구축 및 유지 보수"를 마칩니다.
긴 글 읽어주셔서 감사합니다.

댓글