🌍 네트워크

DNS over HTTPS

HTTPS로 DNS 쿼리를 암호화하는 프로토콜

📖 상세 설명

DNS over HTTPS(DoH)는 HTTPS 프로토콜을 통해 DNS 쿼리를 암호화하여 전송하는 보안 프로토콜입니다. 기존 DNS는 평문으로 쿼리를 전송하기 때문에 ISP나 네트워크 관리자가 사용자가 어떤 웹사이트에 접속하는지 감청할 수 있었습니다. DoH는 이 문제를 해결하여 DNS 프라이버시를 보장합니다.

DoH는 2018년 RFC 8484로 표준화되었으며, Cloudflare와 Google이 선도적으로 도입했습니다. HTTPS 443 포트를 사용하기 때문에 일반 웹 트래픽과 구분이 불가능해서 검열을 우회할 수 있습니다. Firefox는 2020년부터 미국에서 DoH를 기본 활성화했고, Chrome, Edge, Safari 등 주요 브라우저도 지원합니다.

DoH와 유사한 프로토콜로 DoT(DNS over TLS)가 있습니다. DoT는 853 포트를 사용하며, 전용 포트 덕분에 네트워크 관리자가 DNS 트래픽을 별도로 관리할 수 있습니다. 반면 DoH는 웹 트래픽과 섞여서 블로킹이 어렵습니다. 기업 환경에서는 DoT, 개인 프라이버시가 중요한 경우 DoH가 선호됩니다.

대표적인 DoH 서버로는 Cloudflare 1.1.1.1(가장 빠름), Google 8.8.8.8(안정성), Quad9 9.9.9.9(보안 특화, 멀웨어 도메인 차단) 등이 있습니다. 한국에서는 1.1.1.1이 평균 10-20ms로 가장 빠른 응답 시간을 보여줍니다.

📊 DoH vs DoT 비교

구분 DoH (DNS over HTTPS) DoT (DNS over TLS)
포트 443 (HTTPS) 853 (전용)
프로토콜 HTTPS/HTTP2 TLS 직접 연결
검열 우회 쉬움 (웹 트래픽과 구분 불가) 어려움 (전용 포트 차단 가능)
기업 관리 어려움 (모니터링 불가) 쉬움 (포트 기반 정책 적용)
성능 HTTP/2 오버헤드 존재 더 빠름 (단순 TLS)
브라우저 지원 Chrome, Firefox, Edge, Safari OS 레벨 설정 필요

🌐 주요 DoH 제공자

Cloudflare
1.1.1.1 / 1.0.0.1
https://cloudflare-dns.com/dns-query
가장 빠른 응답 속도, 개인정보 보호 중점, 24시간 로그 삭제
Google Public DNS
8.8.8.8 / 8.8.4.4
https://dns.google/dns-query
높은 안정성, 전 세계 인프라, ECS 지원
Quad9
9.9.9.9 / 149.112.112.112
https://dns.quad9.net/dns-query
보안 특화, 멀웨어/피싱 도메인 자동 차단, 비영리 재단
NextDNS
개인 설정 IP 제공
https://dns.nextdns.io/[설정ID]
커스텀 필터링, 광고/트래커 차단, 상세 통계

💻 코드 예제

# DoH 쿼리 (Cloudflare) - JSON 형식
curl -H "accept: application/dns-json" \
  "https://cloudflare-dns.com/dns-query?name=google.com&type=A"

# DoH 쿼리 (Google) - JSON 형식
curl "https://dns.google/resolve?name=google.com&type=A"

# DoH 쿼리 - DNS 와이어 형식 (바이너리)
curl -H "accept: application/dns-message" \
  "https://cloudflare-dns.com/dns-query?dns=AAABAAABAAAAAAAAB2dvb2dsZQNjb20AAAEAAQ"

# 응답 시간 측정
curl -w "DNS: %{time_namelookup}s, Total: %{time_total}s\n" -o /dev/null -s \
  "https://cloudflare-dns.com/dns-query?name=example.com&type=A"

# DoT 테스트 (853 포트, openssl 사용)
echo -e '\x00\x1d\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07google\x03com\x00\x00\x01\x00\x01' | \
  openssl s_client -connect 1.1.1.1:853 -quiet 2>/dev/null | xxd

# 시스템 DoH 설정 (systemd-resolved, Linux)
# /etc/systemd/resolved.conf 수정
# [Resolve]
# DNS=1.1.1.1#cloudflare-dns.com
# DNSOverTLS=yes
import httpx  # pip install httpx
import json

# DoH 쿼리 (JSON API)
def doh_query_json(domain: str, record_type: str = "A") -> dict:
    """Cloudflare DoH JSON API로 DNS 쿼리"""
    url = "https://cloudflare-dns.com/dns-query"
    params = {"name": domain, "type": record_type}
    headers = {"accept": "application/dns-json"}

    response = httpx.get(url, params=params, headers=headers)
    return response.json()

