작성일 :

신뢰의 문제

DNS의 원리 (2)에서 DNS 질의 과정을 살펴보았습니다. 그런데 Recursive Resolver가 받은 응답이 진짜인지 확인할 방법이 있을까요?

1983년 DNS가 설계될 때 인터넷은 소규모 연구 네트워크였고, 참여자들은 서로를 신뢰했습니다.

응답의 진위를 검증할 필요가 없었기에, DNS에는 그런 수단이 포함되지 않았습니다.

하지만 오늘날의 인터넷에서는 공격자가 DNS 응답을 조작할 수 있고, 검증 수단의 부재가 곧 취약점이 됩니다.


DNS의 보안 취약점

DNS Spoofing

DNS Spoofing은 Recursive Resolver가 Authoritative Server에 질의를 보내고 응답을 기다리는 동안, 공격자가 위조된 응답을 먼저 전송하는 공격입니다.

Recursive Resolver는 먼저 도착한 응답을 채택하므로, 뒤늦게 도착하는 정상 응답은 무시됩니다.


1
2
3
4
5
6
7
8
정상적인 경우:
Recursive Resolver ──질의──▶ Authoritative Server
                   ◀─응답──                      (정상 IP)

DNS Spoofing:
Recursive Resolver ──질의──▶ Authoritative Server
                   ◀─────── 공격자 (가짜 응답, 먼저 도착)
                   ◀─────── Authoritative Server (정상 응답, 무시됨)


DNS 프로토콜의 세 가지 구조적 특성이 이 공격을 가능하게 합니다.

  • UDP 사용: TCP와 달리 연결을 맺지 않아, 송신자를 확인하는 과정 없이 누구든 응답 패킷을 보낼 수 있음
  • 약한 트랜잭션 ID: 질의와 응답을 매칭하는 유일한 수단이 16비트 ID(65,536가지)뿐이라, 무작위로 시도하면 맞출 수 있음
  • 인증 없음: 응답에 서명이 없어, ID만 일치하면 정상 응답으로 받아들임

이 세 가지 문제에 대한 해결책은 이 글의 뒷부분에서 다룹니다. Source Port Randomization, DNSSEC 등이 대표적입니다.

Cache Poisoning

Cache Poisoning은 DNS Spoofing을 한 단계 발전시킨 공격입니다.

한 번의 응답만 위조하는 것이 아니라, Recursive Resolver의 캐시 자체를 오염시켜 이후 모든 질의에 영향을 줍니다.

DNS의 원리 (2)에서 살펴본 Additional 섹션이 공격에 사용됩니다.

Recursive Resolver는 응답의 Additional 섹션에 포함된 정보도 함께 캐시에 저장하는데, 공격자가 여기에 관련 없는 도메인의 가짜 레코드를 끼워 넣습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
공격 시나리오:

1. 공격자가 Recursive Resolver에 질의 전송
   "evil.example.com의 IP는?"

2. Recursive Resolver가 Authoritative Server에 질의
   (아직 응답을 기다리는 중)

3. 공격자가 Authoritative Server보다 먼저 가짜 응답 전송
   Answer:     "evil.example.com → 1.2.3.4"
   Additional: "www.example.com → 6.6.6.6"  ← 악성

4. Recursive Resolver가 응답을 채택하고 캐시에 저장
   www.example.com → 6.6.6.6 (오염됨)

5. 이후 www.example.com을 질의하는 모든 사용자가
   오염된 캐시를 받음


현재는 Bailiwick checking으로 일부 완화되었습니다. 질의한 도메인과 관련 없는 Additional 정보를 거부하는 규칙으로, 위 시나리오처럼 evil.example.com 질의에 www.example.com 정보가 포함되면 이를 무시합니다. 하지만 완전한 해결책은 아닙니다.

Kaminsky Attack (2008)

2008년 Dan Kaminsky가 발표한 Cache Poisoning 기법입니다.


기존 Cache Poisoning은 Recursive Resolver의 캐시에 정상 레코드가 이미 있으면, TTL이 만료될 때까지 공격할 수 없었습니다.

Kaminsky는 존재하지 않는 서브도메인으로 이 한계를 우회했습니다.

abc123.example.com처럼 존재하지 않는 이름을 질의하면 캐시에 해당 레코드가 없으므로, Recursive Resolver는 반드시 Authoritative Server에 질의를 보냅니다. 이 질의가 진행되는 동안이 DNS Spoofing을 시도할 수 있는 시간입니다.

