Skip to content
Published on

DNS 완전 정복: 네임서버, DDNS, nslookup 실전 가이드 — 도메인 등록부터 트러블슈팅까지

Authors

1. DNS 동작 원리 완전 이해

DNS란? 인터넷의 전화번호부

DNS(Domain Name System)는 사람이 읽을 수 있는 도메인 이름(예: www.example.com)을 컴퓨터가 이해하는 IP 주소(예: 93.184.216.34)로 변환하는 시스템입니다. 1983년 Paul Mockapetris가 RFC 882, 883에서 처음 제안했고, 현재는 RFC 1034, 1035가 기본 명세입니다.

DNS가 없다면 우리는 모든 웹사이트에 접속할 때 IP 주소를 직접 입력해야 합니다. DNS는 인터넷 인프라의 가장 기본적이면서도 가장 중요한 구성 요소입니다.

사용자 입력: www.example.com
DNS Resolution
IP 주소: 93.184.216.34
서버에 HTTP 요청

DNS 계층 구조: Root에서 Subdomain까지

DNS는 트리 구조의 계층적 분산 데이터베이스입니다. 최상위에서 하위로 내려가며:

          .  (Root)
         / \
      com   org   net   kr   jp  ...   (TLD - Top Level Domain)
       |
    example                             (SLD - Second Level Domain)
     / \
   www  mail  api                       (Subdomain)

계층별 역할:

계층예시관리 주체
Root (.).ICANN / IANA
TLD.com, .kr, .org레지스트리 (Verisign, KISA 등)
SLDexample.com도메인 소유자
Subdomainwww.example.com도메인 소유자

FQDN(Fully Qualified Domain Name)은 마지막에 점(.)을 포함합니다: www.example.com.

DNS 쿼리 흐름: 재귀적 vs 반복적

DNS 해석은 두 가지 방식이 조합되어 동작합니다.

재귀적 쿼리 (Recursive Query): 클라이언트가 재귀 리졸버에게 "최종 답을 알려줘"라고 요청합니다. 리졸버가 모든 일을 대신 처리합니다.

반복적 쿼리 (Iterative Query): 재귀 리졸버가 각 네임서버에게 "이 도메인 아는 사람 누구야?"라고 물어보면, 네임서버는 "나는 모르지만 저기 물어봐"라고 다음 서버를 안내합니다.

[사용자 PC] → 재귀적 쿼리 → [재귀 리졸버 (ISP/8.8.8.8)]
                                    |
                              반복적 쿼리 시작
                                    |
                    ┌───────────────┼───────────────┐
                    ↓               ↓               ↓
             [Root Server]   [TLD Server]   [Authoritative NS]
             "com은 여기"    "example.com     "IP93.x.x.x"
                             은 여기"

전체 흐름 상세:

  1. 사용자가 브라우저에 www.example.com 입력
  2. 브라우저 캐시 확인 → OS 캐시 확인 → hosts 파일 확인
  3. OS가 설정된 재귀 리졸버(예: 8.8.8.8)에 재귀적 쿼리 전송
  4. 재귀 리졸버가 캐시 확인 → 없으면 Root 서버에 반복적 쿼리
  5. Root 서버: ".com TLD 서버는 a.gtld-servers.net이야"
  6. 재귀 리졸버가 TLD 서버에 쿼리
  7. TLD 서버: "example.com의 네임서버는 ns1.example.com이야"
  8. 재귀 리졸버가 권한 있는 네임서버에 쿼리
  9. 권한 있는 네임서버: "www.example.com의 IP는 93.184.216.34야"
  10. 재귀 리졸버가 결과를 캐싱하고 클라이언트에 응답

13개 Root 서버와 Anycast

전 세계 DNS의 시작점인 Root 서버는 이름상 13개(A~M)이지만, Anycast 기술 덕분에 실제로는 1,700개 이상의 인스턴스가 전 세계에 분산되어 있습니다.

Root 서버운영 기관인스턴스 수 (대략)
AVerisign10+
BUSC-ISI6+
CCogent10+
DUniversity of Maryland200+
ENASA300+
FISC300+
JVerisign200+
KRIPE NCC100+
LICANN200+
MWIDE Project10+

Anycast란? 같은 IP 주소를 여러 물리적 서버에 할당하는 기술입니다. 사용자의 쿼리는 BGP 라우팅을 통해 가장 가까운 인스턴스로 자동 전달됩니다. 이 덕분에 Root 서버 IP는 13개뿐이지만 전 세계 어디서나 빠른 응답이 가능합니다.

DNS 캐싱: 성능의 핵심

DNS 캐싱은 여러 레벨에서 이루어집니다:

[브라우저 캐시][OS 캐시][재귀 리졸버 캐시][각 네임서버 응답의 TTL]

Chrome: chrome://net-internals/#dns 에서 확인 가능
Windows: ipconfig /displaydns
Linux: systemd-resolve --statistics
macOS: sudo dscacheutil -flushcache

TTL (Time To Live) 이해:

example.com.    3600    IN    A    93.184.216.34
              TTL = 3600 (1시간)

TTL 값에 따른 전략:

TTL 값용도장점단점
60초DNS 변경 예정 시빠른 전파쿼리 증가, 응답 느림
300초 (5분)일반적인 서비스균형 잡힌 선택-
3600초 (1시간)안정적 서비스빠른 응답, 쿼리 감소변경 반영 느림
86400초 (1일)거의 변하지 않는 레코드최고 성능긴급 변경 어려움

실전 팁: DNS 변경 전에 TTL을 60초로 낮추고, 변경이 완전히 전파된 후 다시 올리세요.


2. 네임서버 심화

권한 있는(Authoritative) vs 재귀(Recursive) 네임서버

구분Authoritative NSRecursive Resolver
역할특정 도메인의 최종 정보 보유클라이언트 대신 DNS 트리 순회
데이터존 파일의 원본 데이터캐시된 데이터
예시ns1.cloudflare.com8.8.8.8 (Google DNS)
운영 주체도메인 소유자/호스팅 업체ISP, Google, Cloudflare
응답 플래그AA (Authoritative Answer) 비트 설정AA 비트 없음

Primary(Master) vs Secondary(Slave) 네임서버

권한 있는 네임서버는 다시 Primary와 Secondary로 나뉩니다.

