- Published on
DNS Deep Dive — Resolution, Caching, DNSSEC, DoH/DoT, Anycast, 1.1.1.1 내부 완전 정복 (2025)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
TL;DR
- DNS는 계층적 분산 KV 저장소다. 도메인(
example.com) → IP(93.184.216.34) 매핑을 담당하지만 실제로는 훨씬 많은 타입의 레코드를 다룬다. - 4단계 참여자: Stub resolver (클라이언트 OS) → Recursive resolver (ISP/Cloudflare) → Root/TLD/Authoritative server.
- 재귀 vs 반복: 클라이언트는 보통 재귀 조회만, recursive resolver가 root부터 반복 조회를 대행.
- 13개 Root Server는 거짓말이다. 13개의 IP 주소이지만 각각 BGP anycast로 수백 개 인스턴스가 전 세계 분산.
- TTL과 캐싱: 모든 레코드에 유효 시간. 너무 길면 변경 반영 느림, 너무 짧으면 DNS 트래픽 폭증.
- DNSSEC: 레코드에 서명. DNSKEY → RRSIG → DS → 상위 DNSKEY → 루트 DNSKEY까지 신뢰 체인. 하지만 복잡해서 채택 느림(30% 정도).
- **DoH (DNS over HTTPS)**와 DoT (DNS over TLS): ISP의 DNS 도청과 위조를 막는 암호화. 2020년대 주류.
- 실전: Cloudflare 1.1.1.1 (Knot Resolver), Google 8.8.8.8, Cisco OpenDNS, Quad9. 각자 다른 철학과 정책.
- CoreDNS: Kubernetes의 기본 DNS. Go로 짠 플러그인 기반 서버.
1. DNS는 왜 필요한가
1.1 숫자가 싫은 인간
IP 주소는 외우기 어렵다. 93.184.216.34보다 example.com이 백 배 기억하기 쉽다. 1980년대 초까지는 어떻게 해결했나?
HOSTS.TXT 파일: SRI-NIC이 단일 텍스트 파일을 유지하며, 모든 호스트가 이 파일을 다운로드. 수백 대 컴퓨터로는 괜찮았지만 수만 대로 늘어나며 한계:
- 매일 파일 업데이트 → 전 세계 다운로드 폭주.
- 이름 충돌 → 중앙 기관이 일일이 승인.
- 네트워크 분할 → 일관성 문제.
1.2 Paul Mockapetris의 DNS (1983)
Paul Mockapetris가 RFC 882/883에서 계층적, 분산된, 캐시 기반 시스템을 제안했다. 핵심 아이디어:
- 네임스페이스의 계층화:
com,example.com,www.example.com. 각 레벨이 독립적으로 관리. - 위임: 상위가 하위 관리 권한을 "위임". 루트는 TLD 서버 주소만 안다.
- 캐싱: 한 번 조회한 결과를 TTL 동안 재사용. 대부분의 조회가 캐시에서 해결.
- UDP 기반: 빠른 stateless 쿼리. 더 커지면 TCP.
1984년 BIND(Berkeley Internet Name Domain)가 최초 구현. 놀랍게도 40년 후에도 같은 아키텍처가 작동한다.
1.3 규모
2025년 DNS 현황:
- 전 세계 일일 쿼리: ~10조 건.
- 등록 도메인: 3.5억 개.
- TLD: 1,500 개 이상(
.com,.org, ...,.app,.dev,.aws). - Cloudflare 1.1.1.1 하루 쿼리: 1조 건.
- Google 8.8.8.8 하루 쿼리: 3조 건.
이 모든 게 하나의 중앙 DB 없이 분산/캐시/위임으로 돌아간다. 20세기 가장 성공적인 분산 시스템 중 하나.
2. 네임스페이스 구조
2.1 트리
DNS는 뒤집힌 트리다:
. (root)
/ | \
com org uk (TLD)
/ | \
example wikipedia co
/ | \ /
www api mail google (2LD)
/
www
읽는 방향: www.google.co.uk. (점으로 끝, 루트까지).
.uk= TLD..co.uk= 2LD (영국의 commercial).google.co.uk= 사용자 도메인.www.google.co.uk= 서브도메인/호스트.
2.2 Zone
Zone은 관리 단위다. 특정 노드부터 아래 서브트리를 한 조직이 관리한다.
예:
- Root zone: "." — IANA가 관리, TLD 서버 목록을 가진다.
.comzone: Verisign이 관리, 등록된 모든.com도메인 정보.example.comzone: 도메인 주인이 관리,www.example.com,mail.example.com등.
한 zone 안에서는 Authoritative Name Server가 진실의 근원이다.
2.3 Delegation
부모 zone이 자식 zone에게 **"너 이 이름은 너 알아서 해"**라고 하는 것. 기술적으로 NS 레코드로 표현:
example.com. IN NS ns1.example.com.
example.com. IN NS ns2.example.com.
.com zone에 위 레코드가 있다. "example.com에 대한 질문은 ns1.example.com 또는 ns2.example.com에게 가라."
2.4 Glue Record
위 예에 모순이 있다: ns1.example.com의 IP를 알려면 example.com에 질문해야 하는데, 그걸 물어보려면 ns1.example.com의 IP가 필요하다. 무한 루프!
Glue record가 해결: 부모 zone이 자식의 NS 호스트명 + IP를 같이 제공.
example.com. IN NS ns1.example.com.
ns1.example.com. IN A 192.0.2.1 ← glue
이 A 레코드는 .com zone에 있다(비록 example.com의 이름이지만). Glue 덕분에 resolver는 추가 조회 없이 ns1의 IP를 알고 바로 물을 수 있다.
3. 참여자들
3.1 Stub Resolver
사용자 컴퓨터의 OS 구성요소. 매우 단순:
/etc/resolv.conf에 정의된 resolver 주소로 쿼리 전송.- 답변 대기.
- 애플리케이션에게 IP 반환.
대부분의 stub resolver는 재귀 조회만 요청한다 ("알아서 다 찾아서 답만 줘"). 직접 root를 건드리지 않음.
cat /etc/resolv.conf
nameserver 1.1.1.1
nameserver 8.8.8.8
macOS는 scutil, Windows는 ipconfig /all, 모바일은 시스템 설정.
3.2 Recursive Resolver (재귀 리졸버)
ISP 또는 공용 서비스(Cloudflare 1.1.1.1, Google 8.8.8.8)가 제공. 역할:
- Stub resolver로부터 쿼리 수신.
- 캐시 확인. 있으면 즉시 반환.
- 없으면 반복 조회로 답을 찾아옴 (root → TLD → authoritative).
- 결과를 캐시하고 stub에게 반환.
반복 조회가 재귀 리졸버의 핵심 일이다.
3.3 Root Server
최상위. . zone. TLD 서버 목록만 가진다.
"13개 root server"는:
- 13개의 letter: A부터 M (
a.root-servers.net~m.root-servers.net). - 각 letter는 하나의 IP 주소.
- 하지만 그 IP는 BGP anycast로 전 세계 수백 개 인스턴스가 응답.
- 예:
a.root-servers.net은 198.41.0.4인데, 이 IP는 60+ 곳에서 광고.
여러분의 ISP → 광고된 경로 중 가장 가까운 a.root-servers.net 인스턴스로 라우팅
지금 root server 총 인스턴스 수는 1,900개 이상. 사실상 "분산 CDN"이다.
3.4 TLD Server
각 TLD를 관리:
.com,.net: Verisign..org: Public Interest Registry..uk: Nominet..kr: KISA.
TLD 서버는 등록된 2LD의 NS 정보만 가진다. .com 서버에 example.com을 물으면 ns1.example.com, ns2.example.com NS 레코드와 glue를 반환.
3.5 Authoritative Server
실제 DNS 데이터를 가진 서버. 도메인 주인이 관리. 예:
- Route 53 (AWS).
- Cloud DNS (Google Cloud).
- Cloudflare DNS.
- NS1, Dyn, DNSMadeEasy (상용).
- BIND/Knot/PowerDNS 자체 호스팅.
Authoritative 서버는 캐시 없음(자기 데이터만 대답). 관리 zone의 master copy를 가진다.
4. Resolution Process
4.1 간단한 예제: www.example.com 조회
Step 1: 애플리케이션 getaddrinfo("www.example.com") 호출.
Step 2: Stub resolver가 /etc/resolv.conf의 첫 번째 서버(예: 1.1.1.1)에 쿼리 송신.
UDP 패킷, port 53
Query: www.example.com, type=A, class=IN, id=0x1234, RD=1
RD(Recursion Desired) 비트가 1이면 "재귀 조회 해줘". Stub resolver가 항상 1로 설정.
Step 3: Recursive resolver(1.1.1.1)가 캐시 확인.
Cache miss 시 반복 조회:
3.1: Root에게 질문.
1.1.1.1 → a.root-servers.net (198.41.0.4)
Query: www.example.com, type=A
Response:
ANSWER: (비어있음)
AUTHORITY:
com. IN NS a.gtld-servers.net.
com. IN NS b.gtld-servers.net.
...
ADDITIONAL (glue):
a.gtld-servers.net. IN A 192.5.6.30
...
Root는 답을 모르지만 ".com을 관리하는 서버들은 여기다"라고 알려준다.
3.2: TLD에게 질문.
1.1.1.1 → a.gtld-servers.net (192.5.6.30)
Query: www.example.com, type=A
Response:
ANSWER: (비어있음)
AUTHORITY:
example.com. IN NS a.iana-servers.net.
example.com. IN NS b.iana-servers.net.
ADDITIONAL (glue):
a.iana-servers.net. IN A 199.43.135.53
...
.com TLD 서버도 답을 모르지만 "example.com은 IANA 서버가 관리"라고.
3.3: Authoritative에게 질문.
1.1.1.1 → a.iana-servers.net (199.43.135.53)
Query: www.example.com, type=A
Response:
ANSWER:
www.example.com. IN A 93.184.216.34
AUTHORITY:
example.com. IN NS ...
드디어 답.
Step 4: Recursive resolver가 답을 stub에게 반환. 캐시에도 TTL 동안 저장.
Step 5: Stub이 애플리케이션에게 93.184.216.34 반환. connect(93.184.216.34:80).
4.2 전체 그림
App ──→ Stub Resolver ──→ Recursive Resolver
│
├──→ Root Server: "com은?"
│ ← "a.gtld-servers.net (...)"
│
├──→ a.gtld-servers.net: "example.com은?"
│ ← "a.iana-servers.net (...)"
│
├──→ a.iana-servers.net: "www.example.com의 A?"
│ ← "93.184.216.34"
│
← 93.184.216.34 (+ TTL)
4.3 캐시의 중요성
대부분의 쿼리는 Step 2에서 Recursive resolver의 캐시가 있어서 즉시 답한다. 실제로는:
- 90%+ 쿼리가 local resolver 캐시에서.
- **7%**가 1-2 hop만 거침 (
.com캐시는 보통 있음). - 3% 미만이 root까지 가는 full 반복 조회.
그래서 "하루 10조 쿼리"인데 root server는 초당 수십만 쿼리만 받는다.
5. DNS 메시지 포맷
5.1 헤더
DNS 메시지는 UDP 또는 TCP로 전송. 구조:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QDCOUNT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ANCOUNT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NSCOUNT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ARCOUNT |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ID: 16-bit 랜덤. 쿼리와 응답 매칭용.
- QR: 0 = query, 1 = response.
- AA: Authoritative Answer. 응답이 authoritative server에서 온 것.
- TC: Truncated. UDP 크기 초과 시 설정, 클라이언트는 TCP로 재시도.
- RD: Recursion Desired. 클라이언트가 재귀 조회를 원함.
- RA: Recursion Available. 서버가 재귀 조회를 지원.
- RCODE: 응답 코드. 0=NOERROR, 2=SERVFAIL, 3=NXDOMAIN, 5=REFUSED.
5.2 섹션들
- Question: 쿼리 내용.
(name, type, class)트리플. - Answer: 실제 답 레코드들.
- Authority: 권한 있는 NS 정보.
- Additional: 기타 도움 될 정보 (예: glue).
5.3 이름 압축
DNS 메시지는 가급적 512 바이트 이내여야 UDP로 편안. 그래서 이름을 압축한다:
www.example.com → 첫 등장: 전체 저장
www.example.com → 두 번째 등장: 포인터 (2 바이트, 첫 번째 위치 가리킴)
포인터는 바이트의 상위 2비트가 11인 것으로 구분. 최대 14-bit 오프셋.
5.4 EDNS(0)
기본 DNS는 UDP 512 바이트 제한. 하지만 DNSSEC이나 큰 답변은 그보다 크다. EDNS(0) (RFC 6891)가 확장을 추가:
OPT Pseudo-RR in Additional section:
UDP payload size: 4096 ← 클라이언트가 받을 수 있는 크기
Extended RCODE
Flags (DO = DNSSEC OK)
현대 리졸버는 4096 바이트 UDP 허용. 일부 방화벽이 UDP fragmenting을 막아 문제가 되기도 한다.
6. 레코드 타입
6.1 기본 타입
A: IPv4 주소.
example.com. IN A 93.184.216.34
AAAA: IPv6 주소.
example.com. IN AAAA 2606:2800:220:1:248:1893:25c8:1946
CNAME: Canonical Name. 별칭.
www.example.com. IN CNAME example.com.
주의: CNAME은 자기 도메인의 다른 레코드와 공존 못함.
NS: Name Server. zone을 관리하는 서버.
example.com. IN NS ns1.example.com.
SOA: Start of Authority. zone 메타데이터.
example.com. IN SOA ns1.example.com. admin.example.com. (
2024010101 ; serial
7200 ; refresh
3600 ; retry
1209600 ; expire
86400 ) ; minimum TTL
6.2 고급 타입
MX: Mail Exchanger. 메일 서버와 우선순위.
example.com. IN MX 10 mail1.example.com.
example.com. IN MX 20 mail2.example.com.
TXT: 자유 텍스트. SPF, DKIM, 도메인 소유 증명.
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
_dmarc.example.com. IN TXT "v=DMARC1; p=reject"
SRV: Service location. 포트와 서버 주소.
_sip._tcp.example.com. IN SRV 10 5 5060 sipserver.example.com.
PTR: Pointer. IP → 이름 역방향 조회.
34.216.184.93.in-addr.arpa. IN PTR example.com.
CAA: Certificate Authority Authorization. 어떤 CA가 이 도메인에 인증서 발급 가능한가.
example.com. IN CAA 0 issue "letsencrypt.org"
6.3 DNSSEC 타입
DNSKEY: 공개 서명 키. RRSIG: 서명. DS: Delegation Signer. 자식 DNSKEY의 해시. NSEC / NSEC3: "이 이름은 없다"의 authenticated denial.
자세한 것은 DNSSEC 섹션에서.
6.4 Generic 타입 (2020s)
HTTPS / SVCB: HTTPS connection hint. ALPN, 포트, 암호화 등 전달.
example.com. IN HTTPS 1 . alpn="h3,h2" port="443"
이로써 클라이언트는 HTTP/3 사용 여부를 DNS 조회 시점에 안다 → 첫 연결 시 h3 직접 사용. TLS 1.3 ALPN 협상 전에 힌트.
7. TTL과 캐싱
7.1 TTL의 의미
각 레코드에 "몇 초 동안 유효"가 붙는다.
www.example.com. 300 IN A 93.184.216.34
300 = 5분. Recursive resolver는 이 답을 5분간 캐시. 그 후 다시 조회.
7.2 TTL 트레이드오프
짧은 TTL (예: 60초):
- 장점: 변경 즉시 반영, 트래픽 이전 빠름.
- 단점: 리졸버 캐시 효율 저하, authoritative 서버 부하 증가.
긴 TTL (예: 86400초 = 1일):
- 장점: 캐시 효율 좋음, 부하 낮음.
- 단점: 변경 사항이 퍼지는 데 하루 걸림.
일반적 값:
- A 레코드 (일반 웹사이트): 300-3600초.
- 메일 MX: 3600-86400초.
- NS 레코드: 172800초 (2일).
- CNAME: 300-3600초.
- CDN 트래픽 관리: 30-60초 (매우 짧게).
7.3 Negative Caching
"NXDOMAIN" (도메인 없음) 응답도 캐시된다. SOA 레코드의 minimum 필드가 NXDOMAIN TTL. 너무 짧으면 무효 도메인 쿼리가 반복됨.
7.4 TTL의 함정
배포 전 TTL 줄이기 실수:
배포 1일 전: TTL을 60초로 줄임. 하지만 예전 TTL(3600)의 캐시가 아직 남음.
배포 당일: 새 IP로 변경. 하지만 3600초 된 캐시가 아직 돌아다님.
→ 일부 유저가 2시간 동안 구 서버에 접속.
올바른 순서: 배포 2일 전에 TTL 줄임 (기존 3600초 캐시 만료 후 60초로 업데이트됨) → 배포 당일 IP 변경.
8. DNSSEC
8.1 문제
기본 DNS는 아무 검증 없음. 응답이 진짜인지 위조인지 알 수 없다. 2008년 Dan Kaminsky가 DNS cache poisoning 공격을 발표 — 16-bit ID를 추측하거나 brute force로 가짜 응답 주입 가능. 전 세계가 긴급 패치.
DNSSEC (DNS Security Extensions)는 레코드에 디지털 서명을 추가한다.
8.2 개념
example.com. IN A 93.184.216.34
example.com. IN RRSIG A <서명: example.com의 ZSK로 서명>
RRSIG는 "이 레코드는 진짜다"는 보증. 서명은 ZSK (Zone Signing Key)로 생성. ZSK 자체는 DNSKEY 레코드에 있다.
example.com. IN DNSKEY 256 3 8 <ZSK 공개 키>
그리고 DNSKEY 자체도 KSK (Key Signing Key)로 서명된다. KSK의 해시는 부모 zone의 DS 레코드에 있다.
example.com. IN DS 12345 8 2 <해시>
부모(.com)의 DS는 부모의 ZSK로 서명되고, 그 DNSKEY는 부모의 KSK로 서명되고... 이렇게 루트까지 신뢰 체인이 이어진다.
8.3 신뢰 체인
루트(.)의 KSK (trust anchor — 수동 배포)
↓ 서명
루트의 ZSK
↓ 서명
com의 DS 레코드
↓ 검증
com의 KSK
↓ 서명
com의 ZSK
↓ 서명
example.com의 DS
↓ 검증
example.com의 KSK
↓ 서명
example.com의 ZSK
↓ 서명
www.example.com의 A 레코드
루트의 KSK는 "trust anchor"다. 리졸버에 수동으로 설치(시스템 업데이트로 배포). 이로써 전체 체인이 검증 가능.
8.4 Authenticated Denial: NSEC / NSEC3
"이 도메인은 없다"는 응답도 위조 방지해야 한다. 그냥 NXDOMAIN을 믿을 수 없다.
NSEC: "foo.example.com과 qux.example.com 사이에 이름 없음"을 증명. NSEC 레코드 자체도 서명되어 있다.
foo.example.com. IN NSEC qux.example.com. A AAAA RRSIG NSEC
문제: 존 워킹(zone walking) 가능. "foo 다음은 qux"라는 정보로 전체 zone의 이름을 알 수 있다 → 프라이버시 누출.
NSEC3: 이름을 해시로 저장. 해시만 공개되므로 전체 이름 목록을 쉽게 알 수 없다.
<hash1>.example.com. IN NSEC3 ... <hash2> ...
여전히 brute force로 해시를 깰 수는 있지만 훨씬 어렵다.
8.5 DNSSEC 문제
왜 30%만 채택됐는가:
- 복잡하다: 키 관리, 롤오버, 서명 만료.
- 운영 실수 치명적: 서명 만료되면 도메인이 완전 중단.
- 성능: 서명 검증이 CPU 사용. 응답 크기 증가.
- UDP fragmentation: 4KB 넘는 응답이 방화벽에 막히는 경우.
- DDoS amplification: DNSSEC 응답이 크므로 UDP spoof 공격 증폭 효과 악용.
현재 ISP 리졸버 중 ~30%만 DNSSEC 검증. 대형 공용 리졸버(1.1.1.1, 8.8.8.8, Quad9)는 모두 검증.
8.6 2018년 KSK 롤오버
루트 KSK가 교체됐다. 처음이었고, 20년 동안 도달할 수 없는 사건. 전 세계 리졸버의 trust anchor를 업데이트해야 했다. 대부분 OS 업데이트로 자동 처리됐지만 일부 오래된 시스템이 DNSSEC 전체 실패 → 인터넷 끊김.
2024년에 또 한 번의 롤오버가 예정되어 있다 (5년 주기).
9. DoH / DoT
9.1 문제
기본 DNS는 평문 UDP. 모든 사람이 볼 수 있다:
- ISP: 고객이 어떤 사이트에 접속하는지 파악 가능 → 광고 타겟팅, 정부 감시.
- WiFi 엿듣는 사람: 카페, 공항.
- 검열 회피 방해: 국가 차원의 필터링이 DNS 레벨에서 작동.
- 중간자 공격: DNS 답을 위조.
9.2 DNS over TLS (DoT, RFC 7858)
DNS 쿼리를 TLS로 감싸서 port 853으로 전송.
Client ↔ TLS handshake ↔ Resolver:853
↓
DNS query/response (encrypted)
장점:
- TLS로 암호화.
- 별도 포트(853)라 쉽게 식별 가능 → 필터링 쉬움.
Android 9 Private DNS 기능이 DoT 사용.
9.3 DNS over HTTPS (DoH, RFC 8484)
DNS 쿼리를 HTTPS POST로 감싸서 port 443으로 전송.
POST https://cloudflare-dns.com/dns-query
Content-Type: application/dns-message
<바이너리 DNS 쿼리>
또는 GET으로:
GET https://cloudflare-dns.com/dns-query?dns=<base64url>
장점:
- port 443 → HTTPS 트래픽에 섞여 필터링 매우 어려움.
- 기존 HTTPS 스택 재사용.
- 브라우저에서 직접 사용 가능.
Firefox는 기본 DoH 활성화 (Cloudflare, NextDNS). Chrome은 옵션. Windows 10 22H2+도 DoH 지원.
9.4 논쟁
찬성:
- 프라이버시 ↑.
- 검열 회피.
- 중간자 공격 방지.
반대:
- 기업 네트워크 관리자가 DNS를 통제 못함 → 악성 사이트 차단 어려움.
- 맬웨어 탐지가 어려워짐.
- 부모 통제(parental control) 우회.
많은 기업이 "사내 DoH 금지" 또는 "사내 DoH 서버로만 허용" 정책을 둔다.
9.5 ODoH (Oblivious DoH)
2020년대 초. DoH의 추가 개선: 리졸버도 클라이언트 IP를 모르게 한다.
Client → Proxy (암호화) → Resolver
↑ ↑
"누가 물었는지 알지만 "무엇을 물었는지 알지만
무엇을 물었는지 모름" 누가 물었는지 모름"
Oblivious = "잊혀진". 프록시와 리졸버가 협력하지 않으면 이용자 추적 불가. Cloudflare와 Apple이 초기 구현.
10. 1.1.1.1 내부 — Cloudflare
10.1 아키텍처
Cloudflare의 공용 리졸버 1.1.1.1은 전 세계 300+ PoP에 배포되어 있다.
User → 가장 가까운 PoP (BGP anycast) → Resolver
↓
캐시 확인
↓
반복 조회 (필요 시)
↓
응답 + 캐시 업데이트
Anycast로 같은 IP 1.1.1.1이 모든 PoP에서 광고된다. 사용자의 BGP 경로에 따라 가장 가까운 곳으로 라우팅.
10.2 Knot Resolver
Cloudflare는 오픈소스 Knot Resolver를 기반으로 한 자체 구현을 쓴다(상당 부분 개조).
Knot Resolver 특징:
- 체코 NIC Labs(
.cz관리 기관)가 개발. - 모듈형 — Lua로 확장.
- 매우 빠름(멀티코어 스케일).
- DNSSEC 기본 검증.
Cloudflare는 여기에:
- DoH/DoT 프론트엔드 추가.
- DDoS 방어 레이어.
- 로깅 최소화 (프라이버시 정책).
1.1.1.1만이 아니라1.1.1.2(맬웨어 차단),1.1.1.3(맬웨어 + 성인 콘텐츠 차단) 같은 변형.
10.3 프라이버시 약속
Cloudflare는:
- 쿼리 로그 24시간 후 삭제.
- 개인 식별 정보 저장 안 함.
- 제3자 감사 (KPMG 등).
일반 ISP가 DNS 쿼리 로그로 광고 타겟팅하는 것에 대한 대안.
10.4 8.8.8.8 — Google Public DNS
Google의 공용 리졸버. 1.1.1.1과 유사하지만 몇 가지 차이:
- Google의 자체 구현 (오픈소스 아님).
- 전 세계 anycast.
- ECS (EDNS Client Subnet) 지원 — CDN이 사용자 위치를 알게 해서 최적 서버 반환.
- DoH/DoT 지원.
- 로깅 정책은 Cloudflare만큼 엄격하지 않음.
10.5 Quad9
9.9.9.9 — 스위스 기반 비영리. 특징:
- 기본적으로 맬웨어 도메인 차단.
- GDPR 준수.
- 프라이버시 우선.
- DNSSEC 검증.
11. CoreDNS — Kubernetes의 DNS
11.1 왜 쿠버네티스에 DNS가 필요한가
K8s에서 Pod가 서비스를 찾는 방법:
curl http://my-service.default.svc.cluster.local
이 이름이 Pod의 IP로 해석돼야 한다. CoreDNS가 그 일을 한다.
11.2 CoreDNS 구조
Go로 작성, 플러그인 기반. 각 기능이 플러그인.
Corefile (CoreDNS 설정):
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
- kubernetes 플러그인: K8s API에서 service/pod 정보 읽기.
- forward: 외부 도메인은 상위 DNS로.
- cache: 응답 캐시.
- prometheus: 메트릭 expose.
11.3 Service Discovery
K8s가 my-service라는 서비스를 만들면 CoreDNS가 자동으로 레코드 생성:
my-service.default.svc.cluster.local. IN A 10.96.0.42
Pod들은 /etc/resolv.conf에 CoreDNS 주소가 있고, search default.svc.cluster.local로 축약 이름도 작동:
curl http://my-service # → my-service.default.svc.cluster.local
11.4 Headless Service
ClusterIP가 없는 서비스. DNS가 모든 Pod IP 리스트 반환:
headless-service.default.svc.cluster.local. IN A 10.244.1.5
headless-service.default.svc.cluster.local. IN A 10.244.1.6
headless-service.default.svc.cluster.local. IN A 10.244.2.3
StatefulSet에서 자주 쓰임 (각 Pod가 고유 DNS 이름).
11.5 NodeLocal DNSCache
CoreDNS를 각 노드에 로컬 캐시로 배포. Pod는 localhost의 DNS를 쿼리 → 네트워크 홉 감소 + 클러스터 DNS 부하 경감.
Pod → 127.0.0.1:53 (nodelocal) → CoreDNS 클러스터 → 외부
대규모 클러스터(수천 노드)에서 필수.
12. DNS 기반 로드 밸런싱
12.1 Round Robin DNS
가장 단순: 같은 이름에 여러 A 레코드. 리졸버가 랜덤하게 하나 반환.
api.example.com. IN A 10.0.1.1
api.example.com. IN A 10.0.1.2
api.example.com. IN A 10.0.1.3
장점: 간단. 단점: 캐시 때문에 정확한 분산 안 됨. 실패한 서버 제거 못 함(TTL까지 기다려야).
12.2 Geo DNS
사용자 위치에 따라 다른 답 반환.
사용자 (한국) → dns.example.com → 10.0.1.1 (한국 서버)
사용자 (미국) → dns.example.com → 10.0.2.1 (미국 서버)
Route 53 GeoDNS, Cloudflare Load Balancing, NS1 등이 지원.
작동 원리:
- Authoritative server가 쿼리 source IP 확인.
- GeoIP DB에서 국가/지역 조회.
- 해당 지역 서버 IP 반환.
더 정확한 버전: ECS (EDNS Client Subnet) — recursive resolver가 자기 위치 대신 실제 사용자 subnet을 authoritative에 전달.
12.3 Health-Check DNS
DNS 제공자가 주기적으로 서버 health check. 실패한 서버를 자동으로 DNS에서 빼기.
dns.example.com → 10.0.1.1 (health OK)
10.0.1.2 (FAIL — DNS에서 제외)
10.0.1.3 (health OK)
TTL을 짧게(30-60초) 해서 빠른 failover.
12.4 가중치 라우팅
api.example.com. IN A 10.0.1.1 (weight 80)
api.example.com. IN A 10.0.1.2 (weight 20)
카나리 배포에 유용: 새 버전에 트래픽 5%만 보내고 점진 증가.
13. DNS 보안 위협
13.1 Cache Poisoning
2008년 Kaminsky 공격. 16-bit ID를 추측해서 리졸버 캐시에 가짜 답을 주입.
완화:
- Source port randomization: 예전엔 53만 썼는데, 이제 랜덤 포트. 엔트로피 32-bit+16-bit.
- DNSSEC: 서명으로 검증.
- 0x20 encoding: 쿼리 이름의 대소문자를 랜덤으로 → 응답과 매칭 검증.
13.2 Amplification Attack
DDoS 기법. 작은 쿼리로 큰 응답 유도 → 피해자 IP 스푸핑.
공격자 → 56 byte 쿼리 (source IP = 피해자) → DNS 리졸버
↓
4096 byte 응답 → 피해자
70배 증폭. 피해자는 원치 않는 트래픽에 익사.
완화:
- Open resolver 없애기: 리졸버는 자기 네트워크만 답변.
- BCP38 (ingress filtering): ISP가 source IP 검증.
- Response Rate Limiting (RRL): 같은 subnet에 중복 응답 제한.
13.3 DNS Hijacking
DNS 응답을 조작해 사용자를 가짜 사이트로 유도.
- ISP의 개입: 일부 ISP가 NXDOMAIN을 자기 검색 페이지로.
- 멀웨어: 로컬
/etc/hosts또는 resolver 변경. - 정부 검열: 중국의 Great Firewall이 특정 도메인에 가짜 응답.
방어:
- DoH/DoT 사용.
- DNSSEC 검증.
- VPN 통한 우회.
13.4 Domain Generation Algorithm (DGA)
멀웨어가 알고리즘으로 매일 새 도메인을 생성 (예: abcde1234.com). C&C 서버와 통신. 차단이 어렵다 (수천 개 도메인).
방어: 텍스트 엔트로피 분석으로 DGA 도메인 탐지.
14. 실무 디버깅
14.1 dig 명령어
# 기본 A 쿼리
dig example.com
# 특정 타입
dig example.com MX
dig example.com TXT
# 특정 리졸버
dig @1.1.1.1 example.com
# 전체 경로 추적
dig +trace example.com
# DNSSEC 검증 확인
dig +dnssec example.com
# 짧은 출력
dig +short example.com
+trace는 root부터 반복 조회를 시뮬레이션. "어느 단계에서 문제 생겼는지" 파악 가능.
14.2 nslookup / host
더 단순한 도구들. 대체로 dig이 더 정보가 풍부.
host example.com
nslookup example.com
14.3 공용 조회 도구
- DNSChecker.org: 여러 국가 리졸버에서 동시 조회.
- Cloudflare DNS Checker: https://1.1.1.1/help.
- DNSViz.net: DNSSEC 신뢰 체인 시각화.
- MXToolbox: MX/SPF/DKIM/DMARC 테스트.
14.4 흔한 문제와 해결
"변경한 DNS가 반영 안 돼요":
- TTL 확인. 옛 레코드 TTL이 긴가?
- 로컬 캐시 플러시:
sudo killall -HUP mDNSResponder(macOS),ipconfig /flushdns(Windows). dig @권위서버로 직접 권위 서버에 물어보기.
"DNSSEC 에러":
dig +dnssec +cd(cd = checking disabled)로 검증 건너뛰고 답 받기.- DNSViz로 체인 확인.
- 서명 만료 자주 발생 (키 롤오버 실수).
"간헐적 timeout":
- EDNS fragmentation 문제일 수 있음.
+noedns로 테스트.- 방화벽이 UDP fragment 막는가?
15. 현대 트렌드 (2024-2025)
15.1 DoH 기본화
주요 브라우저와 OS가 DoH를 기본 또는 강력 권장. "DNS는 암호화되어야 한다"가 새 표준.
15.2 SVCB/HTTPS 레코드
HTTP/3 협상을 DNS 레벨에서. 클라이언트가 첫 연결 시 h3 사용 여부를 미리 안다.
15.3 Encrypted Client Hello (ECH)
TLS의 SNI도 암호화. 사이트 이름이 더 이상 평문으로 보이지 않음. DNS의 SVCB 레코드로 ECH 공개 키 배포.
15.4 More TLDs, IDN
.app, .dev, .aws, .microsoft 같은 브랜드 TLD 증가. IDN (International Domain Name)으로 한글/한자 도메인도.
한국.kr, 우리.한국 같은 도메인이 실제로 동작.
15.5 DNS Abuse 대응
스팸, 피싱, 멀웨어의 출발점이 주로 DNS. ICANN이 "DNS abuse" 정의 강화, 등록 기관(registrar)의 책임 확대.
16. 학습 리소스
책:
- "DNS and BIND" — Paul Albitz & Cricket Liu (고전, 5판).
- "Pro DNS and BIND 10" — Ron Aitchison.
- "Managing Mission-Critical Domains" — Mark E. Jeftovic.
RFC:
- RFC 1034, 1035: 원본 DNS.
- RFC 4033-4035: DNSSEC.
- RFC 6891: EDNS(0).
- RFC 7858: DoT.
- RFC 8484: DoH.
사이트:
- ICANN: https://www.icann.org
- IANA root zone: https://www.iana.org/domains/root
- DNS-OARC: https://www.dns-oarc.net (운영자 커뮤니티)
도구:
- dig, drill, kdig.
- DNSViz (DNSSEC 시각화).
- WireShark (DNS 프로토콜 분석).
17. 요약 — 한 장 정리
┌─────────────────────────────────────────────────────┐
│ DNS Cheat Sheet │
├─────────────────────────────────────────────────────┤
│ 계층: │
│ Root (.) → TLD (.com) → 2LD (example.com) → Host │
│ │
│ 참여자: │
│ Stub Resolver: OS 수준, 재귀 요청 │
│ Recursive Resolver: ISP/Cloudflare/Google │
│ Root Server: 13 letters, 1900+ anycast instances │
│ TLD Server: .com, .net 등 │
│ Authoritative Server: 실제 데이터 │
│ │
│ 쿼리 흐름: │
│ Stub → Recursive (cache?) → Root → TLD → Auth │
│ │
│ 주요 레코드: │
│ A: IPv4 AAAA: IPv6 │
│ CNAME: 별칭 NS: 네임서버 │
│ MX: 메일 TXT: 자유 │
│ SRV: 서비스 위치 CAA: 인증서 권한 │
│ SOA: zone 메타 │
│ DNSKEY/RRSIG/DS/NSEC: DNSSEC │
│ HTTPS/SVCB: HTTP/3 힌트 │
│ │
│ TTL: │
│ 짧음(60s): 유연, 부하 ↑ │
│ 길음(86400s): 부하 ↓, 느린 변경 │
│ 배포 시 미리 TTL 줄이기 │
│ │
│ DNSSEC: │
│ 레코드 → RRSIG (ZSK 서명) │
│ ZSK → DNSKEY → KSK 서명 │
│ KSK → 부모 DS 레코드 │
│ ... 루트까지 → 루트 KSK trust anchor │
│ NSEC/NSEC3로 denial 증명 │
│ │
│ 암호화: │
│ DoT: TLS, port 853 │
│ DoH: HTTPS, port 443 │
│ ODoH: 추가로 client IP 숨김 │
│ │
│ 공용 리졸버: │
│ 1.1.1.1 Cloudflare (프라이버시) │
│ 8.8.8.8 Google (ECS 지원) │
│ 9.9.9.9 Quad9 (맬웨어 차단) │
│ NextDNS 208.67.222.222 Cisco OpenDNS │
│ │
│ 도구: │
│ dig, drill, kdig │
│ dig +trace, +dnssec │
│ DNSViz.net │
└─────────────────────────────────────────────────────┘
18. 퀴즈
Q1. "13개 root server"라는 말이 왜 오해인가?
A. "13개의 IP 주소"가 맞지만 실제로는 1,900개 이상의 물리 서버가 있다. 각 IP(a.root-servers.net ~ m.root-servers.net)가 BGP anycast로 광고되기 때문에, 같은 IP가 전 세계 수백 개 위치에서 응답한다. 리졸버가 198.41.0.4로 질문하면 BGP 경로에 따라 가장 가까운 인스턴스로 라우팅된다. 이 덕분에 데이터센터 하나가 통째로 사라져도 DNS는 정상 작동한다. 13이 한계인 이유는 원래 UDP 512바이트 안에 "priming query" 응답이 들어가야 했기 때문이다.
Q2. 재귀(recursive) 조회와 반복(iterative) 조회의 차이는?
A. 재귀 조회: 클라이언트가 "알아서 답만 줘"라고 요청. 서버가 전체 과정을 대신 수행. Stub resolver가 ISP 리졸버에 하는 것이 재귀. 반복 조회: 클라이언트가 "너가 아는 만큼만 알려줘, 나머지는 내가 찾겠다"고 요청. Root → TLD → Auth로 한 단계씩 내려가며 직접 수행. Recursive resolver가 상위 서버들에게 하는 것이 반복 조회. 즉, Recursive resolver는 재귀 요청을 받고, 반복 조회를 수행한다.
Q3. CNAME이 같은 이름의 다른 레코드와 공존할 수 없는 이유는?
A. CNAME은 "이 이름은 다른 이름의 별칭이다"라는 의미다. 별칭이라면 모든 질문이 원본 이름으로 리다이렉트돼야 일관성이 유지된다. 만약 www.example.com에 CNAME과 A가 동시에 있다면, A를 쓰라는 건지 CNAME을 쫓아가라는 건지 애매해진다. 그래서 RFC 1034가 명시적으로 금지. 실무 함정: **zone apex(example.com 자체)**에는 SOA/NS가 반드시 있어야 해서 CNAME을 쓸 수 없다. 해결책: ALIAS, ANAME 레코드 (Route 53, Cloudflare의 독자 확장).
Q4. DNSSEC 도입이 지연되는 가장 큰 이유는?
A. 운영 복잡도와 실수 시 치명적 결과. DNSSEC은 키 관리(ZSK, KSK), 서명 만료 관리, 키 롤오버, NSEC/NSEC3 선택 등 운영 부담이 크다. 그런데 서명이 만료되거나 체인이 깨지면 도메인이 완전히 해석 불가가 된다. 반면 기본 DNS는 설정 실수가 있어도 부분적으로나마 동작한다. "위험은 크고 이득은 불확실"한 결정이라 많은 도메인 운영자가 미룬다. 또한 EDNS 4KB 응답이 일부 방화벽에 막히는 운영 이슈도 있다. 20년이 지났어도 검증률이 30% 정도에 머무는 이유.
Q5. DoT와 DoH의 주된 차이점은?
A. 포트와 프로토콜. DoT는 별도 포트 853에서 TLS 위에 DNS. 표준 DNS처럼 보이고 네트워크 관리자가 쉽게 식별/관리 가능. DoH는 port 443에서 HTTPS POST/GET으로 DNS. 일반 HTTPS 트래픽과 구분 불가 → 필터링과 검열이 매우 어렵다. 프라이버시 관점에서는 DoH가 강하지만, 기업 네트워크 관리 관점에서는 통제 불가라는 단점. Firefox는 DoH 기본, Android 9+는 DoT 기본. 둘 다 DoH/DoT 변환 proxy가 있어서 상호 운용 가능.
Q6. TTL을 변경할 때 "배포 2일 전에 줄여야 하는" 이유는?
A. 기존 캐시 때문. 현재 TTL이 1시간(3600초)이고 이를 60초로 줄이는 변경을 배포했다고 하자. 이 변경 자체가 기존 1시간 TTL 캐시가 만료된 후에야 리졸버에 도달한다. 즉 최대 1시간 동안은 옛 TTL 정보가 남아있다. 따라서 "60초 TTL이 실제로 적용"되는 시점은 변경 배포 후 최대 1시간 뒤. 배포 직전(예: 1시간 전)에 줄이면 실제 IP 변경 시 일부 리졸버가 여전히 3600초 캐시를 가진 상태. 올바른 순서: 배포 2일 전 → TTL 줄임(1일 안에 전 세계 캐시가 새 TTL로 업데이트됨) → 배포일 → IP 변경 → 60초 안에 모두 반영.
Q7. DNS Amplification 공격은 어떻게 작동하는가?
A. 공격자가 피해자의 IP로 스푸핑된 작은 DNS 쿼리를 많은 open resolver에 보낸다. 리졸버는 응답을 "쿼리 발신자"(=스푸핑된 피해자 IP)로 보낸다. DNS 응답은 쿼리보다 훨씬 클 수 있다(특히 DNSSEC enabled면 4KB). 예: 56 바이트 쿼리 → 4000 바이트 응답 = 70배 증폭. 공격자는 소량의 대역폭으로 피해자에게 거대한 트래픽을 쏟아낸다. 방어: (1) Open resolver 금지(리졸버는 자기 네트워크만 서비스), (2) BCP38(ISP가 source IP 검증으로 스푸핑 차단), (3) Response Rate Limiting으로 같은 타깃에 반복 응답 제한. 2013년 Spamhaus 공격(300Gbps), 2016년 Dyn 공격 같은 대규모 사례의 주요 기법.
이 글이 도움이 됐다면 다음 포스트도 확인해 보세요:
- "BGP 라우팅 Deep Dive" — DNS anycast가 기반하는 BGP 프로토콜.
- "TLS/SSL Deep Dive" — DoT/DoH가 사용하는 TLS와 ECH.
- "CDN & Edge Caching Strategies" — DNS 기반 CDN 라우팅의 배경.
- "HTTP/3 & QUIC Deep Dive" — HTTPS 레코드가 알려주는 h3.