공격이 실패하면(트랜잭션 ID를 맞추지 못하면), 정상 응답이 캐시에 저장됩니다.

같은 이름으로 다시 시도하면 캐시가 응답하므로 Authoritative Server에 질의를 보내지 않아 공격 기회가 없습니다.

하지만 random2.example.com이라는 새로운 이름을 사용하면 다시 캐시에 없는 상태가 되어, 즉시 다음 시도가 가능합니다.

이렇게 매번 다른 서브도메인을 사용하면 공격을 무한히 반복할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
공격 과정:

1. 공격자가 Recursive Resolver에 질의 전송
   "abc123.example.com의 IP는?"
   → 존재하지 않는 도메인이므로 캐시에 없음

2. Recursive Resolver가 example.com의 Authoritative Server에 질의

3. 공격자가 서로 다른 트랜잭션 ID로 가짜 응답을 대량 전송
   (65,536가지 중 하나를 맞추기 위해)
   Authority 섹션: "example.com NS = evil.attacker.com"

4. 정상 응답보다 먼저 도착하고 ID가 일치하면 성공
   → Recursive Resolver의 캐시에서
     example.com의 NS가 공격자 서버로 변경됨


Cache Poisoning은 Additional 섹션의 가짜 A 레코드로 특정 도메인의 IP를 오염시키지만, Kaminsky Attack은 Authority 섹션의 가짜 NS 레코드로 도메인 전체를 탈취합니다.


대응책 (2008년 이후):

  • Source Port Randomization: Recursive Resolver가 질의를 보낼 때 출발 포트도 랜덤화합니다. 공격자는 트랜잭션 ID(65,536가지)와 포트 번호(~65,536가지)를 동시에 맞춰야 하므로, 추측 난이도가 약 40억 분의 1로 증가합니다.
  • 0x20 인코딩: DNS는 도메인 이름의 대소문자를 구분하지 않지만, 응답할 때 질의에 사용된 대소문자를 그대로 돌려줍니다. Recursive Resolver가 wWw.ExAmPLE.coM처럼 랜덤한 대소문자 패턴으로 질의를 보내면, 정상 Authoritative Server는 같은 패턴으로 응답하지만 공격자는 어떤 패턴이 사용되었는지 모르므로 맞출 수 없습니다.
  • DNSSEC: 응답에 디지털 서명을 추가하여, 위조된 응답을 근본적으로 거부합니다.

이 대응책 중 가장 근본적인 해결책인 DNSSEC를 자세히 살펴보겠습니다.


DNSSEC

디지털 서명으로 해결

DNSSEC(DNS Security Extensions)네트워크 보안의 원리 (1)에서 설명한 비대칭 암호화를 DNS에 적용합니다.

각 Zone의 Authoritative Server가 개인키로 응답에 디지털 서명을 추가하고, Recursive Resolver가 공개키로 이 서명을 검증합니다.

공격자는 개인키를 모르므로 올바른 서명을 생성할 수 없고, 위조된 응답은 검증 단계에서 걸러집니다.

DNSSEC 레코드 타입

DNSSEC은 네 가지 새로운 레코드 타입을 추가합니다: 공개키(DNSKEY), 서명(RRSIG), Zone 간 인증(DS), 부재 증명(NSEC/NSEC3).


DNSKEY

Zone의 공개키를 담는 레코드입니다.

1
2
3
4
5
6
example.com.  IN  DNSKEY  257 3 13 (mdsswUyr3DPW...eKGQ==)
                          │   │  │
                        플래그 │  알고리즘 (ECDSA P-256)
                        (KSK) │
                          프로토콜
                        (DNSSEC 고정값)


플래그 값에 따라 키의 역할이 나뉩니다.

KSK(Key Signing Key, 플래그 257)는 다른 키를 서명하는 상위 키이고, ZSK(Zone Signing Key, 플래그 256)는 실제 레코드를 서명하는 키입니다.

두 키를 분리하는 이유는 교체(롤오버) 주기가 다르기 때문입니다. ZSK는 자주 교체하되, 부모 Zone에 등록해야 하는 KSK는 드물게 교체하여 운영 부담을 줄입니다.


RRSIG (Resource Record Signature)

레코드에 대한 디지털 서명을 담는 레코드입니다. 각 레코드 타입마다 대응하는 RRSIG가 존재합니다. 아래는 A 레코드와 그 서명입니다.

