8장 : DNS
DNS 레코드와 실습
DNS 서버가 도메인에 대한 정보를 저장한다는 것을 알았습니다. 그 정보가 구체적으로 어떤 형태인지, 그리고 직접 조회하는 방법을 살펴보겠습니다.
주요 DNS 레코드 유형
DNS 레코드는 도메인 이름에 연결된 데이터입니다.
┌────────────────────────────────────────────┐
│ DNS 리소스 레코드 (RR) │
├──────────┬──────┬──────┬──────┬────────────┤
│ NAME │ TTL │ CLASS│ TYPE │ RDATA │
├──────────┼──────┼──────┼──────┼────────────┤
│ example │ 86400│ IN │ A │ 93.184.216 │
│ .com │ │ │ │ .34 │
├──────────┼──────┼──────┼──────┼────────────┤
│ example │ 86400│ IN │ AAAA │ 2606:2800: │
│ .com │ │ │ │ 220:1:: │
├──────────┼──────┼──────┼──────┼────────────┤
│ example │ 86400│ IN │ MX │ 10 mail. │
│ .com │ │ │ │ example.com│
└──────────┴──────┴──────┴──────┴────────────┘
NAME: 도메인 이름
TTL: 캐시 유효 기간 (초)
CLASS: 거의 항상 IN (Internet)
TYPE: 레코드 유형
RDATA: 실제 데이터가장 자주 사용되는 레코드 유형을 정리합니다.
| 레코드 | 용도 | 예시 | 비고 |
|---|---|---|---|
| A | 도메인 → IPv4 | example.com → 93.184.216.34 | 가장 기본 |
| AAAA | 도메인 → IPv6 | example.com → 2606:2800:220:1:: | IPv4의 4배 = AAAA |
| CNAME | 도메인 → 도메인 | www → example.com | 별칭, 루트에 불가 |
| MX | 메일 서버 지정 | 10 mail.example.com | 우선순위 숫자 포함 |
| NS | 권한 서버 지정 | ns1.example.com | 위임에 사용 |
| TXT | 텍스트 정보 | v=spf1 include:... | 검증, 이메일 보안 |
| SRV | 서비스 위치 | _sip._tcp 5060 sip.ex.com | 프로토콜+포트 |
| SOA | 영역 시작 | ns1.ex.com admin.ex.com | 영역 메타데이터 |
| PTR | IP → 도메인 (역방향) | 34.216.184.93 → example.com | 역방향 DNS |
| CAA | 인증서 발급 허가 | 0 issue letsencrypt.org | HTTPS 보안 |
CNAME은 다른 레코드와 공존 불가
example.com CNAME lb.amazonaws.com ← 루트 도메인에 불가!
example.com MX mail.example.com ← MX가 이미 있으므로
이유: CNAME은 "이 이름의 모든 것은 저쪽을 따른다"는 의미
→ 같은 이름에 MX, NS 등이 존재하면 모순
대안 (비표준이지만 널리 사용)
ALIAS / ANAME 레코드
example.com ALIAS lb.amazonaws.com ← DNS 서버가 해석 후 A 레코드로 응답
Route 53의 Alias, Cloudflare의 CNAME Flattening 등MX 레코드와 이메일 보안 레코드
MX 레코드에는 우선순위 값이 있어서, 메일 서버의 장애 대응이 가능합니다.
example.com MX 10 mail1.example.com (주 서버, 우선순위 10)
example.com MX 20 mail2.example.com (백업, 우선순위 20)
example.com MX 30 mail3.example.com (2차 백업, 우선순위 30)
메일 전송 시
1. mail1 (우선순위 10)에 먼저 시도
2. mail1 실패 → mail2 (우선순위 20)에 시도
3. mail2도 실패 → mail3 (우선순위 30)에 시도
낮은 숫자 = 높은 우선순위이메일 보안을 위한 TXT 레코드도 중요합니다.
SPF (Sender Policy Framework)
example.com TXT "v=spf1 include:_spf.google.com ~all"
→ "example.com의 메일은 Google 서버에서만 발송된다"
→ 스팸 발송자가 example.com을 사칭하는 것을 방지
DKIM (DomainKeys Identified Mail)
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIIBIj..."
→ 메일에 디지털 서명을 추가하여 변조 방지
DMARC (Domain-based Message Authentication)
_dmarc.example.com TXT "v=DMARC1; p=reject; rua=mailto:..."
→ SPF/DKIM 실패 시 정책 (none/quarantine/reject)nslookup과 dig 실습
DNS 레코드를 직접 조회해 보겠습니다.
nslookup은 Windows, macOS, Linux 모두에서 사용 가능한 기본 DNS 조회 도구입니다.
# 기본 A 레코드 조회
nslookup example.com
# 특정 레코드 유형 조회
nslookup -type=MX example.com
nslookup -type=TXT example.com
nslookup -type=NS example.com
nslookup -type=AAAA example.com
# 특정 DNS 서버를 지정하여 조회
nslookup example.com 8.8.8.8
# 역방향 DNS 조회 (IP → 도메인)
nslookup 93.184.216.34> nslookup -type=MX google.com
Server: 192.168.1.1 ← 사용된 DNS 리졸버
Address: 192.168.1.1#53 ← 리졸버 IP:포트
Non-authoritative answer: ← 캐시된 응답 (권한 서버 직접 X)
google.com mail exchanger = 10 smtp.google.com.
google.com mail exchanger = 20 smtp2.google.com.
google.com mail exchanger = 30 smtp3.google.com.
"Non-authoritative" = 리졸버 캐시에서 응답
"Authoritative" = 권한 서버에서 직접 응답dig은 더 상세한 정보를 제공하는 도구입니다.
# A 레코드 조회
dig example.com
# 특정 레코드 유형 조회
dig example.com MX
dig example.com NS
dig example.com TXT
dig example.com AAAA
# 간결한 출력 (+short)
dig +short example.com
# 93.184.216.34
# 특정 DNS 서버 지정
dig @8.8.8.8 example.com
# 역방향 DNS
dig -x 93.184.216.34> dig example.com
;; QUESTION SECTION:
;example.com. IN A ← 질문: example.com의 A 레코드
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
│ │ │ │ └── 실제 IP 주소
│ │ │ └─────── 레코드 유형
│ │ └──────────── 클래스 (Internet)
│ └──────────────────── TTL (86400초 = 24시간)
└──────────────────────────────────── 도메인 이름
;; AUTHORITY SECTION:
example.com. 86400 IN NS ns1.example.com. ← 권한 서버 정보
;; Query time: 23 msec ← 질의 소요 시간
;; SERVER: 192.168.1.1#53 ← 사용된 리졸버
;; WHEN: Mon Jan 15 14:30:00 KST 2024
;; MSG SIZE rcvd: 56 ← 응답 크기# +trace 옵션: 루트부터 최종까지 전체 경로 표시
dig +trace example.com
# 출력 예시 (간략):
# . 518400 IN NS a.root-servers.net. ← 루트
# com. 172800 IN NS a.gtld-servers.net. ← TLD
# example.com. 172800 IN NS ns1.example.com. ← 위임
# example.com. 86400 IN A 93.184.216.34 ← 최종 답TTL과 DNS 캐시 동작
DNS 응답에 포함된 TTL(Time To Live)은 해당 레코드를 캐시에 얼마나 오래 보관할 수 있는지를 초 단위로 지정합니다.
TTL이 긴 경우 (86400초 = 24시간)
장점: DNS 질의 횟수 ↓, 응답 속도 ↑
단점: 변경 사항 전파에 최대 24시간
TTL이 짧은 경우 (60초)
장점: 변경 사항 1분 내 반영
단점: DNS 서버 부하 ↑, 매번 질의 필요
실무 전략
평소: TTL = 86400 (24시간)
이전 1주전: TTL = 300 (5분으로 낮춤)
이전 당일: IP 변경 → 5분 내 전파
이전 완료: TTL = 86400 (다시 높임)import socket
import struct
def build_dns_query(domain):
"""DNS 질의 패킷 직접 생성"""
# 헤더: ID, Flags, Questions, Answers, Authority, Additional
header = struct.pack("!HHHHHH",
0x1234, # Transaction ID
0x0100, # Flags: Standard query, Recursion Desired
1, # Questions: 1
0, 0, 0 # Answers, Authority, Additional: 0
)
# 질문 섹션: 도메인을 DNS 형식으로 인코딩
question = b""
for part in domain.split("."):
question += struct.pack("B", len(part)) + part.encode()
question += b"\x00" # 도메인 종료
question += struct.pack("!HH", 1, 1) # Type: A(1), Class: IN(1)
return header + question
def send_dns_query(domain, dns_server="8.8.8.8"):
"""UDP로 DNS 질의 전송"""
query = build_dns_query(domain)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(5)
sock.sendto(query, (dns_server, 53))
response, _ = sock.recvfrom(512)
sock.close()
# 응답 파싱 (간략)
answer_count = struct.unpack("!H", response[6:8])[0]
print(f"도메인: {domain}")
print(f"DNS 서버: {dns_server}")
print(f"응답 레코드 수: {answer_count}")
print(f"응답 크기: {len(response)} bytes")
# A 레코드 IP 추출 (단순 파싱)
if answer_count > 0 and len(response) >= len(query) + 16:
offset = len(query) + 12
if offset + 4 <= len(response):
ip = socket.inet_ntoa(response[offset:offset+4])
print(f"IP 주소: {ip}")
send_dns_query("example.com")캐시는 리졸버뿐 아니라 운영체제와 브라우저에도 존재합니다. DNS 변경 후 캐시가 남아서 안 바뀐다는 문제를 겪을 때, 브라우저 캐시 → OS 캐시 → 리졸버 캐시 순으로 확인해야 합니다.
DNS 실습 체크리스트
| 상황 | 명령어 | 확인 사항 |
|---|---|---|
| 기본 IP 조회 | nslookup domain | A 레코드 IP |
| 메일 서버 확인 | dig domain MX | MX 레코드, 우선순위 |
| 네임서버 확인 | dig domain NS | 위임된 권한 서버 |
| 도메인 인증 확인 | dig domain TXT | SPF, Google 인증 |
| 해석 경로 추적 | dig +trace domain | 루트 → TLD → 권한 |
| 특정 DNS 사용 | dig @1.1.1.1 domain | 리졸버 비교 |
| 캐시 초기화 | ipconfig /flushdns | 로컬 캐시 제거 |
다음 절에서는 DNS의 심화 활용과 실무에서 마주치는 보안 이슈를 살펴보겠습니다.