[Primary NS] ──Zone Transfer──→ [Secondary NS]
  (읽기/쓰기)                     (읽기 전용)

  원본 존 파일 관리                Primary 장애 시 백업
  레코드 추가/수정/삭제            부하 분산 역할

왜 Secondary가 필요한가?

  • 고가용성: Primary 장애 시 Secondary가 응답
  • 부하 분산: 쿼리를 분산 처리
  • 지리적 분산: 사용자와 가까운 곳에 배치
  • RFC 2182 권장: 최소 2개의 네임서버 운영

존 전송 (Zone Transfer): AXFR vs IXFR

Primary에서 Secondary로 존 데이터를 복제하는 방식입니다.

방식설명용도
AXFR전체 존 파일 전송초기 동기화, 데이터 불일치 시
IXFR변경분만 전송일반적인 증분 업데이트
# AXFR 테스트 (보안상 외부에서는 차단되어야 함)
dig @ns1.example.com example.com AXFR

# SOA 레코드의 Serial로 동기화 여부 확인
dig @ns1.example.com example.com SOA +short
# 2024032301 ns1.example.com. admin.example.com. ...

SOA 레코드의 Serial 번호: 관례적으로 YYYYMMDDNN 형식을 사용합니다 (예: 2026032301). Serial이 증가하면 Secondary가 존 전송을 시작합니다.

글루 레코드(Glue Record)의 필요성

도메인 example.com의 네임서버가 ns1.example.com일 때 순환 참조 문제가 발생합니다:

Q: example.com의 IP?
→ example.com의 네임서버는 ns1.example.com
→ ns1.example.com의 IP?
→ example.com의 네임서버에게 물어봐야 하는데...
→ 순환 참조 발생!

해결: 글루 레코드

상위 TLD 서버에 네임서버의 IP를 직접 등록합니다:

;; .com TLD 서버의 위임 레코드
example.com.    IN    NS    ns1.example.com.
example.com.    IN    NS    ns2.example.com.

;; 글루 레코드 (Additional Section)
ns1.example.com.    IN    A    203.0.113.1
ns2.example.com.    IN    A    203.0.113.2

주요 DNS 소프트웨어

소프트웨어유형특징
BIND9권한/재귀 겸용가장 오래된 DNS 서버. 전체 기능 지원
PowerDNS권한 전용DB 백엔드 지원 (MySQL, PostgreSQL)
CoreDNS권한/재귀Go 기반, 플러그인 아키텍처, K8s 기본 DNS
Unbound재귀 전용가볍고 보안 중심, DNSSEC 검증 기본
Knot DNS권한 전용고성능, 현대적 설계
dnsmasq경량 캐싱소규모 네트워크/홈 라우터용

CoreDNS in Kubernetes

Kubernetes 1.13부터 CoreDNS가 기본 DNS 서버입니다. Pod 내에서 서비스 이름으로 통신할 수 있는 것이 CoreDNS 덕분입니다.

# CoreDNS Corefile 예시
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}

K8s DNS 해석 규칙:

# Pod에서 서비스 접근 시
my-service                          → my-service.default.svc.cluster.local
my-service.other-ns                 → my-service.other-ns.svc.cluster.local
my-service.other-ns.svc.cluster.local → 완전한 FQDN

# Pod의 /etc/resolv.conf
nameserver 10.96.0.10          # CoreDNS ClusterIP
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5                # (.) 5개 미만이면 search 도메인 추가

ndots:5의 의미: api.example.com은 점이 2개이므로(5 미만) K8s는 먼저 api.example.com.default.svc.cluster.local 등을 시도합니다. 이것이 외부 DNS 해석을 느리게 만들 수 있어, 외부 도메인은 FQDN(마지막에 . 추가)으로 지정하는 것이 좋습니다.


3. DNS 레코드 타입 총정리

핵심 레코드 타입

타입용도예시
AIPv4 주소 매핑example.com. IN A 93.184.216.34
AAAAIPv6 주소 매핑example.com. IN AAAA 2606:2800:220:1::
CNAME별칭 (다른 도메인으로 포인팅)www.example.com. IN CNAME example.com.
MX메일 서버 지정example.com. IN MX 10 mail.example.com.
TXT텍스트 정보 (SPF, DKIM 등)example.com. IN TXT "v=spf1 ..."
NS네임서버 지정example.com. IN NS ns1.example.com.
SOA존 권한 정보시리얼, 리프레시, 만료 등
SRV서비스 위치_sip._tcp.example.com. IN SRV 10 60 5060 sip.example.com.
CAA인증서 발급 권한example.com. IN CAA 0 issue "letsencrypt.org"
PTR역방향 조회 (IP→도메인)34.216.184.93.in-addr.arpa. IN PTR example.com.
NAPTRURI 변환 규칙SIP, ENUM에서 사용

CNAME의 제약사항

# OK - 서브도메인에 CNAME
www.example.com.    IN    CNAME    example.com.

# BAD - 루트 도메인(Apex)CNAME 사용 불가!
# example.com.       IN    CNAME    other.com.    (RFC 위반)

# 해결: ALIAS/ANAME (비표준) 또는 Cloudflare의 CNAME Flattening

왜 Apex에 CNAME을 쓸 수 없는가? CNAME은 해당 이름의 다른 모든 레코드와 공존할 수 없습니다. 하지만 Apex 도메인에는 반드시 SOA, NS 레코드가 존재해야 하므로 CNAME과 충돌합니다.

이메일 인증 3총사: SPF, DKIM, DMARC

이메일 스팸과 피싱을 방지하기 위한 3가지 DNS 기반 인증 체계입니다.

SPF (Sender Policy Framework):

example.com.  IN  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.0/24 -all"
메커니즘의미
include:domain해당 도메인의 SPF도 허용
ip4:CIDR해당 IP 대역 허용
a도메인의 A 레코드 IP 허용
mxMX 레코드의 IP 허용
-all위 목록 외 모두 거부
~all위 목록 외 소프트 실패

DKIM (DomainKeys Identified Mail):

selector1._domainkey.example.com.  IN  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEB..."

메일 서버가 이메일에 전자 서명을 추가하고, 수신 서버가 DNS의 공개키로 검증합니다.

DMARC (Domain-based Message Authentication, Reporting, and Conformance):