1
2
3
4
5
6
7
example.com.  IN  A     93.184.216.34      ← 서명 대상
example.com.  IN  RRSIG A 13 2 3600 (      ← 위 A 레코드의 서명
                    20260301000000          서명 만료일
                    20260201000000          서명 시작일
                    12345                   키 태그 (어떤 DNSKEY로 서명했는지)
                    example.com.            서명한 Zone
                    oJB1W6WNGv+...AfI= )    서명값


Recursive Resolver는 서명 만료일/시작일로 유효 기간을 확인하고, 키 태그로 해당 DNSKEY를 찾아 서명을 검증합니다.


DS (Delegation Signer)

부모 Zone이 자식 Zone의 공개키를 인증하는 레코드입니다. 자식의 DNSKEY를 해시한 값을 담고 있어, Recursive Resolver가 자식 Zone에서 받은 DNSKEY가 부모가 인정한 키인지 확인할 수 있습니다.

1
2
3
4
5
6
; .com Zone에 등록된 레코드
; "example.com의 DNSKEY는 이 해시와 일치해야 진짜다"
example.com.  IN  DS  12345 13 2 (49FD46E6...1AFE51DE)
                      │     │  │              │
                    키 태그  │  다이제스트 타입  DNSKEY의 해시값
                        알고리즘  (SHA-256)


NSEC/NSEC3

“질의한 이름은 존재하지 않음”을 증명하는 레코드입니다. DNSSEC는 존재하는 레코드에 서명하는 방식이므로, 존재하지 않는 이름에 대해서는 별도의 증명 방법이 필요합니다. 공격자가 “존재하지 않음”이라는 응답을 위조하여 정상 도메인의 접속을 방해할 수 있기 때문입니다.

NSEC은 Zone 내 이름을 정렬하여 인접한 이름의 쌍을 기록합니다.

1
2
3
4
5
; Zone에 alpha, beta, gamma만 존재할 때
; 누군가 "charlie.example.com"을 질의하면:
beta.example.com.  IN  NSEC  gamma.example.com. A RRSIG NSEC
; → beta와 gamma 사이에는 아무것도 없다
;    charlie는 알파벳순으로 이 구간에 속하므로 존재하지 않음


하지만 NSEC은 “다음 이름”을 직접 알려주므로, 공격자가 NSEC 레코드를 순서대로 따라가면 Zone 내 모든 도메인 이름을 수집할 수 있습니다(Zone Walking).

NSEC3는 이름 대신 해시값을 사용하여 이 문제를 완화합니다.

신뢰 체인 (Chain of Trust)

Recursive Resolver가 example.com의 DNSKEY를 받았을 때, 이 키 자체가 진짜인지 어떻게 알 수 있을까요?

부모 Zone인 .com이 DS 레코드로 보증합니다. 그러면 .com의 DNSKEY는?

루트(.)가 보증합니다. 이렇게 루트까지 거슬러 올라가는 구조가 신뢰 체인입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                    Trust Anchor
                    (미리 신뢰하는 루트 공개키)
                         │
                    ┌────▼────┐
                    │  Root   │  DNSKEY (루트 키)
                    │   .     │  DS (.com의 DNSKEY 해시)
                    └────┬────┘
                         │ 루트의 DS가 .com의 DNSKEY를 보증
                    ┌────▼────┐
                    │  .com   │  DNSKEY
                    │   TLD   │  DS (example.com의 DNSKEY 해시)
                    └────┬────┘
                         │ .com의 DS가 example.com의 DNSKEY를 보증
                    ┌────▼────┐
                    │ example │  DNSKEY
                    │  .com   │  RRSIG (각 레코드 서명)
                    └─────────┘


Trust Anchor는 이 체인의 시작점입니다.

트의 공개키가 운영체제나 Recursive Resolver에 미리 설정되어 있어, 별도의 보증 없이 신뢰합니다.

IANA가 관리하며, 2018년에 첫 키 롤오버가 수행되었습니다.

DNSSEC 검증 과정

Recursive Resolver가 www.example.com의 A 레코드를 검증하는 과정입니다.


example.com 레벨

  1. Authoritative Server로부터 A 레코드 + RRSIG를 수신
  2. example.com의 DNSKEY(ZSK)로 RRSIG 서명 검증
  3. 이 DNSKEY가 진짜인지 확인하기 위해, .com Zone의 DS 레코드에서 해시 일치 여부를 확인