# 사용 예시
result = doh_query_json("google.com", "A")
print(f"도메인: {result['Question'][0]['name']}")
for answer in result.get('Answer', []):
    print(f"  {answer['type']}: {answer['data']} (TTL: {answer['TTL']}s)")

# Google DoH 쿼리
def google_doh_query(domain: str) -> dict:
    """Google DoH JSON API"""
    url = f"https://dns.google/resolve?name={domain}&type=A"
    response = httpx.get(url)
    return response.json()

# DoH 서버 응답 속도 비교
import time

DOH_SERVERS = {
    "Cloudflare": "https://cloudflare-dns.com/dns-query?name=example.com&type=A",
    "Google": "https://dns.google/resolve?name=example.com&type=A",
    "Quad9": "https://dns.quad9.net:5053/dns-query?name=example.com&type=A"
}

for name, url in DOH_SERVERS.items():
    start = time.time()
    httpx.get(url, headers={"accept": "application/dns-json"})
    latency = (time.time() - start) * 1000
    print(f"{name}: {latency:.1f}ms")
// DoH 쿼리 (브라우저 / Node.js)
async function dohQuery(domain, type = 'A') {
    const url = `https://cloudflare-dns.com/dns-query?name=${domain}&type=${type}`;

    const response = await fetch(url, {
        headers: { 'accept': 'application/dns-json' }
    });

    return response.json();
}

// 사용 예시
const result = await dohQuery('google.com', 'A');
console.log('DNS 응답:', result);

result.Answer?.forEach(record => {
    console.log(`${record.name} -> ${record.data} (TTL: ${record.TTL}s)`);
});

// 여러 레코드 타입 조회
async function fullDnsLookup(domain) {
    const types = ['A', 'AAAA', 'MX', 'TXT', 'NS'];
    const results = {};

    await Promise.all(types.map(async type => {
        try {
            const data = await dohQuery(domain, type);
            results[type] = data.Answer || [];
        } catch (e) {
            results[type] = [];
        }
    }));

    return results;
}

// DNS 응답 시간 측정
async function measureDohLatency(server, domain) {
    const start = performance.now();
    await fetch(`${server}?name=${domain}&type=A`, {
        headers: { 'accept': 'application/dns-json' }
    });
    return performance.now() - start;
}

// 여러 DoH 서버 비교
const servers = {
    'Cloudflare': 'https://cloudflare-dns.com/dns-query',
    'Google': 'https://dns.google/resolve',
};

for (const [name, url] of Object.entries(servers)) {
    const latency = await measureDohLatency(url, 'example.com');
    console.log(`${name}: ${latency.toFixed(1)}ms`);
}

🗣️ 실무에서 이렇게 말하세요

💬 보안 팀 미팅에서
"카페나 공항 같은 퍼블릭 와이파이에서 DNS 스누핑 위험이 있습니다. 회사 기기에 DoH를 기본 활성화하면 직원들의 웹 브라우징 프라이버시를 보호할 수 있어요. Cloudflare 1.1.1.1이나 NextDNS로 설정하면 됩니다."
💬 네트워크 팀과 논의할 때
"DoH를 도입하면 기존 DNS 기반 보안 솔루션이 무력화될 수 있어요. 기업 환경에서는 DoT(853 포트)를 사용하거나, 내부 DoH 프록시를 구축해서 DNS 트래픽을 모니터링할 수 있게 해야 합니다. 아니면 Umbrella 같은 에이전트 기반 솔루션을 검토해보세요."
💬 면접에서
"DoH와 DoT 모두 DNS 암호화 프로토콜이지만, DoH는 443 포트를 사용해서 일반 HTTPS 트래픽과 구분이 안 되고, DoT는 853 전용 포트를 사용해서 네트워크 관리가 가능합니다. 개인 프라이버시 목적이면 DoH가, 기업 보안 정책과 병행하려면 DoT가 적합합니다."

⚠️ 흔한 실수 & 주의사항

기업 보안 정책과 충돌

DoH는 DNS 기반 콘텐츠 필터링, DLP 솔루션을 우회합니다. 기업 환경에서는 Firefox의 canary domain 체크를 활용하거나, 그룹 정책으로 DoH를 비활성화하세요.

단일 DoH 서버 의존

DoH 서버 장애 시 DNS 해석이 불가능해집니다. Cloudflare + Google처럼 복수의 DoH 서버를 폴백으로 설정하세요.

완전한 익명성 오해

DoH는 DNS 쿼리만 암호화합니다. SNI(Server Name Indication)를 통해 접속 도메인이 노출될 수 있습니다. 완전한 프라이버시를 원하면 ECH(Encrypted Client Hello)도 함께 사용해야 합니다.

올바른 DoH 설정

브라우저별 설정: Chrome(설정 > 개인정보 > 보안 DNS), Firefox(설정 > 네트워크 설정 > HTTPS를 통한 DNS 활성화). OS 레벨은 Windows 11, iOS 14+, Android 9+에서 네이티브 지원합니다.

🔗 관련 용어

📚 더 배우기