_dmarc.example.com.  IN  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com; pct=100"
정책의미
p=none모니터링만 (보고서 수집)
p=quarantine의심스러운 메일 스팸함으로
p=reject인증 실패 메일 거부

실전 존 파일 예시 (BIND 형식)

$TTL 3600
$ORIGIN example.com.

@       IN  SOA   ns1.example.com. admin.example.com. (
                  2026032301  ; Serial (YYYYMMDDNN)
                  3600        ; Refresh (1시간)
                  900         ; Retry (15)
                  1209600     ; Expire (2)
                  86400       ; Minimum TTL (1)
                  )

; 네임서버
@       IN  NS    ns1.example.com.
@       IN  NS    ns2.example.com.

; A 레코드
@       IN  A     203.0.113.10
www     IN  A     203.0.113.10
api     IN  A     203.0.113.20

; AAAA 레코드
@       IN  AAAA  2001:db8::10

; CNAME
blog    IN  CNAME example.github.io.
docs    IN  CNAME readthedocs.io.

; MX 레코드 (우선순위 낮은 숫자가 높은 우선순위)
@       IN  MX    10 mail.example.com.
@       IN  MX    20 mail2.example.com.
mail    IN  A     203.0.113.30

; TXT 레코드
@       IN  TXT   "v=spf1 include:_spf.google.com -all"
_dmarc  IN  TXT   "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"

; SRV 레코드
_sip._tcp  IN  SRV  10 60 5060 sip.example.com.

; CAA 레코드
@       IN  CAA   0 issue "letsencrypt.org"
@       IN  CAA   0 issuewild "letsencrypt.org"

4. 도메인 등록/이전 실전 가이드

도메인 등록 구조

[ICANN] ──관리──→ [레지스트리] ──위임──→ [레지스트라] ──판매──→ [리셀러]
                  (Verisign)        (가비아, Namecheap)    (호스팅 업체 등)

레지스트리(Registry): TLD 전체를 관리 (: .com은 Verisign)
레지스트라(Registrar): ICANN 인가를 받아 도메인 등록을 대행
리셀러(Reseller): 레지스트라의 재판매 파트너

한국 레지스트라 비교

레지스트라.com 연간 비용.kr 연간 비용특징
가비아약 16,500원약 18,700원국내 최대, 부가 서비스 풍부
후이즈약 15,400원약 17,600원가격 경쟁력
카페24약 14,300원약 16,500원호스팅 연동 편리
Hosting.kr약 12,100원약 14,300원최저가 지향

해외 레지스트라 비교

레지스트라.com 연간 비용특징
Cloudflare Registrar약 10.11 USD원가 판매, 마크업 없음
Namecheap약 8.88 USD (첫해)갱신가 상승 주의
Porkbun약 9.73 USD가성비 좋음
Google Domains서비스 종료 → Squarespace 이관2023년 종료

Cloudflare Registrar를 추천하는 이유:

  • 도매가(원가) 그대로 판매 (마크업 0)
  • 갱신가도 동일
  • 무료 DNSSEC, Whois Privacy
  • Cloudflare CDN/보안 연동 용이

도메인 이전(Transfer) 절차

1. 현재 레지스트라에서 Transfer Lock(도메인 잠금) 해제
2. Auth Code(인증 코드 / EPP 코드) 발급
3. 새 레지스트라에서 Transfer 신청 + Auth Code 입력
4. 기존 레지스트라의 승인 메일 확인 (5~7일 대기)
5. 이전 완료 후 DNS 설정 확인

주의사항:
- 등록/이전 후 60일간 재이전 불가 (ICANN 60-Day Lock)
- 만료 15일 이내의 도메인은 이전 불가
- .kr 도메인은 별도 절차 (KISA 규정)

Whois와 RDAP

# Whois 조회
whois example.com

# RDAP (Whois 후속, JSON 기반)
curl -s "https://rdap.verisign.com/com/v1/domain/example.com" | jq .

RDAP(Registration Data Access Protocol)의 장점:

  • 표준화된 JSON 응답
  • HTTPS로 보안 전송
  • 국제화(IDN) 지원
  • 차등 접근 제어 가능

5. DDNS (Dynamic DNS) 완전 가이드

DDNS가 필요한 이유

가정용 인터넷은 대부분 유동 IP를 할당받습니다. ISP가 주기적으로(또는 라우터 재시작 시) IP를 변경하기 때문에, 고정 IP 없이는 집에서 서버를 운영하기 어렵습니다.

문제:
  집 서버 IP: 211.xxx.xxx.100 (어제)
  집 서버 IP: 211.xxx.xxx.200 (오늘)IP 변경됨!

  DNS: myserver.example.com211.xxx.xxx.100 (어제 등록)
  → 접속 불가!

해결 (DDNS):
  IP 변경 감지 → 자동으로 DNS 레코드 업데이트
  myserver.example.com211.xxx.xxx.200 (자동 갱신)

DDNS 서비스 비교

서비스무료커스텀 도메인업데이트 간격특징
DuckDNS무료X (*.duckdns.org만)실시간완전 무료, 오픈소스
No-IP무료(30일 갱신)유료5분3개 무료 호스트명
Cloudflare DDNS무료O (자체 도메인)실시간API로 직접 구현 필요
Synology DDNS무료X (*.synology.me)실시간Synology NAS 전용
Dynu무료O (4개까지)실시간IPv6 지원

실전 셋업 1: ddclient (Linux)

# 설치
sudo apt install ddclient

# /etc/ddclient.conf 설정 (Cloudflare 예시)
protocol=cloudflare
use=web, web=https://api.ipify.org
zone=example.com
login=your-email@example.com
password=your-cloudflare-api-token
myserver.example.com

# 서비스 시작
sudo systemctl enable ddclient
sudo systemctl start ddclient

# 상태 확인
sudo systemctl status ddclient
sudo ddclient -query

실전 셋업 2: Cloudflare API로 DDNS 직접 구현

#!/bin/bash
# cloudflare-ddns.sh

# 설정
CF_API_TOKEN="your-api-token-here"
CF_ZONE_ID="your-zone-id-here"
CF_RECORD_NAME="myserver.example.com"
CF_RECORD_ID="your-record-id-here"