.com 레벨

  1. .com의 DNSKEY(ZSK)로 DS 레코드의 RRSIG 검증
  2. .com의 DNSKEY가 진짜인지 확인하기 위해, 루트 Zone의 DS 레코드에서 해시 일치 여부를 확인

루트 레벨

  1. 루트의 DNSKEY(ZSK)로 DS 레코드의 RRSIG 검증
  2. 루트의 DNSKEY는 Trust Anchor(미리 설정된 루트 공개키)와 대조하여 최종 검증 완료


모든 단계가 성공해야 응답을 신뢰합니다. 하나라도 실패하면 SERVFAIL을 반환합니다.

DNSSEC의 한계

  • 운영 복잡성: ZSK는 수개월, KSK는 수년 주기로 롤오버해야 함. 절차를 잘못하면 서명 검증이 실패하여, 정상 도메인의 접속까지 불가능해짐
  • 응답 크기 증가: RRSIG, DNSKEY, DS 레코드가 추가되어 응답이 수 배 커짐. UDP 512바이트를 쉽게 초과하므로 EDNS0이나 TCP 폴백이 필요
  • 프라이버시 부재: 응답의 무결성은 보장하지만, 질의와 응답 자체는 평문으로 전송됨. 네트워크 경로상의 누구든 사용자가 어떤 도메인을 조회하는지 볼 수 있음

DNSSEC는 “응답이 위조되지 않았는가?”는 해결했지만, “누가 무엇을 질의하는가?”는 해결하지 못했습니다.

이 프라이버시 문제를 다루는 기술이 암호화된 DNS입니다.


암호화된 DNS

프라이버시 문제

HTTPS가 웹 콘텐츠를 암호화하더라도, 그 직전에 수행되는 DNS 질의는 평문으로 전송됩니다.

사용자가 bank.com에 접속하면 페이지 내용은 보호되지만, “bank.com의 IP를 알려달라”는 요청은 그대로 노출됩니다.


1
2
3
4
5
6
7
8
9
10
11
HTTPS로 보호되지 않는 구간:

┌──────────────┐  "bank.com의 IP는?"   ┌──────────────────┐
│ Stub Resolver │ ───────────────────▶ │ Recursive        │
│              │ ◀─────────────────── │ Resolver         │
└──────────────┘    평문 (UDP 53)      └──────────────────┘

관찰 가능한 위치:
  - 로컬 네트워크 관리자
  - ISP
  - 공용 Wi-Fi 공격자

DoT (DNS over TLS)

네트워크 보안의 원리 (2)에서 설명한 TLS를 DNS 질의에 적용한 프로토콜입니다. 전용 포트 853을 사용합니다.


  • 장점: 표준 TLS를 그대로 사용하므로 구현이 간단
  • 단점: 전용 포트(853)를 사용하므로, 네트워크 관리자가 해당 포트만 차단하면 DoT 자체가 작동하지 않음


1
2
3
4
5
6
7
DoT (포트 853):
┌──────────────┐                      ┌──────────────────┐
│ Stub Resolver │ ◀── TLS 터널 ────▶ │ Recursive        │
│              │     (TCP 853)       │ Resolver         │
└──────────────┘                      └──────────────────┘
                  DNS 질의/응답이
                  TLS 안에서 암호화됨


DoT는 주로 Stub Resolver와 Recursive Resolver 사이 구간을 암호화합니다.

Recursive Resolver와 Authoritative Server 사이에도 적용할 수 있지만, 아직 널리 보급되지는 않았습니다.

DoH (DNS over HTTPS)

DoT는 전용 포트(853)를 사용하므로 차단이 쉽다는 한계가 있었습니다.

DoH는 DNS 질의를 일반 HTTPS 트래픽에 실어 보내, 이 문제를 해결합니다.

포트 443을 사용하므로 일반 웹 트래픽과 구분할 수 없습니다.


  • 장점: 네트워크 관리자가 DoH만 선별하여 차단하기 어려움
  • 단점: TLS 위에 HTTP/2 계층이 추가되어 DoT보다 오버헤드가 큼


DoH는 GET과 POST 두 가지 방식을 지원합니다.

GET은 DNS 메시지를 Base64로 인코딩하여 URL에 포함하고, POST는 이진 DNS 메시지를 본문에 담습니다.

