DNS
DNS(Domain Name System)完全ガイド
はじめに
DNS(Domain Name System)は、人間が理解しやすいドメイン名(例: www.example.com)をコンピュータが通信に使用するIPアドレス(例: 93.184.216.34)に変換する、インターネットの基盤システムである。1983年にPaul MockapetrisによってRFC 882/883として提案され、現在のRFC 1034/1035として標準化された。
DNSは「インターネットの電話帳」とも呼ばれ、Web、メール、VPN、CDNなど、事実上すべてのインターネットサービスが依存している。DNSが停止すると、ドメイン名による通信が不可能になり、インターネット全体に甚大な影響を及ぼす。
本記事では、DNSの基本概念、階層構造、名前解決プロセス、レコードタイプ、サーバー設定、セキュリティ(DNSSEC、DoH/DoT)、パフォーマンス最適化、トラブルシューティングまで、DNSの全容を体系的に解説する。
第1章: DNSの基本概念
1.1 DNSの役割
DNSは以下の主要な機能を提供する:
| 機能 | 説明 |
|---|---|
| 名前解決(正引き) | ドメイン名 → IPアドレス(Aレコード、AAAAレコード) |
| 逆引き | IPアドレス → ドメイン名(PTRレコード) |
| メールルーティング | ドメイン → メールサーバー(MXレコード) |
| サービス検出 | サービスの場所とポート(SRVレコード) |
| テキスト情報 | SPF、DKIM、DMARCなどのポリシー(TXTレコード) |
| エイリアス | ドメインの別名(CNAMEレコード) |
| 権限委譲 | サブドメインの管理権限の委譲(NSレコード) |
1.2 DNSの階層構造
DNSは分散型の階層データベースとして設計されている。
. (ルート)
/|\
/ | \
/ | \
com net org jp uk ... (TLD: トップレベルドメイン)
/|\ |
/ | \ |
/ | \ |
google amazon example co ac ... (SLD: セカンドレベルドメイン)
| |
www yahoo
|
www
ドメイン名の構造:
www.example.com.
│ │ │ │
│ │ │ └─ ルートドメイン(通常省略、末尾のドット)
│ │ └──── TLD(トップレベルドメイン)
│ └────────── SLD(セカンドレベルドメイン)
└──────────────── サブドメイン(ホスト名)
FQDN(完全修飾ドメイン名): www.example.com.(末尾にドットを含む)
1.3 TLD(トップレベルドメイン)の種類
| 種類 | 例 | 説明 |
|---|---|---|
| gTLD(汎用) | .com, .net, .org, .info | 汎用的に使用可能 |
| ccTLD(国別) | .jp, .uk, .de, .cn | 国・地域コード |
| 新gTLD | .tokyo, .app, .dev, .cloud | 2012年以降に追加 |
| sTLD(スポンサー付き) | .edu, .gov, .mil | 特定組織向け |
| インフラTLD | .arpa | インフラ用途(逆引きなど) |
1.4 DNSの構成要素
┌─────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ クライアント │ │ リゾルバ │ │ 権威DNSサーバー │
│ (スタブリゾルバ)│───>│(フルリゾルバ/ │───>│ (Authoritative) │
│ │<───│ キャッシュDNS) │<───│ │
└─────────────┘ └──────────────────┘ └──────────────────┘
│
│ キャッシュ
▼
┌──────────────┐
│ キャッシュ │
│ (TTLベース) │
└──────────────┘
| コンポーネント | 役割 | 例 |
|---|---|---|
| スタブリゾルバ | OSの名前解決クライアント | /etc/resolv.conf |
| フルリゾルバ(再帰リゾルバ) | クライアントに代わって名前解決を実行 | 8.8.8.8, 1.1.1.1, Unbound |
| 権威DNSサーバー | ゾーンデータを管理・応答 | BIND, NSD, PowerDNS |
| ルートサーバー | TLDサーバーへの参照を提供 | a.root-servers.net〜m.root-servers.net |
| TLDサーバー | SLDサーバーへの参照を提供 | a.gtld-servers.net等 |
| フォワーダー | DNSクエリを上位サーバーに転送 | 企業内DNSなど |
1.5 ルートサーバー
DNSの最上位に位置する13のルートサーバーグループ。実際には、Anycastにより数百のノードが世界中に分散配置されている。
| サーバー | 運用組織 | IPアドレス例 |
|---|---|---|
| a.root-servers.net | Verisign | 198.41.0.4 |
| b.root-servers.net | USC-ISI | 199.9.14.201 |
| c.root-servers.net | Cogent | 192.33.4.12 |
| d.root-servers.net | University of Maryland | 199.7.91.13 |
| e.root-servers.net | NASA | 192.203.230.10 |
| f.root-servers.net | ISC | 192.5.5.241 |
| g.root-servers.net | US DoD | 192.112.36.4 |
| h.root-servers.net | US Army | 198.97.190.53 |
| i.root-servers.net | Netnod | 192.36.148.17 |
| j.root-servers.net | Verisign | 192.58.128.30 |
| k.root-servers.net | RIPE NCC | 193.0.14.129 |
| l.root-servers.net | ICANN | 199.7.83.42 |
| m.root-servers.net | WIDE Project | 202.12.27.33 |
# ルートサーバーへの直接問い合わせ
$ dig @a.root-servers.net . NS
# ルートヒントファイルの確認
$ cat /var/named/named.ca # BIND
$ cat /etc/unbound/root.hints # Unbound
第2章: DNS名前解決プロセス
2.1 再帰的問い合わせと反復的問い合わせ
再帰的問い合わせ(Recursive Query):
クライアント → フルリゾルバ: 「www.example.comのIPは?」
フルリゾルバが完全な回答を返す責任を持つ
反復的問い合わせ(Iterative Query):
フルリゾルバ → 権威サーバー: 「www.example.comのIPは?」
権威サーバーは知っている範囲で回答(参照情報を返す場合もある)
2.2 名前解決の完全なフロー
ユーザーがブラウザで www.example.com にアクセス
① アプリケーション → スタブリゾルバ
getaddrinfo("www.example.com") を呼び出し
② スタブリゾルバ → ローカルキャッシュ確認
/etc/hosts ファイル → NSS設定 → DNSリゾルバ
③ スタブリゾルバ → フルリゾルバ(再帰クエリ)
「www.example.com の A レコードをください」
④ フルリゾルバ → キャッシュ確認
キャッシュにあれば即座に応答
⑤ フルリゾルバ → ルートサーバー(反復クエリ)
「www.example.com の A レコードをください」
ルートサーバー: 「.com は a.gtld-servers.net に聞いてください」
⑥ フルリゾルバ → TLDサーバー(反復クエリ)
「www.example.com の A レコードをください」
TLDサーバー: 「example.com は ns1.example.com に聞いてください」
⑦ フルリゾルバ → 権威サーバー(反復クエリ)
「www.example.com の A レコードをください」
権威サーバー: 「www.example.com は 93.184.216.34 です」(権威応答)
⑧ フルリゾルバ → スタブリゾルバ
応答をキャッシュに保存し、クライアントに返答
⑨ スタブリゾルバ → アプリケーション
IPアドレスを返す
┌──────┐ ① ┌──────────┐ ③ ┌────────────┐
│ブラウザ│───>│スタブリゾルバ│───>│フルリゾルバ │
└──────┘ ⑨ └──────────┘ ⑧ └─────┬──────┘
│
⑤│ ⑥│ ⑦│
▼ ▼ ▼
┌─────┐ ┌───┐ ┌────┐
│ルート │ │TLD│ │権威 │
└─────┘ └───┘ └────┘
2.3 DNSメッセージフォーマット
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Header |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Question |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Answer |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Authority |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| Additional |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
ヘッダフォーマット:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| フィールド | ビット数 | 説明 |
|---|---|---|
| ID | 16 | トランザクション識別子 |
| QR | 1 | 0=クエリ, 1=応答 |
| Opcode | 4 | 0=標準クエリ, 1=逆クエリ, 2=サーバーステータス |
| AA | 1 | 権威応答(Authoritative Answer) |
| TC | 1 | 切り詰め(Truncation) — UDP応答が512バイトを超えた場合 |
| RD | 1 | 再帰要求(Recursion Desired) |
| RA | 1 | 再帰利用可能(Recursion Available) |
| RCODE | 4 | 応答コード |
主な応答コード(RCODE):
| コード | 名称 | 説明 |
|---|---|---|
| 0 | NOERROR | 正常 |
| 1 | FORMERR | フォーマットエラー |
| 2 | SERVFAIL | サーバーエラー |
| 3 | NXDOMAIN | ドメインが存在しない |
| 4 | NOTIMP | 未実装 |
| 5 | REFUSED | 拒否 |
2.4 DNSトランスポート
| プロトコル | ポート | 用途 |
|---|---|---|
| UDP | 53 | 通常のDNSクエリ(512バイト以下) |
| TCP | 53 | 大きなレスポンス、ゾーン転送(AXFR/IXFR) |
| DoT(DNS over TLS) | 853 | 暗号化されたDNSクエリ |
| DoH(DNS over HTTPS) | 443 | HTTPS上のDNSクエリ |
| DoQ(DNS over QUIC) | 853 | QUIC上のDNSクエリ |
# UDP/TCPの切り替え
# 応答が512バイト(EDNS0では最大4096バイト)を超える場合、
# TC(Truncation)ビットが設定され、クライアントはTCPで再試行する
# EDNS0(Extension Mechanisms for DNS)
$ dig +bufsize=4096 www.example.com
# EDNS0はUDPの最大ペイロードサイズを拡張する
2.5 TTL(Time To Live)とキャッシュ
TTLは、DNSレコードがキャッシュに保持される時間(秒)を指定する。
TTLの設計指針:
短いTTL(60〜300秒):
✅ 変更が迅速に反映される
✅ フェイルオーバーが速い
❌ DNSクエリ数が増加
❌ 権威サーバーへの負荷増大
用途: CDN、ロードバランシング、フェイルオーバー
長いTTL(3600〜86400秒):
✅ DNSクエリ数が減少
✅ 名前解決のレイテンシが低い
❌ 変更の反映が遅い
用途: 安定したサービスのMXレコード、NSレコード
# TTLの確認
$ dig www.example.com
;; ANSWER SECTION:
www.example.com. 300 IN A 93.184.216.34
# ^^^
# TTL = 300秒(5分)
# キャッシュのTTL減少を観察
$ dig www.example.com +noall +answer
www.example.com. 287 IN A 93.184.216.34 # 13秒経過
$ dig www.example.com +noall +answer
www.example.com. 270 IN A 93.184.216.34 # 30秒経過
2.6 ネガティブキャッシュ
存在しないドメイン(NXDOMAIN)の応答もキャッシュされる。ネガティブキャッシュのTTLはSOAレコードのMINIMUMフィールドで制御される。
# ネガティブキャッシュの確認
$ dig nonexistent.example.com
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, ...
;; AUTHORITY SECTION:
example.com. 86400 IN SOA ns1.example.com. admin.example.com. ...
# MINIMUM = 3600
# ネガティブキャッシュTTL = min(SOA TTL, SOA MINIMUM) = min(86400, 3600) = 3600秒
第3章: DNSレコードタイプ
3.1 主要なレコードタイプ一覧
| タイプ | 値 | 説明 | RFC |
|---|---|---|---|
| A | 1 | IPv4アドレス | RFC 1035 |
| AAAA | 28 | IPv6アドレス | RFC 3596 |
| CNAME | 5 | 正規名(別名) | RFC 1035 |
| MX | 15 | メール交換(メールサーバー) | RFC 1035 |
| NS | 2 | ネームサーバー | RFC 1035 |
| PTR | 12 | ポインタ(逆引き) | RFC 1035 |
| SOA | 6 | 権威の開始(ゾーン情報) | RFC 1035 |
| TXT | 16 | テキスト情報 | RFC 1035 |
| SRV | 33 | サービスロケータ | RFC 2782 |
| CAA | 257 | CA認証(証明書発行制限) | RFC 8659 |
| DS | 43 | 委譲署名者(DNSSEC) | RFC 4034 |
| DNSKEY | 48 | DNS鍵(DNSSEC) | RFC 4034 |
| RRSIG | 46 | リソースレコード署名(DNSSEC) | RFC 4034 |
| NSEC/NSEC3 | 47/50 | 不在証明(DNSSEC) | RFC 4034/5155 |
| TLSA | 52 | TLS認証(DANE) | RFC 6698 |
| HTTPS | 65 | HTTPSサービスバインディング | RFC 9460 |
| SVCB | 64 | サービスバインディング | RFC 9460 |
3.2 各レコードタイプの詳細
A レコード(IPv4アドレス)
; ドメインからIPv4アドレスへのマッピング
www.example.com. 300 IN A 93.184.216.34
example.com. 300 IN A 93.184.216.34
; 複数のAレコード(ラウンドロビンDNS)
www.example.com. 300 IN A 10.0.0.1
www.example.com. 300 IN A 10.0.0.2
www.example.com. 300 IN A 10.0.0.3
# Aレコードの問い合わせ
$ dig www.example.com A +short
93.184.216.34
# 複数レコードの確認
$ dig www.google.com A +short
142.250.80.4
AAAA レコード(IPv6アドレス)
www.example.com. 300 IN AAAA 2606:2800:220:1:248:1893:25c8:1946
# AAAAレコードの問い合わせ
$ dig www.example.com AAAA +short
2606:2800:220:1:248:1893:25c8:1946
CNAME レコード(正規名 / エイリアス)
; www.example.com は example.com のエイリアス
www.example.com. 300 IN CNAME example.com.
; CDN使用時の典型的な設定
cdn.example.com. 300 IN CNAME d1234.cloudfront.net.
CNAMEの制約:
- CNAMEはそのドメインの唯一のレコードでなければならない
- ゾーンの頂点(example.com)にはCNAMEを設定できない(MX, NS等と共存不可)
- 代替: ALIAS/ANAME レコード(一部のDNSプロバイダが提供する独自拡張)
MX レコード(メールサーバー)
; 優先度の低い値が高優先
example.com. 3600 IN MX 10 mail1.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
example.com. 3600 IN MX 30 backup-mail.example.com.
# MXレコードの問い合わせ
$ dig example.com MX +short
10 mail1.example.com.
20 mail2.example.com.
NS レコード(ネームサーバー)
; ドメインの権威ネームサーバー
example.com. 86400 IN NS ns1.example.com.
example.com. 86400 IN NS ns2.example.com.
; グルーレコード(NSサーバーがゾーン内にある場合に必要)
ns1.example.com. 86400 IN A 198.51.100.1
ns2.example.com. 86400 IN A 198.51.100.2
SOA レコード(Start of Authority)
example.com. 86400 IN SOA ns1.example.com. admin.example.com. (
2024010101 ; シリアル番号(YYYYMMDDNN形式推奨)
3600 ; リフレッシュ間隔(1時間)
900 ; リトライ間隔(15分)
604800 ; 有効期限(7日)
3600 ; ネガティブキャッシュTTL(1時間)
)
| フィールド | 説明 | 推奨値 |
|---|---|---|
| MNAME | プライマリネームサーバー | ns1.example.com. |
| RNAME | 管理者メールアドレス(@を.に置換) | admin.example.com. |
| SERIAL | シリアル番号(変更ごとにインクリメント) | YYYYMMDDNN |
| REFRESH | セカンダリがプライマリに確認する間隔 | 3600 (1h) |
| RETRY | リフレッシュ失敗時のリトライ間隔 | 900 (15m) |
| EXPIRE | セカンダリがゾーンデータを無効とする期限 | 604800 (7d) |
| MINIMUM | ネガティブキャッシュのTTL | 3600 (1h) |
TXT レコード
; SPF(Sender Policy Framework)
example.com. 300 IN TXT "v=spf1 mx ip4:198.51.100.0/24 include:_spf.google.com -all"
; DKIM(DomainKeys Identified Mail)
google._domainkey.example.com. 300 IN TXT "v=DKIM1; k=rsa; p=MIIBIj..."
; DMARC(Domain-based Message Authentication)
_dmarc.example.com. 300 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"
; ドメイン検証
example.com. 300 IN TXT "google-site-verification=abc123..."
example.com. 300 IN TXT "MS=ms12345678"
SRV レコード(サービスロケータ)
; 書式: _service._protocol.name TTL class SRV priority weight port target
_sip._tcp.example.com. 300 IN SRV 10 60 5060 sip1.example.com.
_sip._tcp.example.com. 300 IN SRV 10 40 5060 sip2.example.com.
_ldap._tcp.example.com. 300 IN SRV 0 0 389 ldap.example.com.
_kerberos._tcp.example.com. 300 IN SRV 0 0 88 kdc.example.com.
CAA レコード(CA認証)
; Let's Encryptのみが証明書を発行可能
example.com. 3600 IN CAA 0 issue "letsencrypt.org"
example.com. 3600 IN CAA 0 issuewild "letsencrypt.org"
example.com. 3600 IN CAA 0 iodef "mailto:security@example.com"
PTR レコード(逆引き)
; IPv4逆引き
34.216.184.93.in-addr.arpa. 3600 IN PTR www.example.com.
; IPv6逆引き
6.4.9.1.8.c.5.2.3.9.8.1.8.4.2.0.1.0.0.0.0.2.2.0.0.0.8.2.6.0.6.2.ip6.arpa. 3600 IN PTR www.example.com.
# 逆引きの確認
$ dig -x 93.184.216.34 +short
$ host 93.184.216.34
HTTPS / SVCB レコード
; HTTPSレコード(RFC 9460)— ECH、ALPN、IPヒントなどを提供
example.com. 300 IN HTTPS 1 . alpn="h2,h3" ipv4hint=93.184.216.34 ech="..."
; AliasMode
example.com. 300 IN HTTPS 0 cdn.example.net.
# HTTPSレコードの確認
$ dig example.com HTTPS
第4章: DNSゾーンとサーバー設定
4.1 ゾーンファイルの構造
; /etc/bind/zones/example.com.zone
$ORIGIN example.com.
$TTL 3600
; SOAレコード
@ IN SOA ns1.example.com. admin.example.com. (
2024010101 ; Serial
3600 ; Refresh (1h)
900 ; Retry (15m)
604800 ; Expire (7d)
3600 ; Minimum TTL (1h)
)
; NSレコード
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
; Aレコード(ネームサーバー自身)
ns1 IN A 198.51.100.1
ns2 IN A 198.51.100.2
; Aレコード(Webサーバー)
@ IN A 93.184.216.34
www IN A 93.184.216.34
www IN AAAA 2606:2800:220:1:248:1893:25c8:1946
; CNAMEレコード
cdn IN CNAME d1234.cloudfront.net.
blog IN CNAME example.ghost.io.
; MXレコード
@ IN MX 10 mail1.example.com.
@ IN MX 20 mail2.example.com.
mail1 IN A 198.51.100.10
mail2 IN A 198.51.100.11
; TXTレコード
@ IN TXT "v=spf1 mx ip4:198.51.100.0/24 -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"
4.2 BIND(Berkeley Internet Name Domain)の設定
# /etc/named.conf(BIND 9の主要設定)
options {
directory "/var/named";
listen-on port 53 { 127.0.0.1; 198.51.100.1; };
listen-on-v6 port 53 { ::1; };
allow-query { any; };
allow-recursion { 10.0.0.0/8; 172.16.0.0/12; 192.168.0.0/16; };
recursion yes;
dnssec-validation auto;
forwarders {
8.8.8.8;
8.8.4.4;
};
rate-limit {
responses-per-second 10;
window 5;
};
version "not disclosed";
};
zone "example.com" IN {
type master;
file "zones/example.com.zone";
allow-transfer { 198.51.100.2; }; # セカンダリサーバーへの転送許可
also-notify { 198.51.100.2; };
};
zone "100.51.198.in-addr.arpa" IN {
type master;
file "zones/198.51.100.rev";
};
4.3 Unbound(リカーシブリゾルバ)の設定
# /etc/unbound/unbound.conf
server:
interface: 0.0.0.0
port: 53
access-control: 10.0.0.0/8 allow
access-control: 172.16.0.0/12 allow
access-control: 192.168.0.0/16 allow
access-control: 127.0.0.0/8 allow
# パフォーマンス設定
num-threads: 4
msg-cache-size: 128m
rrset-cache-size: 256m
key-cache-size: 64m
neg-cache-size: 16m
# キャッシュ設定
cache-min-ttl: 60
cache-max-ttl: 86400
prefetch: yes # TTL切れ前にプリフェッチ
prefetch-key: yes
serve-expired: yes # TTL切れのキャッシュを一時的に提供
serve-expired-ttl: 86400
# DNSSEC
auto-trust-anchor-file: "/var/lib/unbound/root.key"
val-clean-additional: yes
# プライバシー
hide-identity: yes
hide-version: yes
qname-minimisation: yes # QNAME最小化(プライバシー保護)
# セキュリティ
harden-glue: yes
harden-dnssec-stripped: yes
harden-below-nxdomain: yes
use-caps-for-id: yes # 0x20エンコーディング
# ログ
verbosity: 1
log-queries: no
log-replies: no
# フォワード設定(DoT使用)
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 1.1.1.1@853#cloudflare-dns.com
forward-addr: 1.0.0.1@853#cloudflare-dns.com
forward-addr: 8.8.8.8@853#dns.google
forward-addr: 8.8.4.4@853#dns.google
# ローカルゾーン(内部DNS)
local-zone: "internal.example.com." static
local-data: "app.internal.example.com. 300 IN A 10.0.1.100"
local-data: "db.internal.example.com. 300 IN A 10.0.2.100"
4.4 CoreDNS(Kubernetes向け)
# /etc/coredns/Corefile
.:53 {
errors
health {
lameduck 5s
}
ready
# Kubernetesクラスタ内の名前解決
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
# 外部ドメインの解決
forward . /etc/resolv.conf {
max_concurrent 1000
}
# キャッシュ
cache 30
# ループ検出
loop
# リロード設定
reload
# ログ
log
# Prometheusメトリクス
prometheus :9153
}
4.5 ゾーン転送
AXFR(完全ゾーン転送)
プライマリサーバーからセカンダリサーバーへゾーンデータ全体を転送する。
# AXFRのテスト
$ dig @ns1.example.com example.com AXFR
# BINDでのAXFR許可設定
# zone "example.com" {
# type master;
# allow-transfer { 198.51.100.2; };
# };
IXFR(差分ゾーン転送)
変更された差分のみを転送する。シリアル番号の差分に基づく。
# IXFRのテスト
$ dig @ns1.example.com example.com IXFR=2024010100
NOTIFY
プライマリサーバーがゾーン変更をセカンダリに通知するメカニズム。
# BINDでのNOTIFY設定
# zone "example.com" {
# type master;
# also-notify { 198.51.100.2; };
# notify yes;
# };
4.6 動的DNS更新(Dynamic DNS / DDNS)
# nsupdate を使用した動的更新
$ nsupdate -k /etc/bind/keys/update.key <<EOF
server ns1.example.com
zone example.com
update delete test.example.com A
update add test.example.com 300 A 10.0.0.100
send
EOF
# BINDでの動的更新許可
# zone "example.com" {
# type master;
# allow-update { key "update-key"; };
# };
第5章: DNSセキュリティ
5.1 DNSに対する主な脅威
| 攻撃 | 説明 | 対策 |
|---|---|---|
| DNSキャッシュポイズニング | 偽のDNS応答をキャッシュに注入 | DNSSEC, ソースポートランダム化 |
| DNSスプーフィング | DNS応答を偽装 | DNSSEC |
| DNS増幅攻撃(DDoS) | DNSを使用したDDoSリフレクション攻撃 | RRL, BCP38 |
| DNSトンネリング | DNSクエリを使用したデータ窃取 | クエリ分析, ファイアウォール |
| DNSハイジャック | ドメインの不正な移管・設定変更 | レジストリロック, DNSSEC |
| NXDOMAINハイジャック | 不在ドメインの応答を改ざん | DNSSEC |
| ドメインシャドウイング | 正規ドメインにサブドメインを不正作成 | アカウント保護, モニタリング |
5.2 DNSSEC(DNS Security Extensions)
DNSSECは、DNS応答にデジタル署名を付加し、応答の真正性と完全性を検証する仕組み。
DNSSECの信頼チェーン:
ルートゾーン (.)
│ DNSKEY(KSK + ZSK)
│ DS(.comのKSKのハッシュ)
▼
.comゾーン
│ DNSKEY(KSK + ZSK)
│ DS(example.comのKSKのハッシュ)
▼
example.comゾーン
│ DNSKEY(KSK + ZSK)
│ RRSIG(各レコードの署名)
▼
www.example.com A 93.184.216.34 + RRSIG
DNSSEC関連のレコードタイプ:
| レコード | 説明 |
|---|---|
| DNSKEY | ゾーンの公開鍵(KSK: 鍵署名鍵、ZSK: ゾーン署名鍵) |
| RRSIG | リソースレコードセットの署名 |
| DS | 子ゾーンのKSKのハッシュ(親ゾーンに配置) |
| NSEC/NSEC3 | 不在証明(ドメインが存在しないことの証明) |
# DNSSECの検証
$ dig +dnssec www.example.com
# ADフラグ(Authenticated Data)が設定されていればDNSSEC検証済み
# DNSSEC検証の詳細
$ dig +dnssec +cd www.example.com # CDフラグで検証をスキップ
$ delv www.example.com # DNSSEC検証ツール
# DNSSECチェーンの確認
$ dig +trace +dnssec www.example.com
# DS レコードの確認
$ dig example.com DS +short
DNSSEC鍵の管理
# KSK(鍵署名鍵)の生成
$ dnssec-keygen -a ECDSAP256SHA256 -f KSK example.com
# ZSK(ゾーン署名鍵)の生成
$ dnssec-keygen -a ECDSAP256SHA256 example.com
# ゾーンの署名
$ dnssec-signzone -A -3 $(head -c 1000 /dev/urandom | sha1sum | cut -b 1-16) \
-N INCREMENT -o example.com -t example.com.zone
# 鍵のローテーション
# ZSK: 30〜90日ごとにローテーション推奨
# KSK: 1〜2年ごとにローテーション推奨
5.3 DNS over TLS(DoT)
DNSクエリをTLSで暗号化して送信する。ポート853を使用。
# DoTでの問い合わせ(kdigを使用)
$ kdig -d @1.1.1.1 +tls-ca +tls-host=cloudflare-dns.com www.example.com
# systemd-resolvedでのDoT設定
# /etc/systemd/resolved.conf
# [Resolve]
# DNS=1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com
# DNSOverTLS=yes
# UnboundでのDoTフォワード設定
# forward-zone:
# name: "."
# forward-tls-upstream: yes
# forward-addr: 1.1.1.1@853#cloudflare-dns.com
5.4 DNS over HTTPS(DoH)
DNSクエリをHTTPS上で送信する。ポート443を使用し、通常のHTTPSトラフィックと区別がつかない。
# DoHでの問い合わせ(curlを使用)
$ curl -H "accept: application/dns-json" \
"https://cloudflare-dns.com/dns-query?name=www.example.com&type=A"
# DoHでの問い合わせ(ワイヤーフォーマット)
$ curl -s -H "content-type: application/dns-message" \
"https://cloudflare-dns.com/dns-query" \
--data-binary @query.bin | python3 -c "import sys; ..."
主要なDoHプロバイダ:
| プロバイダ | URL |
|---|---|
| Cloudflare | https://cloudflare-dns.com/dns-query |
| https://dns.google/dns-query | |
| Quad9 | https://dns.quad9.net/dns-query |
5.5 DNS増幅攻撃の対策
# レスポンスレート制限(RRL)— BINDの設定
# options {
# rate-limit {
# responses-per-second 10;
# window 5;
# slip 2;
# };
# };
# オープンリゾルバの確認
$ dig @your-server.com example.com +short
# 外部から応答が返る場合、オープンリゾルバの可能性
# アクセス制御
# allow-recursion { 内部ネットワーク; };
# allow-query-cache { 内部ネットワーク; };
5.6 RPZ(Response Policy Zone)
DNSベースのセキュリティフィルタリング。マルウェアサイトやフィッシングサイトへのアクセスをDNSレベルでブロックする。
# BINDでのRPZ設定
# zone "rpz.example.com" {
# type master;
# file "rpz.example.com.zone";
# };
# options {
# response-policy { zone "rpz.example.com"; };
# };
# RPZゾーンファイル
# malware.example.com CNAME . ; NXDOMAINを返す
# phishing.example.com CNAME . ; NXDOMAINを返す
# *.bad-site.com CNAME rpz-passthru. ; 特定のサブドメインを許可
第6章: DNS運用とパフォーマンス
6.1 Anycast DNS
同じIPアドレスを複数の地理的に分散したサーバーに割り当て、BGPルーティングにより最も近いサーバーに自動的にルーティングする技術。
利点:
- 低レイテンシ(最寄りのサーバーに接続)
- DDoS耐性(トラフィックが分散)
- 高可用性(1台が停止しても他がサービス継続)
主要なAnycast DNSプロバイダ:
- Cloudflare DNS (1.1.1.1)
- Google Public DNS (8.8.8.8)
- Amazon Route 53
- NS1
6.2 GeoDNS(地理的DNS)
クライアントのIPアドレスの地理情報に基づいて異なる応答を返す。CDNで広く使用。
# PowerDNSのGeoIP設定例
# geoip-database-files=/usr/share/GeoIP/GeoLite2-Country.mmdb
#
# zones:
# example.com:
# www:
# geo:
# JP: 10.0.1.1 # 日本のユーザー
# US: 10.0.2.1 # 米国のユーザー
# default: 10.0.3.1
6.3 DNSロードバランシング
方式1: ラウンドロビンDNS
www.example.com. 300 IN A 10.0.0.1
www.example.com. 300 IN A 10.0.0.2
www.example.com. 300 IN A 10.0.0.3
→ クライアントに返されるIPの順序がランダム化される
方式2: 重み付きDNS(AWS Route 53など)
www.example.com. 300 IN A 10.0.0.1 ; Weight: 70
www.example.com. 300 IN A 10.0.0.2 ; Weight: 30
方式3: ヘルスチェック付きDNS
→ 死活監視と連動し、障害サーバーを応答から除外
方式4: レイテンシベースルーティング
→ クライアントに最も近いリージョンのIPを返す
6.4 DNSフェイルオーバー
フェイルオーバー設定(AWS Route 53の例):
プライマリ: www.example.com → 10.0.0.1 (ヘルスチェック: HTTP /health)
セカンダリ: www.example.com → 10.0.0.2 (フェイルオーバー先)
プライマリがヘルスチェック失敗
→ Route 53が自動的にセカンダリのIPを返す
→ TTL短縮(60秒など)で迅速なフェイルオーバー
6.5 プリフェッチとキャッシュ最適化
# Unboundのプリフェッチ設定
server:
prefetch: yes
# TTLの90%経過時に、次のクエリをトリガーとしてバックグラウンドで
# 権威サーバーに問い合わせ、キャッシュを更新する
prefetch-key: yes
# DNSSEC鍵もプリフェッチ
serve-expired: yes
# TTL切れのキャッシュを一時的に提供しつつ、バックグラウンドで更新
serve-expired-ttl: 86400
# キャッシュサイズ
msg-cache-size: 128m
rrset-cache-size: 256m
第7章: DNSトラブルシューティング
7.1 dig(Domain Information Groper)
# 基本的な問い合わせ
$ dig www.example.com
# 特定のレコードタイプ
$ dig www.example.com A
$ dig www.example.com AAAA
$ dig example.com MX
$ dig example.com TXT
$ dig example.com NS
$ dig example.com SOA
# 簡潔な出力
$ dig www.example.com +short
93.184.216.34
# 特定のDNSサーバーに問い合わせ
$ dig @8.8.8.8 www.example.com
$ dig @ns1.example.com www.example.com
# トレース(ルートからの完全な解決パスを表示)
$ dig +trace www.example.com
# 逆引き
$ dig -x 93.184.216.34
# DNSSECの確認
$ dig +dnssec www.example.com
# TCPでの問い合わせ
$ dig +tcp www.example.com
# すべてのレコードタイプ
$ dig example.com ANY
# 詳細出力
$ dig +noall +answer +authority +additional www.example.com
# バッチ処理
$ dig -f domains.txt +short
# 応答時間の確認
$ dig www.example.com | grep "Query time"
;; Query time: 12 msec
7.2 nslookup
# 基本的な問い合わせ
$ nslookup www.example.com
# 特定のDNSサーバーを指定
$ nslookup www.example.com 8.8.8.8
# レコードタイプの指定
$ nslookup -type=MX example.com
$ nslookup -type=TXT example.com
$ nslookup -type=NS example.com
# 逆引き
$ nslookup 93.184.216.34
7.3 host
# 基本的な問い合わせ
$ host www.example.com
www.example.com has address 93.184.216.34
# 逆引き
$ host 93.184.216.34
# 特定のレコードタイプ
$ host -t MX example.com
$ host -t NS example.com
# 詳細出力
$ host -v www.example.com
7.4 一般的な問題と対処法
SERVFAIL
# 原因の調査
$ dig www.example.com +trace
# DNSSEC検証エラーの可能性
$ dig www.example.com +dnssec +cd # CD(Checking Disabled)フラグで検証をスキップ
# CDフラグで成功する場合はDNSSEC関連の問題
# 権威サーバーの確認
$ dig @ns1.example.com www.example.com
NXDOMAIN(ドメインが存在しない)
# ドメインの存在確認
$ dig example.com NS
# NSレコードが返ればドメインは存在する
# タイプミスの確認
$ dig wwww.example.com # typo
# ゾーン設定の確認
$ dig @ns1.example.com www.example.com
名前解決が遅い
# 応答時間の確認
$ dig www.example.com | grep "Query time"
# キャッシュの確認(2回目は高速なはず)
$ dig www.example.com # 1回目: 50ms
$ dig www.example.com # 2回目: 0ms(キャッシュ)
# DNSサーバーの応答確認
$ dig @8.8.8.8 www.example.com | grep "Query time"
$ dig @1.1.1.1 www.example.com | grep "Query time"
# ネットワーク到達性の確認
$ ping 8.8.8.8
$ traceroute 8.8.8.8
DNSの伝播確認
# 複数のDNSサーバーでの確認
$ for ns in 8.8.8.8 1.1.1.1 9.9.9.9; do
echo "=== $ns ==="
dig @$ns www.example.com +short
done
# 権威サーバー全体での確認
$ dig example.com NS +short | while read ns; do
echo "=== $ns ==="
dig @$ns www.example.com +short
done
7.5 クライアント側の設定
# /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 1.1.1.1
options timeout:2 attempts:3 rotate
# /etc/hosts(ローカルオーバーライド)
127.0.0.1 localhost
10.0.0.100 app.internal.example.com app
# /etc/nsswitch.conf(名前解決の順序)
hosts: files dns myhostname
# files: /etc/hosts を先に確認
# dns: DNSリゾルバに問い合わせ
# macOS
$ scutil --dns # DNS設定の確認
$ dscacheutil -flushcache # DNSキャッシュのクリア
$ sudo killall -HUP mDNSResponder
# Linux (systemd-resolved)
$ resolvectl status # DNS設定の確認
$ resolvectl flush-caches # キャッシュクリア
$ resolvectl statistics # キャッシュ統計
# Windows
> ipconfig /displaydns # DNSキャッシュの表示
> ipconfig /flushdns # DNSキャッシュのクリア
第8章: 実践シナリオとベストプラクティス
8.1 メールセキュリティのDNS設定
; SPF — 送信元メールサーバーの認証
example.com. 300 IN TXT "v=spf1 mx ip4:198.51.100.0/24 include:_spf.google.com -all"
; 説明:
; mx: ドメインのMXレコードのサーバーからの送信を許可
; ip4:198.51.100.0/24: このIPレンジからの送信を許可
; include:_spf.google.com: Google Workspaceの送信サーバーを許可
; -all: 上記以外はすべて拒否
; DKIM — メールの電子署名
selector1._domainkey.example.com. 300 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."
; DMARC — SPFとDKIMのポリシー統合
_dmarc.example.com. 300 IN TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; pct=100"
; MTA-STS — メールのTLS強制
_mta-sts.example.com. 300 IN TXT "v=STSv1; id=20240101"
; TLSRPT — TLSレポート
_smtp._tls.example.com. 300 IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@example.com"
8.2 Kubernetes環境のDNS
# CoreDNSのConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
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 {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
# Kubernetes内のDNS確認
$ kubectl run -it --rm debug --image=busybox -- nslookup kubernetes.default
$ kubectl run -it --rm debug --image=busybox -- nslookup my-service.my-namespace.svc.cluster.local
# Pod内のDNS設定
$ kubectl exec -it my-pod -- cat /etc/resolv.conf
# nameserver 10.96.0.10
# search my-namespace.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
8.3 CDN統合のDNS設定
; CloudFrontとの統合
cdn.example.com. 300 IN CNAME d123456.cloudfront.net.
; Cloudflareとの統合(プロキシモード)
www.example.com. 300 IN A 104.16.132.229 ; Cloudflare Anycast IP
; AWS Route 53 エイリアスレコード(ALB向け)
; example.com → my-alb-123456.us-east-1.elb.amazonaws.com
; Route 53のALIASレコードはゾーン頂点でも使用可能(CNAMEの代替)
第9章: DNSの最新動向
9.1 DNS over QUIC(DoQ)
QUICプロトコル上でDNSクエリを実行する。DoTの低レイテンシ版として期待されている。
9.2 Oblivious DNS over HTTPS(ODoH)
プロキシを経由してDoHを実行し、DNSサーバーがクライアントのIPアドレスを知ることを防ぐ。
9.3 DDR(Discovery of Designated Resolvers)
暗号化DNS(DoT/DoH)のリゾルバを自動的に発見するメカニズム(RFC 9462)。
9.4 SVCB/HTTPS レコード
サービスの接続パラメータ(ALPN、ECH鍵、IPヒント)をDNSで提供する新しいレコードタイプ(RFC 9460)。
まとめ
DNSはインターネットの基盤であり、その理解はすべてのエンジニアに不可欠である。本記事の要点:
- 基本概念: 階層構造、ルートサーバー、TLD、再帰/反復クエリ
- 名前解決プロセス: スタブリゾルバ → フルリゾルバ → 権威サーバーの連携
- レコードタイプ: A/AAAA、CNAME、MX、NS、SOA、TXT、SRV、CAA、HTTPS
- サーバー設定: BIND、Unbound、CoreDNS、ゾーンファイル
- セキュリティ: DNSSEC、DoT/DoH、RPZ、キャッシュポイズニング対策
- 運用: Anycast、GeoDNS、ロードバランシング、フェイルオーバー
- トラブルシューティング: dig、nslookup、一般的な問題と対処
- 実践: メールセキュリティ(SPF/DKIM/DMARC)、Kubernetes DNS、CDN統合
- 最新動向: DoQ、ODoH、DDR、SVCB/HTTPSレコード
参考文献
- RFC 1034 - Domain Names - Concepts and Facilities (1987)
- RFC 1035 - Domain Names - Implementation and Specification (1987)
- RFC 2782 - A DNS RR for specifying the location of services (SRV) (2000)
- RFC 4034 - Resource Records for the DNS Security Extensions (2005)
- RFC 4035 - Protocol Modifications for the DNS Security Extensions (2005)
- RFC 6698 - The DNS-Based Authentication of Named Entities (DANE) (2012)
- RFC 7858 - Specification for DNS over Transport Layer Security (DoT) (2016)
- RFC 8484 - DNS Queries over HTTPS (DoH) (2018)
- RFC 8659 - DNS Certification Authority Authorization (CAA) (2019)
- RFC 9460 - Service Binding and Parameter Specification via the DNS (2023)
- "DNS and BIND" - Cricket Liu, Paul Albitz (O'Reilly)
- "Pro DNS and BIND 10" - Ron Aitchison (Apress)
- IANA Root Zone Database: https://www.iana.org/domains/root/db
- Root Servers: https://root-servers.org/