# 현재 공인 IP 확인
CURRENT_IP=$(curl -s https://api.ipify.org)

# DNS에 등록된 IP 확인
DNS_IP=$(dig +short "$CF_RECORD_NAME" @1.1.1.1)

# IP가 변경되었으면 업데이트
if [ "$CURRENT_IP" != "$DNS_IP" ]; then
    echo "IP changed: $DNS_IP -> $CURRENT_IP"

    curl -s -X PUT \
        "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$CF_RECORD_ID" \
        -H "Authorization: Bearer $CF_API_TOKEN" \
        -H "Content-Type: application/json" \
        --data "{\"type\":\"A\",\"name\":\"$CF_RECORD_NAME\",\"content\":\"$CURRENT_IP\",\"ttl\":60,\"proxied\":false}"

    echo "DNS updated successfully"
else
    echo "IP unchanged: $CURRENT_IP"
fi
# crontab에 등록 (5분마다 실행)
crontab -e
# */5 * * * * /home/user/cloudflare-ddns.sh >> /var/log/ddns.log 2>&1

실전 셋업 3: Docker + DDNS 자동 업데이트

# docker-compose.yml
version: '3'
services:
  cloudflare-ddns:
    image: oznu/cloudflare-ddns:latest
    restart: always
    environment:
      - API_KEY=your-cloudflare-api-token
      - ZONE=example.com
      - SUBDOMAIN=myserver
      - PROXIED=false
      - RRTYPE=A
      - DELETE_ON_STOP=false
      - DNS_SERVER=1.1.1.1
docker-compose up -d

홈서버 운영: DDNS + Let's Encrypt + Nginx Proxy Manager

[인터넷][공유기 포트포워딩][Nginx Proxy Manager][서비스들]
                                        |
                                  Let's Encrypt
                                  자동 SSL 발급
# docker-compose.yml - 홈서버 스택
version: '3'
services:
  nginx-proxy-manager:
    image: jc21/nginx-proxy-manager:latest
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
      - '81:81' # 관리 패널
    volumes:
      - ./npm-data:/data
      - ./npm-letsencrypt:/etc/letsencrypt

  cloudflare-ddns:
    image: oznu/cloudflare-ddns:latest
    restart: always
    environment:
      - API_KEY=your-cf-token
      - ZONE=example.com
      - SUBDOMAIN=home

포트포워딩 + 방화벽 설정

공유기 설정:
  외부 80 → 내부 192.168.1.100:80
  외부 443 → 내부 192.168.1.100:443

Linux 방화벽 (UFW):
  sudo ufw allow 80/tcp
  sudo ufw allow 443/tcp
  sudo ufw enable

보안 주의사항:

  • 22번(SSH) 포트는 외부에 절대 개방하지 마세요 (VPN 또는 Tailscale 사용)
  • 관리 패널(81번)도 외부 차단
  • fail2ban으로 브루트포스 방어
  • Cloudflare Proxy를 켜면 원본 IP 노출 방지

6. nslookup 완전 활용법

기본 사용법

# 기본 조회
nslookup example.com
# Server:  8.8.8.8
# Address: 8.8.8.8#53
#
# Non-authoritative answer:
# Name:    example.com
# Address: 93.184.216.34

# 특정 DNS 서버로 조회
nslookup example.com 1.1.1.1

레코드 타입별 조회

# MX 레코드 (메일 서버)
nslookup -type=mx gmail.com
# gmail.com  mail exchanger = 5 gmail-smtp-in.l.google.com.
# gmail.com  mail exchanger = 10 alt1.gmail-smtp-in.l.google.com.

# AAAA 레코드 (IPv6)
nslookup -type=aaaa google.com

# TXT 레코드 (SPF, DKIM 등)
nslookup -type=txt example.com

# NS 레코드 (네임서버)
nslookup -type=ns example.com

# SOA 레코드 (존 정보)
nslookup -type=soa example.com

# CAA 레코드 (인증서 발급 권한)
nslookup -type=caa example.com

# SRV 레코드 (서비스 위치)
nslookup -type=srv _sip._tcp.example.com

# ANY (모든 레코드 - 일부 서버는 차단)
nslookup -type=any example.com

대화형 모드

nslookup
> server 8.8.8.8          # DNS 서버 변경
> set type=mx              # 레코드 타입 설정
> gmail.com                # 조회
> set type=txt
> example.com
> set debug                # 디버그 모드 ON
> example.com              # 상세 정보 출력
> set d2                   # 더 상세한 디버그
> exit

역방향 조회 (PTR)

# IP → 도메인 조회
nslookup 8.8.8.8
# 8.8.8.8.in-addr.arpa  name = dns.google.

nslookup 1.1.1.1
# 1.1.1.1.in-addr.arpa  name = one.one.one.one.

실전 예제 10가지

# 1. 특정 도메인의 네임서버 확인
nslookup -type=ns example.com

# 2. 메일 서버 확인 (이메일 문제 디버깅)
nslookup -type=mx company.com

# 3. SPF 레코드 확인 (이메일 스팸 문제)
nslookup -type=txt example.com

# 4. Google DNS vs Cloudflare DNS 비교
nslookup example.com 8.8.8.8
nslookup example.com 1.1.1.1

# 5. IPv6 주소 확인
nslookup -type=aaaa facebook.com

# 6. 와일드카드 서브도메인 테스트
nslookup nonexistent-sub.example.com

# 7. CAA 레코드 확인 (SSL 인증서 발급 전)
nslookup -type=caa example.com

# 8. 역방향 DNS 확인 (IP 소유자 파악)
nslookup 203.0.113.1

# 9. CNAME 체인 추적
nslookup -type=cname www.example.com

# 10. SOA 레코드로 DNS 관리자 확인
nslookup -type=soa example.com

7. dig 명령어 마스터리

dig vs nslookup 차이점

항목dignslookup
출력상세 (섹션별 구분)간략
DNSSEC지원 (+dnssec)미지원
추적지원 (+trace)미지원
배치 모드지원 (-f)미지원
설치bind-utils/dnsutils대부분 기본 설치
권장DevOps/SRE간단한 확인

기본 사용법

# 기본 조회
dig example.com

# 출력 구조:
# ;; QUESTION SECTION:    ← 질문
# ;example.com.           IN  A
#
# ;; ANSWER SECTION:      ← 응답
# example.com.      3600  IN  A  93.184.216.34
#
# ;; AUTHORITY SECTION:   ← 권한 있는 네임서버
# example.com.      3600  IN  NS  a.iana-servers.net.
#
# ;; ADDITIONAL SECTION:  ← 추가 정보
# a.iana-servers.net. 3600 IN  A  199.43.135.53
#
# ;; Query time: 23 msec
# ;; SERVER: 8.8.8.8#53(8.8.8.8)

자주 쓰는 옵션

# 짧은 출력 (IP만)
dig +short example.com
# 93.184.216.34

# 특정 레코드 타입
dig example.com MX
dig example.com AAAA
dig example.com TXT
dig example.com NS
dig example.com SOA
dig example.com CAA

# 특정 DNS 서버 지정
dig @8.8.8.8 example.com
dig @1.1.1.1 example.com

# 응답 시간만 확인
dig example.com | grep "Query time"
# ;; Query time: 23 msec

Root부터 추적: +trace

# DNS 해석 전체 과정을 Root부터 추적
dig +trace example.com

# 출력 (요약):
# .                   518400  IN  NS  a.root-servers.net.  ← Root
# com.                172800  IN  NS  a.gtld-servers.net.  ← TLD
# example.com.         86400  IN  NS  a.iana-servers.net.  ← Authoritative
# example.com.          3600  IN  A   93.184.216.34        ← 최종 답

이것은 DNS 트러블슈팅에서 가장 유용한 명령 중 하나입니다. 어느 단계에서 문제가 발생하는지 정확히 알 수 있습니다.

DNSSEC 검증

# DNSSEC 서명 정보 확인
dig +dnssec example.com

# DNSSEC 유효성 검증
dig +sigchase +trusted-key=/etc/trusted-key.key example.com

# DNSSEC 관련 레코드 직접 조회
dig example.com DNSKEY
dig example.com DS
dig example.com RRSIG
dig example.com NSEC

배치 조회

# domains.txt 파일의 모든 도메인 한 번에 조회
cat domains.txt
# example.com
# google.com
# github.com

dig -f domains.txt +short

# 특정 레코드 타입으로 배치 조회
dig -f domains.txt MX +short

고급 옵션

# TCP 모드로 조회 (UDP 대신)
dig +tcp example.com

# 응답의 특정 섹션만 출력
dig +noall +answer example.com    # 응답만
dig +noall +authority example.com  # 권한 섹션만
dig +noall +stats example.com     # 통계만

# TTL 포함 축약 출력
dig +nocmd +noall +answer +ttlid example.com

# 역방향 조회
dig -x 8.8.8.8
# 8.8.8.8.in-addr.arpa.  IN  PTR  dns.google.

# CHAOS 클래스로 DNS 서버 버전 확인
dig @ns1.example.com version.bind CHAOS TXT

# EDNS Client Subnet 테스트
dig +subnet=203.0.113.0/24 example.com @8.8.8.8

실전 예제 15가지

# 1. 특정 네임서버에서 권한 있는 응답 확인
dig @ns1.example.com example.com +norecurse

# 2. DNS 전파 확인 (여러 DNS 서버 비교)
for dns in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
  echo "=== $dns ==="
  dig @$dns example.com +short
done

# 3. CNAME 체인 전체 추적
dig +trace +nodnssec www.example.com CNAME

# 4. MX 레코드 우선순위 확인
dig example.com MX +short | sort -n

# 5. SPF 레코드 확인
dig example.com TXT +short | grep spf

# 6. DKIM 레코드 확인
dig selector1._domainkey.example.com TXT +short

# 7. DMARC 정책 확인
dig _dmarc.example.com TXT +short

# 8. CAA 레코드 확인 (SSL 발급 전)
dig example.com CAA +short

# 9. SOA 레코드의 시리얼 번호 확인 (존 전송 동기화)
dig example.com SOA +short

# 10. 응답 시간 비교 (DNS 성능 테스트)
for i in $(seq 1 10); do
  dig example.com @8.8.8.8 | grep "Query time"
done

# 11. IPv6 레코드 확인
dig example.com AAAA +short

# 12. 와일드카드 DNS 확인
dig random-subdomain.example.com +short

# 13. NSEC/NSEC3 레코드로 DNSSEC 부정 존재 증명
dig nonexistent.example.com NSEC

# 14. DNS 응답 크기 확인 (DDoS 증폭 테스트)
dig example.com ANY +bufsize=4096

# 15. 전체 존 내보내기 시도 (보안 감사)
dig @ns1.example.com example.com AXFR

8. DNS 보안

DNS 공격 유형

1. DNS Cache Poisoning (캐시 오염)

정상: 리졸버 → Authoritative NS → 정확한 IP
공격: 공격자가 가짜 응답을 리졸버 캐시에 주입
결과: 사용자가 피싱 사이트로 유도됨

방어: DNSSEC, 랜덤 소스 포트, 0x20 인코딩

2. DNS Amplification DDoS

공격 방식:
1. 공격자가 피해자 IP로 소스 주소를 위조 (IP Spoofing)
2. 오픈 리졸버에 큰 응답을 유발하는 쿼리 전송 (ANY 타입)
3. 작은 쿼리 → 큰 응답 = 증폭 효과 (50~70)
4. 모든 응답이 피해자에게 집중

방어: BCP38(소스 주소 검증), RRL(Response Rate Limiting)

3. DNS Hijacking

방식 1: 라우터/ISP 수준에서 DNS 응답 변조
방식 2: 레지스트라 계정 탈취 → 네임서버 변경
방식 3: 악성코드가 시스템 DNS 설정 변경

방어: DNSSEC, 레지스트라 계정 2FA, DNS 모니터링

4. DNS Tunneling

목적: DNS 프로토콜을 악용하여 데이터 유출/원격 제어
방식: DNS 쿼리/응답에 인코딩된 데이터를 숨김

: malicious-data.encoded.evil.com 으로 TXT 쿼리
→ 방화벽은 정상 DNS 트래픽으로 인식

방어: DNS 쿼리 길이/빈도 모니터링, DNS 방화벽

DNSSEC 동작 원리

DNSSEC은 DNS 응답의 무결성과 출처를 암호학적으로 검증합니다.

신뢰의 체인 (Chain of Trust):
  Root (.).com → example.com

  각 레벨에서:
  1. DNSKEY: 존의 공개키
  2. RRSIG: 각 레코드의 전자 서명
  3. DS: 하위 존의 공개키 해시 (상위 존에 저장)
  4. NSEC/NSEC3: "이 이름은 존재하지 않음"의 증명
# DNSSEC 검증 확인
dig +dnssec example.com

# 응답에 'ad' 플래그가 있으면 DNSSEC 검증 성공
# flags: qr rd ra ad; QUERY: 1, ANSWER: 2

# DNSKEY 조회
dig example.com DNSKEY +short

# DS 레코드 조회 (상위 존에서)
dig example.com DS +short

DNS over HTTPS (DoH) / DNS over TLS (DoT)

기존 DNS는 평문 UDP/TCP로 전송되어 ISP나 네트워크 관리자가 DNS 쿼리를 열람/조작할 수 있습니다.

프로토콜포트암호화특징
일반 DNS53 (UDP/TCP)없음도청/조작 가능
DoT853 (TCP)TLS전용 포트로 차단 가능
DoH443 (HTTPS)HTTPSHTTPS 트래픽에 숨어 차단 어려움
DoQ853 (QUIC)QUIC최신, 낮은 지연
# DoH로 DNS 조회 (curl)
curl -s -H "accept: application/dns-json" \
  "https://1.1.1.1/dns-query?name=example.com&type=A" | jq .

# DoH 서비스
# Cloudflare: https://1.1.1.1/dns-query
# Google: https://dns.google/dns-query
# Quad9: https://dns.quad9.net/dns-query

# DoT 테스트 (kdig 사용)
kdig -d @1.1.1.1 +tls-ca +tls-host=cloudflare-dns.com example.com

DNS Filtering: Pi-hole, NextDNS, AdGuard Home

[디바이스][DNS 필터][허용된 쿼리만 통과][인터넷]
                 |
           광고/악성 도메인 차단
           트래커 차단
           성인 콘텐츠 필터링
솔루션유형특징
Pi-hole자체 호스팅Raspberry Pi에서 운영, 네트워크 전체 적용
NextDNS클라우드월 30만 쿼리 무료, 설정 간편
AdGuard Home자체 호스팅DoH/DoT 지원, 웹 UI

기업용: DNS Firewall과 RPZ

RPZ (Response Policy Zone):
  DNS 방화벽에서 특정 도메인에 대한 응답을 재정의하는 기술

예시 (BIND RPZ):
; rpz.db
evil-domain.com        CNAME  .           ; NXDOMAIN 응답
malware-c2.com         CNAME  .           ; 차단
phishing-site.com      A      10.0.0.1    ; 경고 페이지로 리다이렉트

9. 실전 트러블슈팅 10가지 시나리오

시나리오 1: 도메인 등록했는데 접속이 안 됨 (전파 지연)

증상: 도메인을 등록하고 A 레코드를 설정했는데 브라우저에서 접속이 안 됩니다.

원인: DNS 전파(Propagation)는 전 세계 DNS 서버의 캐시가 갱신되는 데 최대 48시간이 소요됩니다.

# 진단
# 1. 권한 있는 네임서버에서 직접 확인 (이것이 되면 설정은 정상)
dig @ns1.your-dns-provider.com yourdomain.com A +short

# 2. 여러 공개 DNS로 전파 상태 확인
dig @8.8.8.8 yourdomain.com +short
dig @1.1.1.1 yourdomain.com +short
dig @9.9.9.9 yourdomain.com +short

# 3. 온라인 도구로 전 세계 전파 확인
# https://www.whatsmydns.net/

해결:

  • 기다립니다 (최대 48시간, 보통 1~4시간)
  • 로컬 DNS 캐시 강제 삭제: ipconfig /flushdns (Windows) 또는 sudo dscacheutil -flushcache (macOS)
  • 사전에 TTL을 낮게 설정했다면 더 빠르게 전파됩니다

시나리오 2: SSL 인증서 발급 실패 (CAA 레코드)

증상: Let's Encrypt로 SSL 인증서를 발급하려는데 실패합니다.

# 진단: CAA 레코드 확인
dig yourdomain.com CAA +short
# 0 issue "digicert.com"   ← Let's Encrypt가 허용 목록에 없음!

# 해결: CAA 레코드 추가 또는 수정
# yourdomain.com. IN CAA 0 issue "letsencrypt.org"
# yourdomain.com. IN CAA 0 issuewild "letsencrypt.org"

# CAA 레코드가 없으면 모든 CA가 발급 가능 (기본값)
dig yourdomain.com CAA +short
# (빈 응답 = 제한 없음)

시나리오 3: 이메일이 스팸함으로 감 (SPF/DKIM/DMARC)

증상: 발송한 이메일이 수신자의 스팸함으로 들어갑니다.

# 진단 1: SPF 레코드 확인
dig yourdomain.com TXT +short | grep spf
# "v=spf1 include:_spf.google.com -all"

# 진단 2: DKIM 레코드 확인 (selector는 이메일 헤더에서 확인)
dig google._domainkey.yourdomain.com TXT +short

# 진단 3: DMARC 정책 확인
dig _dmarc.yourdomain.com TXT +short
# "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"

# 해결 체크리스트:
# 1. SPF에 메일 발송 서버 IP/도메인 포함 확인
# 2. DKIM 서명 키 등록 확인
# 3. DMARC 정책 설정 (처음엔 p=none으로 모니터링)
# 4. DMARC 보고서 분석 후 p=quarantine → p=reject 순서로 강화

시나리오 4: 서브도메인이 작동하지 않음

증상: api.example.com은 되는데 staging.example.com은 안 됩니다.

# 진단: 해당 서브도메인 레코드 존재 여부 확인
dig staging.example.com A +short
# (빈 응답 = 레코드 없음)

dig api.example.com A +short
# 203.0.113.20  (정상)

# 와일드카드 레코드 확인
dig *.example.com A +short

해결:

  • 해당 서브도메인의 A/CNAME 레코드를 명시적으로 추가
  • 또는 와일드카드(*.example.com) 레코드 설정
  • 와일드카드는 명시적 레코드보다 우선순위가 낮음을 기억하세요

시나리오 5: DNS 변경 후 일부 사용자만 접속 불가 (TTL 캐시)

증상: DNS 레코드를 변경했는데, 어떤 사용자는 새 서버로 접속하고 어떤 사용자는 이전 서버로 접속합니다.

# 진단: 각 DNS 서버의 캐시 상태 확인
dig @8.8.8.8 example.com +short    # Google DNS
dig @1.1.1.1 example.com +short    # Cloudflare DNS
dig @168.126.63.1 example.com +short  # KT DNS

# TTL 확인
dig example.com | grep -A1 "ANSWER SECTION"
# example.com.  1800  IN  A  203.0.113.10
#                ↑ 남은 TTL이 아직 높음

해결:

  • TTL 시간만큼 기다립니다
  • 다음부터는 DNS 변경 24시간 전에 TTL을 60초로 낮추세요
  • 변경 완료 후 TTL을 원래 값으로 복구

시나리오 6: nslookup은 되는데 브라우저 접속 불가

증상: nslookup example.com은 정상 응답하는데 Chrome에서 접속이 안 됩니다.

# 진단 1: hosts 파일 확인
cat /etc/hosts          # Linux/macOS
type C:\Windows\System32\drivers\etc\hosts  # Windows

# 진단 2: 브라우저 DNS 캐시 확인
# Chrome: chrome://net-internals/#dns → Clear host cache

# 진단 3: HSTS 문제 확인
# Chrome: chrome://net-internals/#hsts
# 도메인 삭제 후 재시도

# 진단 4: 프록시/VPN 설정 확인
# 브라우저 프록시 설정이 DNS를 우회할 수 있음

# 진단 5: DNS over HTTPS 설정 확인
# Chrome 설정 → 개인 정보 보호 및 보안 → 보안 DNS 사용

시나리오 7: 도메인 이전 후 DNS 끊김

증상: 도메인을 다른 레지스트라로 이전한 후 사이트가 다운되었습니다.

# 진단: 현재 네임서버 확인
dig example.com NS +short
# 이전 레지스트라의 네임서버가 보이면 아직 업데이트 안 됨

# 해결 순서:
# 1. 새 레지스트라에서 DNS 레코드를 먼저 설정
# 2. 이전 전에 모든 레코드를 새 곳에 복제
# 3. 네임서버 변경
# 4. 이전 네임서버는 최소 48시간 유지

예방법: 이전 전에 반드시 새 레지스트라에 모든 DNS 레코드를 먼저 설정하세요.

시나리오 8: K8s 내부 DNS 해석 실패 (CoreDNS, ndots)

증상: Pod에서 외부 도메인(api.external.com)에 접속이 안 되거나 매우 느립니다.

# 진단 1: Pod 내에서 DNS 해석 테스트
kubectl exec -it debug-pod -- nslookup api.external.com

# 진단 2: resolv.conf 확인
kubectl exec -it debug-pod -- cat /etc/resolv.conf
# nameserver 10.96.0.10
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5

# 진단 3: CoreDNS 로그 확인
kubectl logs -n kube-system -l k8s-app=kube-dns

# 문제: ndots:5 때문에 api.external.com (점 2개)이
# api.external.com.default.svc.cluster.local 등을 먼저 시도

해결:

# 방법 1: FQDN 사용 (마지막에 점 추가)
# 코드에서 api.external.com. 으로 호출

# 방법 2: Pod의 dnsConfig 설정
apiVersion: v1
kind: Pod
spec:
  dnsConfig:
    options:
      - name: ndots
        value: '2'

시나리오 9: CDN 연동 후 원본 서버 IP 노출 (DNS Leak)

증상: Cloudflare를 사용 중인데 원본 서버 IP가 노출되어 DDoS 공격을 직접 받습니다.

# 진단: 프록시되지 않는 레코드 확인
# Cloudflare 대시보드에서 주황색 구름(프록시 활성)이 아닌
# 회색 구름(DNS Only) 레코드가 있는지 확인

# 서브도메인 스캔으로 노출 여부 확인
dig direct.example.com +short     # 원본 IP 노출?
dig mail.example.com +short       # MX용 A레코드에 원본 IP?
dig ftp.example.com +short        # FTP 서브도메인에 원본 IP?

해결:

  • 모든 A/AAAA 레코드에 Cloudflare 프록시 활성화
  • MX에 필요한 A 레코드는 별도 IP 사용
  • 원본 IP가 이미 노출되었다면 서버 IP를 변경
  • 과거 DNS 기록 확인: SecurityTrails, DNS History 등에 원본 IP가 남아있을 수 있음

시나리오 10: DDNS 업데이트가 반영되지 않음

증상: DDNS 서비스를 설정했는데 IP가 변경되어도 DNS가 업데이트되지 않습니다.

# 진단 1: 현재 공인 IP 확인
curl -s https://api.ipify.org

# 진단 2: DNS에 등록된 IP 확인
dig myserver.example.com +short

# 진단 3: DDNS 클라이언트 로그 확인
sudo journalctl -u ddclient -n 50

# 진단 4: API 토큰 유효성 확인
curl -s -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
  -H "Authorization: Bearer YOUR_TOKEN" | jq .

# 일반적인 원인:
# 1. API 토큰 만료 또는 권한 부족
# 2. Zone ID 또는 Record ID 오류
# 3. 방화벽이 DDNS 클라이언트의 외부 통신 차단
# 4. cron 작업이 비활성화됨
# 5. IP 확인 서비스(ipify 등) 접속 불가

10. DNS 서비스 비교표

관리형 DNS 서비스

서비스무료 플랜관리 DNSDDNSDNSSECDDoS 방어가격 (유료)
CloudflareO (무제한)OAPI로 구현O (무료)O무료~엔터프라이즈
AWS Route 53XOXOO (Shield)월 0.50 USD/존
Google Cloud DNSXOXOO월 0.20 USD/존
Azure DNSXOXO (프리뷰)O월 0.50 USD/존
NS1무료 티어OOOO커스텀
Dyn (Oracle)XOOOO커스텀

퍼블릭 DNS 리졸버

서비스PrimarySecondaryDoHDoTDNSSEC 검증특징
Google DNS8.8.8.88.8.4.4OOO가장 널리 사용
Cloudflare1.1.1.11.0.0.1OOO가장 빠름
Quad99.9.9.9149.112.112.112OOO악성 도메인 차단
OpenDNS208.67.222.222208.67.220.220OXO필터링 옵션
AdGuard DNS94.140.14.1494.140.15.15OOO광고 차단

추천 시나리오별 선택

시나리오추천 서비스이유
개인 블로그/사이트Cloudflare (무료)무료 DNS + CDN + SSL
스타트업Cloudflare Pro 또는 Route 53확장성 + 안정성
대기업Route 53 + Cloudflare멀티 DNS + 지연 기반 라우팅
홈서버Cloudflare + DDNS무료 + 동적 IP 지원
K8s 클러스터CoreDNS + External-DNS자동화된 DNS 관리

실전 퀴즈

Q1: DNS 쿼리에서 재귀적(Recursive) 쿼리와 반복적(Iterative) 쿼리의 차이는?

재귀적 쿼리: 클라이언트가 재귀 리졸버에게 최종 답을 요청합니다. 리졸버가 모든 중간 과정을 대신 처리하고 최종 IP 주소를 돌려줍니다.

반복적 쿼리: 재귀 리졸버가 각 단계의 네임서버(Root, TLD, Authoritative)에게 순서대로 질의합니다. 각 서버는 최종 답 대신 "다음에 물어볼 서버"를 안내합니다.

일반적으로 클라이언트 → 리졸버는 재귀적, 리졸버 → 네임서버들은 반복적 쿼리를 사용합니다.

Q2: 루트 도메인(Apex)에 CNAME 레코드를 설정할 수 없는 이유는?

RFC에 따르면 CNAME은 해당 이름에 대한 유일한 레코드여야 합니다. 즉, CNAME이 있으면 같은 이름에 다른 레코드(A, MX, NS, SOA 등)가 존재할 수 없습니다.

하지만 루트 도메인에는 반드시 SOA와 NS 레코드가 있어야 하므로, CNAME과 공존할 수 없어 설정이 불가능합니다.

대안으로 Cloudflare의 CNAME Flattening이나 일부 DNS 제공자의 ALIAS/ANAME 레코드를 사용할 수 있습니다.

Q3: TTL을 60초로 설정했는데 DNS 변경이 48시간이 지나도 반영되지 않는 이유는?

가능한 원인:

  1. TTL을 낮추기 전의 캐시가 아직 남아있을 수 있습니다. TTL 변경 자체도 이전 TTL 시간만큼 전파가 필요합니다.
  2. 일부 ISP DNS 서버는 자체적으로 최소 TTL을 강제합니다 (예: 최소 300초).
  3. 클라이언트의 OS나 브라우저 캐시가 DNS를 자체적으로 캐시합니다.
  4. 네임서버 자체를 변경한 경우, TLD 레벨에서 전파에 최대 48시간이 소요됩니다.

해결: DNS 변경 24시간 전에 TTL을 미리 낮춰두고, 변경 후에는 ipconfig /flushdns 등으로 로컬 캐시를 삭제합니다.

Q4: DNSSEC는 DNS 쿼리를 암호화하는 기술인가?

아닙니다. DNSSEC는 DNS 응답의 **무결성(Integrity)**과 **출처(Authenticity)**를 검증하는 기술이지, 암호화(Encryption) 기술이 아닙니다.

DNSSEC으로 보호된 DNS 응답도 여전히 평문으로 전송됩니다. 즉, DNS 쿼리 내용은 네트워크에서 여전히 볼 수 있습니다.

DNS 쿼리의 암호화(프라이버시)를 원하면 DNS over HTTPS(DoH) 또는 DNS over TLS(DoT)를 사용해야 합니다.

정리하면:

  • DNSSEC = 응답 위변조 방지 (무결성)
  • DoH/DoT = 쿼리 암호화 (프라이버시)
  • 둘 다 사용하면 최적의 보안
Q5: K8s Pod에서 외부 도메인 api.external.com에 접속이 느린 이유와 해결 방법은?

원인: Kubernetes의 기본 DNS 설정에서 ndots:5로 인해, 점(.)이 5개 미만인 도메인은 search 도메인을 먼저 추가하여 조회합니다.

api.external.com은 점이 2개이므로, 실제 쿼리 순서는:

  1. api.external.com.default.svc.cluster.local (NXDOMAIN)
  2. api.external.com.svc.cluster.local (NXDOMAIN)
  3. api.external.com.cluster.local (NXDOMAIN)
  4. api.external.com. (성공)

3번의 불필요한 쿼리 후에야 실제 해석이 됩니다.

해결 방법:

  1. FQDN 사용: api.external.com. (마지막에 점 추가)
  2. Pod의 dnsConfig에서 ndots를 낮은 값(예: 2)으로 설정
  3. 자주 접근하는 외부 도메인은 CoreDNS에 캐싱 규칙 추가

참고 자료

RFC 문서

  • RFC 1034 - Domain Names - Concepts and Facilities
  • RFC 1035 - Domain Names - Implementation and Specification
  • RFC 2136 - Dynamic Updates in the DNS (DDNS)
  • RFC 2181 - Clarifications to the DNS Specification
  • RFC 2308 - Negative Caching of DNS Queries
  • RFC 4033, 4034, 4035 - DNS Security Extensions (DNSSEC)
  • RFC 6698 - DNS-Based Authentication (DANE/TLSA)
  • RFC 7208 - SPF (Sender Policy Framework)
  • RFC 7489 - DMARC
  • RFC 8484 - DNS over HTTPS (DoH)
  • RFC 7858 - DNS over TLS (DoT)
  • RFC 8659 - DNS Certification Authority Authorization (CAA)

도구 및 서비스

  • dig / nslookup - DNS 조회 명령줄 도구
  • whatsmydns.net - 글로벌 DNS 전파 확인
  • dnschecker.org - DNS 레코드 확인
  • mxtoolbox.com - 이메일 DNS 진단 (SPF, DKIM, DMARC)
  • securitytrails.com - DNS 히스토리 조회
  • dnsviz.net - DNSSEC 시각화 및 검증

DNS 소프트웨어

학습 자료

  • Cloudflare Learning Center - DNS 개념 (learning.cloudflare.com)
  • howdns.works - DNS 동작 시각적 설명
  • messwithdns.net - DNS 실습 환경
  • Julia Evans - DNS 관련 블로그 및 zines