1
2
3
4
5
6
7
8
9
10
11
GET 방식:
GET /dns-query?dns=AAABAAAB... HTTP/2
Host: dns.google
Accept: application/dns-message

POST 방식:
POST /dns-query HTTP/2
Host: dns.google
Content-Type: application/dns-message

(이진 DNS 메시지)


주요 DoH 서버:

제공자 URL
Google https://dns.google/dns-query
Cloudflare https://cloudflare-dns.com/dns-query
Quad9 https://dns.quad9.net/dns-query

DoH vs DoT

특성 DoT DoH
포트 853 (전용) 443 (HTTPS 공용)
전송 방식 TLS 위에 DNS 직접 전송 HTTP/2 위에 DNS 전송
차단 용이성 전용 포트로 식별·차단 쉬움 웹 트래픽과 구분 불가


DoH는 차단이 어려운 대신 중앙화 우려가 있습니다.

브라우저가 특정 DoH 서버를 기본값으로 설정하면, 소수의 기업이 DNS 트래픽 대부분을 처리하게 됩니다.

ISP의 감시는 피하지만, 해당 기업이 사용자의 질의 내역을 볼 수 있다는 새로운 집중 문제가 생깁니다.

ODoH (Oblivious DoH)

DoH는 DoH 서버가 “누가 무엇을 질의했는지” 모두 알 수 있다는 한계가 있습니다.

ODoH는 프록시(Proxy)와 대상 서버(Target)를 분리하여 이 문제를 해결합니다.

Proxy는 사용자의 IP는 알지만 질의 내용을 모르고, Target은 질의 내용은 알지만 사용자의 IP를 모릅니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
일반 DoH:
Stub Resolver ──────▶ DoH 서버
                       │
                       └── 질의 내용 + IP 주소 둘 다 앎


ODoH:
Stub Resolver ──▶ Proxy ──▶ Target
                   │           │
                   │           └── 질의 내용은 알지만
                   │               IP 주소 모름 (암호화됨)
                   │
                   └── IP 주소는 알지만
                       질의 내용 모름 (암호화됨)

지금까지 DNS의 보안과 프라이버시를 다루었습니다. 다음은 수십억 사용자의 질의를 어떻게 빠르고 안정적으로 처리하는지 살펴봅니다.


현대 DNS 인프라

Anycast DNS

전 세계에서 사용되는 DNS 서버가 한 곳에만 있다면, 거리에 따른 지연과 단일 장애점 문제를 피할 수 없습니다.

Anycast는 동일한 IP 주소를 여러 물리적 위치의 서버에 할당하고, 그중 가장 가까운 서버 하나가 응답하게 하는 라우팅 방식입니다.

라우팅과 인터넷 구조 (3)에서 설명한 BGP를 활용하여, 도쿄와 LA의 서버가 모두 8.8.8.8을 광고하면 라우터는 경로가 더 짧은 쪽으로 패킷을 전달합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
                    Stub Resolver (서울)
                         │
                         │ 8.8.8.8로 질의
                         ▼
              BGP가 가장 가까운 PoP로 라우팅
                    ╱            ╲
           ┌───────────┐   ┌───────────┐
           │  도쿄 PoP │   │  LA PoP   │
           │  8.8.8.8  │   │  8.8.8.8  │
           └───────────┘   └───────────┘
                ↑
          선택됨 (더 가까움)

PoP = Point of Presence (물리적 서버 위치)


  • 지연 시간 감소: 사용자와 가까운 PoP가 응답하므로 왕복 시간이 짧아짐
  • DDoS 내성: 공격 트래픽도 여러 PoP로 분산되어, 한 PoP가 받는 부하가 줄어듦
  • 자동 장애 복구: 한 PoP가 다운되면 해당 BGP 경로가 사라지고, 트래픽이 다른 PoP로 자동 전환


DNS의 원리 (1)에서 소개한 루트 서버는 a.root-servers.net부터 m.root-servers.net까지 13개의 이름을 가지며, 각각 고유한 IP 주소가 할당되어 있습니다.

13이라는 숫자는 모든 루트 서버 주소를 DNS 응답 하나(UDP 512바이트)에 담아야 했기 때문에 생긴 제한입니다.

하지만 각 이름 뒤에서 Anycast로 여러 PoP를 운영하므로, 예를 들어 k.root-servers.net 하나만 해도 전 세계 수십 곳에서 같은 IP를 광고합니다.

13개를 모두 합하면 전 세계 수백 개 이상의 인스턴스가 동작하고 있습니다.

글로벌 로드 밸런싱

Anycast가 네트워크 계층에서 같은 IP의 가장 가까운 서버로 라우팅했다면, 글로벌 로드 밸런싱은 DNS 계층에서 작동합니다. Authoritative Server가 질의자의 위치에 따라 서로 다른 IP를 반환합니다.


1
2
3
4
5
서울에서 질의:
www.example.com.  60  IN  A  103.x.x.x   ← 도쿄 데이터센터

뉴욕에서 질의:
www.example.com.  60  IN  A  198.x.x.x   ← 뉴욕 데이터센터


지리 기반 응답(GeoDNS): Authoritative Server는 질의를 보낸 Recursive Resolver의 IP로 위치를 추정하고, 가까운 데이터센터의 IP를 반환합니다.


헬스체크 연동: 서버 상태를 주기적으로 모니터링하여, 장애가 발생한 서버의 IP를 응답에서 제거합니다. TTL을 짧게(예: 60초) 설정하면, 캐시가 만료되는 즉시 새로운 IP로 전환됩니다.

CDN과 DNS

CDN(Content Delivery Network)은 전 세계에 분산된 에지 서버가 원본 서버의 콘텐츠를 캐시하여 대신 제공하는 시스템입니다.

사용자는 멀리 있는 원본 서버 대신 가까운 에지 서버에서 콘텐츠를 받으므로 응답이 빨라집니다.

여기서 DNS의 역할은, 사용자를 가장 가까운 에지 서버로 연결하는 것입니다.

도메인 관리자가 CNAME 레코드로 자신의 도메인을 CDN 도메인에 연결하면, 이후 질의는 CDN의 Authoritative Server가 처리합니다.

CDN의 Authoritative Server는 앞서 설명한 GeoDNS와 같은 방식으로 가장 가까운 에지 서버의 IP를 반환합니다.


1
2
3
4
www.example.com.   CNAME   cdn.provider.net.
                              │
                              ▼ CDN의 Authoritative Server가 처리
cdn.provider.net.  A        103.x.x.x  ← 가장 가까운 에지 서버


CNAME Flattening: 앞의 예시에서 www.example.com은 CNAME으로 CDN에 연결할 수 있었지만, example.com 자체(Zone apex)는 그렇게 할 수 없습니다.

CNAME이 존재하면 같은 이름에 다른 레코드를 둘 수 없다는 규칙이 있습니다. 그런데 Zone apex에는 NS, SOA 등 필수 레코드가 반드시 존재하므로, CNAME을 추가하면 규칙에 위반됩니다.

CNAME Flattening은 이 제약을 우회합니다.

1
2
3
4
5
6
7
관리자가 설정:
  example.com → cdn.provider.net  (내부적으로만 기록, CNAME 레코드로 공개하지 않음)

질의가 오면:
  1. Authoritative Server가 cdn.provider.net의 IP를 자체 조회 → 103.x.x.x
  2. 클라이언트에게 반환:
     example.com.  A  103.x.x.x   ← CNAME 없이 A 레코드만 반환

클라이언트 입장에서는 일반 A 레코드와 동일하므로, CNAME 공존 규칙에 위반되지 않습니다.

DNS 기반 서비스 디스커버리

마이크로서비스 환경에서는 서비스가 여러 서버에 분산되고, 배포할 때마다 IP가 바뀔 수 있습니다.

IP를 직접 지정하면 서비스가 이동할 때마다 설정을 변경해야 하지만, DNS로 고정된 이름을 부여하면 IP가 바뀌더라도 이름은 그대로 유지됩니다.

Kubernetes는 클러스터 내부에 자체 DNS를 운영하여 이를 구현합니다.


1
2
3
4
5
6
7
8
9
10
Kubernetes 내부 DNS 이름 구조:

service-name.namespace.svc.cluster.local
│            │         │   └── 클러스터 내부 도메인
│            │         └── 서비스임을 표시
│            └── 네임스페이스 (환경 구분)
└── 서비스 이름

예: redis.production.svc.cluster.local
    → production 네임스페이스의 Redis 서비스 IP


A 레코드는 IP만 알려주지만, 하나의 서버에서 여러 서비스가 각기 다른 포트로 실행될 수 있습니다.

SRV 레코드는 IP와 포트를 함께 제공하여 이 문제를 해결합니다.

1
2
3
4
_http._tcp.web.example.com.  IN  SRV  10 0 80 server1.example.com.
                             IN  SRV  10 0 80 server2.example.com.
                                      │  │ │  └── 대상 서버
                                 우선순위 가중치 포트

지금까지 현재 운영 중인 기술들을 살펴보았습니다. 마지막으로, 표준화가 진행 중이거나 보급 초기인 기술들을 소개합니다.


DNS의 미래

DNS over QUIC (DoQ)

DoT와 DoH는 모두 TCP 기반입니다. TCP에서는 하나의 패킷이 손실되면 뒤따르는 모든 패킷이 재전송을 기다려야 합니다(Head-of-line blocking).

DoQ는 HTTP의 진화 (2)에서 설명한 QUIC을 DNS에 적용하여 이 문제를 해결합니다.


  • 포트: 853 (DoT와 동일하지만 UDP 기반)
  • TLS 1.3 내장: 별도의 TLS 핸드셰이크 없이 암호화 제공
  • 0-RTT 연결: 이전에 접속한 서버라면 첫 패킷에 질의를 포함할 수 있음
  • 독립된 스트림: 여러 질의를 동시에 보낼 때, 하나가 지연되어도 나머지에 영향 없음

HTTPS/SVCB 레코드

기존에는 웹 서버에 접속한 뒤에야 HTTP/3 지원 여부, 대체 포트, 사용 가능한 프로토콜 등을 알 수 있었습니다.

HTTPS/SVCB 레코드는 이러한 서비스 연결 정보를 DNS 조회 시점에 미리 제공하여, 불필요한 왕복을 줄입니다.


1
2
3
4
example.com.  IN  HTTPS  1 . alpn="h3,h2" ipv4hint=93.184.216.34
                              │              │
                         지원 프로토콜    서버 IP 힌트
                         (HTTP/3, HTTP/2)

Encrypted Client Hello (ECH)

DoT/DoH로 DNS 질의를 암호화하더라도, TLS 핸드셰이크 과정에서 한 가지가 여전히 노출됩니다.

클라이언트가 어떤 도메인에 접속하려는지 서버에 알리는 SNI(Server Name Indication) 필드입니다.

하나의 IP에서 여러 도메인을 호스팅할 때, 서버가 올바른 인증서를 선택하려면 이 정보가 필요한데, TLS 암호화가 시작되기 전에 전송되므로 평문으로 노출됩니다.

ECH는 이 SNI를 암호화합니다. 클라이언트가 SNI를 암호화하려면 서버의 공개키가 필요한데, 이 공개키를 DNS의 HTTPS 레코드를 통해 미리 배포합니다.


1
2
example.com.  IN  HTTPS  1 . ech="공개키" alpn="h3,h2"
                              └── 클라이언트가 SNI를 암호화하는 데 사용


세 기술이 각각 다른 구간을 암호화합니다.

  • DoT/DoH: 어떤 도메인을 조회하는지 암호화
  • HTTPS: 웹 콘텐츠 암호화
  • ECH: 어떤 서버에 접속하는지 암호화

세 기술을 결합하면, 네트워크 경로상의 관찰자가 사용자의 인터넷 활동에서 알 수 있는 것이 거의 없어집니다.


마무리

신뢰를 전제로 설계된 DNS는, 그 신뢰가 공격받을 때마다 새로운 방어 기술을 쌓아 왔습니다.


1
2
3
4
5
6
7
8
1983  RFC 882/883       DNS 탄생
1987  RFC 1034/1035     현재 표준의 기반
1999  RFC 2535          DNSSEC 최초 제안
2005  RFC 4033-4035     DNSSEC 현재 표준
2008  Kaminsky Attack   DNS 보안의 전환점
2016  RFC 7858          DNS over TLS
2018  RFC 8484          DNS over HTTPS
2022  RFC 9250          DNS over QUIC


  • 보안: 인증 없는 평문 → Source Port Randomization, 0x20 인코딩 → DNSSEC의 디지털 서명
  • 프라이버시: 질의 내용 노출 → DoT/DoH로 암호화 → ODoH로 익명성 → ECH로 접속 대상까지 은닉
  • 인프라: Anycast로 전 세계 분산, GeoDNS와 CDN으로 지능적 라우팅

시리즈


관련 시리즈

Tags: DNSSEC, DNS, DoH, 네트워크, 보안

Categories: ,