Domain Name System (DNS) は、人間が覚えやすいドメイン名 (www.example.com) を、通信に使う IP アドレス (93.184.216.34) に変換する分散データベース。Web・メール・API・CDN・SaaS — 現代のネット利用はほぼすべてこの解決を経由する。デフォルトは UDP/TCP 53、暗号化 DNS では 853 (DoT) / 443 (DoH / DoQ)。本稿は実用視点で、階層構造・名前解決・主要 RR・dig の使い方・DNSSEC / DoT / DoH / DoQ・主要な攻撃と対策までを通しで扱う。
DNS とは何をしているか #
DNS は 「ドメイン名 → IP アドレス」 の対応表をインターネット規模で配るためのプロトコルであり、世界中の権威サーバーとリゾルバが協調して動く分散データベースでもある。一つの巨大ファイルを誰かが管理するのではなく、各ドメインの管理者が自分の領分だけを責任を持って公開し、必要なときに引っ張ってくる仕組み。
ブラウザに www.example.com と打った瞬間、OS のスタブリゾルバが上位のフルリゾルバへ問い合わせ、フルリゾルバはルート → TLD → 権威サーバーと階層を降りながら答えを集めてくる。結果は TTL の秒数だけキャッシュされ、次回以降は数ミリ秒で返る。
1983 年、Paul Mockapetris が ARPANET の HOSTS.TXT 中央管理の限界を解くために設計 (RFC 882/883)。1987 年 RFC 1034 / 1035 で標準化、UC Berkeley の BIND がデファクト実装に。以降 EDNS (1999) / DNSSEC (2005) / DoT (2016) / DoH (2018) / DoQ (RFC 9250, 2022) と拡張が積み上がってきた。
DNS で実際にできること #
- 名前 → IP の正引き (A / AAAA)
- IP → 名前の逆引き (PTR,
in-addr.arpa) - メールルーティング (MX) / 送信ドメイン認証 (SPF / DKIM / DMARC を TXT で配布)
- サービスディスカバリ (SRV / SVCB / HTTPS RR)
- 証明書発行ポリシー (CAA) / ACME 認証チャレンジ (TXT)
- 応答の真正性検証 (DNSSEC: DNSKEY / RRSIG / DS / NSEC)
階層構造と委譲モデル #
DNS は ルート (.) を頂点とする逆木構造。各組織は自分のゾーンの管理権を上位ゾーンから委譲 (delegation) される。委譲は NS レコード によって表現される — 「example.com の権威は ns1.example.com です」と上位ゾーン (com) が示すことで、解決時の参照先が決まる。
. (root) ─ ICANN / IANA
│
┌───────────┼───────────┐ ← NS 委譲
│ │ │
com jp org # TLD (Verisign / JPRS / PIR)
│ │ │
│ ┌─────┴─────┐ │ ← NS 委譲
│ │ │ │
example co.jp ne.jp … # 2nd-level (組織 / 企業 / プロバイダ)
│
┌─────┼─────┐
│ │ │
www mail api # subdomain (ホスト)FQDN とラベル #
完全形のドメイン名は www.example.com. のように . 区切りで書く (右にあるラベルほど上位)。末尾の . はルートを示し、厳密には付ける。
- ラベル —
.で区切られた各部分。最大 63 オクテット - FQDN (Fully Qualified Domain Name) — ルートまで含めた完全形。全体で最大 253 オクテット
- 大文字小文字は区別されない —
Example.COM=example.com
世界に何億ドメインあろうと、ルートが知っているのは「.com や .jp に聞きに行け」という参照先だけ。各 TLD は配下の登録ドメインの「権威 NS はここ」を返すだけ。誰も全部を知らないからスケールする — これが DNS の根本設計。
主要コンポーネント #
名前解決には複数の役割のサーバーが連携する。それぞれ「何を持っていて、何を返すのか」が違う。
| コンポーネント | 役割 | 代表例 |
|---|---|---|
| ルートサーバー | ルートゾーン . を返す。最終回答は持たず、「.com の権威はここ」と次の参照先だけ返す | a.root-servers.net 〜 m.root-servers.net (13 系統 + anycast で実体 1000 台超) |
| TLD サーバー | .com / .jp 等の TLD ゾーンを管理。「そのドメインの権威はここ」を返す | Verisign (.com) / JPRS (.jp) / PIR (.org) |
| 権威 DNS サーバー | 特定ゾーンの実レコードを保持し、最終回答 (AA=1) を返す | Cloudflare DNS / AWS Route 53 / Google Cloud DNS / Akamai |
| フルリゾルバ (再帰) | ルートから順に問い合わせて結果を集約・キャッシュする。クライアントには最終回答だけ返す | Cloudflare 1.1.1.1 / Google 8.8.8.8 / Quad9 9.9.9.9 / OpenDNS / ISP のリゾルバ |
| スタブリゾルバ | OS 組み込みの軽量クライアント。getaddrinfo() 経由で常に上位フルリゾルバへ投げるだけ | Linux glibc resolver / systemd-resolved / Windows DNS Client |
| フォワーダ / キャッシュ DNS | 組織内に置き、社内クエリのキャッシュ + 外部リゾルバへの転送。社内ゾーンの解決は内部で完結させる | Unbound / dnsmasq / Windows DNS Server (社内 AD) |
代表的なパブリックリゾルバ #
- Cloudflare —
1.1.1.1/1.0.0.1(DoT/DoH 標準対応、低レイテンシ重視) - Google Public DNS —
8.8.8.8/8.8.4.4(最古参のパブリックリゾルバ) - Quad9 —
9.9.9.9(マルウェア C2 ドメインをブロックするフィルタリング込み) - OpenDNS —
208.67.222.222(Cisco 傘下、カテゴリ別フィルタリング)
名前解決の流れ #
www.example.com の A レコードを引く典型例。クライアントはフルリゾルバに再帰問い合わせ (RD=1) を投げ、フルリゾルバはルートから順に反復問い合わせ (iterative) で次の参照先を辿っていく。
getaddrinfo("www.example.com") を呼ぶ。OS の /etc/resolv.conf または DHCP で指定された上位リゾルバへ転送される。www.example.com の A を再帰解決して」と 8.8.8.8 等に依頼。クライアントはここで待つだけ。.com TLD は a.gtld-servers.net に聞いて」と返す。example.com の権威は ns1.example.com」と返す。www.example.com IN A 93.184.216.34 を AA=1 (authoritative answer) で返す。これが最終回答。93.184.216.34 をクライアントに返す。アプリは TCP コネクションをそこに張りに行く。自分で動かして確かめる #
ドメインと「権威サーバが返す IP」を自由に設定して、解決ボタンを押すと 1 ステップずつ 問い合わせの流れをたどれる。ルート → TLD → 権威 と委譲が降りていく様子を、自分の値で確認してみよう。
再帰 (recursive) と反復 (iterative) の使い分け #
- 再帰問い合わせ — クライアント (またはスタブ) → フルリゾルバ間。「最終答えだけくれ」
- 反復問い合わせ — フルリゾルバ → 各権威サーバー間。「知ってる範囲を返してくれ、無ければ次の参照先で OK」
外部から再帰問い合わせを受け付けるリゾルバ (open recursive) は DNS Amplification 攻撃の踏み台になる。インターネット向けの権威サーバーと、内部向けのリゾルバは必ず分離し、リゾルバはアクセス元 IP で制限する。これが運用の鉄則。
キャッシュと TTL の決め方 #
- 短い TTL (60〜300 秒) — CDN / フェイルオーバー対象。切り替えが早いが上位への問い合わせが頻発
- 中くらい (3600 秒 = 1 時間) — 普通の A / AAAA。変更頻度と負荷のバランス
- 長い (86400 秒 = 1 日) — NS / MX / SOA。組織情報なので滅多に変えない
主要なリソースレコード (RR) #
DNS が返す「答え」の単位がレコード (Resource Record)。タイプごとに用途が決まっていて、実運用で出会うのは下表のあたり。
| Type | 用途 | 実例 |
|---|---|---|
| A | ドメイン名 → IPv4 アドレス | example.com. 86400 IN A 93.184.216.34 |
| AAAA | ドメイン名 → IPv6 アドレス | example.com. 86400 IN AAAA 2606:2800:220:1:: |
| CNAME | 別名 (エイリアス)。www → apex.example.com のように転送 | www IN CNAME apex.example.com. |
| NS | このゾーンの権威サーバー。委譲もこれで表現 | example.com. IN NS a.iana-servers.net. |
| MX | メール配送先。Priority + Hostname の組 | example.com. IN MX 10 mail.example.com. |
| TXT | 任意テキスト。SPF / DKIM / DMARC / ACME チャレンジ / 所有権検証 | "v=spf1 include:_spf.google.com ~all" |
| PTR | IP → ドメイン名 (逆引き)。in-addr.arpa ゾーン | 34.216.184.93.in-addr.arpa. IN PTR example.com. |
| SOA | Start of Authority。シリアル / refresh / retry / expire / minimum TTL | ns1 admin 2026051901 7200 3600 1209600 86400 |
| SRV | サービス位置情報。_service._proto.name 形式 | _sip._tcp.example.com. IN SRV 10 5 5060 sip.example.com. |
| CAA | そのドメインの証明書を発行できる CA を制限 | example.com. IN CAA 0 issue "letsencrypt.org" |
| DNSKEY / RRSIG / DS | DNSSEC の公開鍵・署名・親ゾーンの委譲署名 | 後述 §07 で詳述 |
| HTTPS / SVCB | サービスバインディング (RFC 9460, 2023)。HTTP/3 や ALPN 情報を DNS で配信 | example.com. IN HTTPS 1 . alpn="h3,h2" |
RFC 1034 で apex (例 example.com) には CNAME を置けない — 他の RR (SOA, NS, MX 等) と共存できないため。代わりに DNS ホスティング側で ALIAS / ANAME / Cloudflare の CNAME flattening といったベンダ独自機能を使う。サブドメイン (www) なら CNAME OK。
dig 実用ガイド #
dig (Domain Information Groper) は BIND 付属の DNS クエリツール。診断・トラブルシュート・パケット観察のいずれにも一番情報量が多い。これだけ覚えれば実務はだいたい片付く。
$ dig example.com
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
;; AUTHORITY SECTION:
example.com. 86400 IN NS a.iana-servers.net.
example.com. 86400 IN NS b.iana-servers.net.
;; Query time: 25 msec
;; SERVER: 8.8.8.8#53(8.8.8.8) (UDP)レコードタイプを切り替える #
$ dig example.com MX # メールサーバー
$ dig example.com NS # 権威 NS 一覧
$ dig example.com TXT # SPF / DKIM / 検証用
$ dig example.com AAAA # IPv6
$ dig example.com SOA # シリアル等の管理情報
$ dig example.com CAA # 発行可能 CA
$ dig example.com ANY # 一括 (権威によっては拒否される)問い合わせ先サーバーを明示する #
$ dig @8.8.8.8 example.com # Google Public DNS 経由
$ dig @1.1.1.1 example.com # Cloudflare
$ dig @9.9.9.9 example.com # Quad9
$ dig @ns1.example.com example.com SOA # 権威に直接 (キャッシュ迂回)反復解決のトレース #
+trace はルートから順に referral を辿る様子をそのまま出力する。「どの段階で壊れているか」 を切り分ける一番手っ取り早い方法。
$ dig +trace www.example.com
. 518400 IN NS a.root-servers.net.
; ↑ ルートからの NS 一覧 (13 系統)
com. 172800 IN NS a.gtld-servers.net.
; ↑ .com TLD への referral
example.com. 172800 IN NS a.iana-servers.net.
; ↑ example.com 権威への referral
www.example.com. 86400 IN A 93.184.216.34
; ↑ 権威からの最終回答 (AA=1)短く / 詳しく / 逆引き #
$ dig +short example.com
93.184.216.34
$ dig +noall +answer example.com
example.com. 86400 IN A 93.184.216.34
# 逆引き: IP → 名前
$ dig -x 93.184.216.34
34.216.184.93.in-addr.arpa. 86400 IN PTR example.com.DNSSEC を含めて見る #
$ dig +dnssec example.com
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2 ...
# ad フラグ (Authentic Data) が立てば DNSSEC 検証成功
example.com. 3600 IN A 93.184.216.34
example.com. 3600 IN RRSIG A 13 2 3600 ...
$ dig example.com DNSKEY +short # ゾーンの公開鍵
$ dig example.com DS +short # 上位ゾーンに置かれた鍵指紋EDNS バッファ / TCP 強制 / バルク問い合わせ #
$ dig example.com +bufsize=4096 # EDNS UDP バッファを 4096 に
$ dig example.com +tcp # TCP/53 強制 (TC=1 切詰対策)
$ dig example.com +notcp +ignore # 切詰でも TCP に上げない (動作確認)
$ dig -f domains.txt # ファイル中の名前を一括問い合わせその他のクエリツール #
dig 以外にも環境や目的で使い分けるツールがある。暗号化 DNS (DoT / DoH) の確認には kdig が一番手軽。
| ツール | 立ち位置 | 得意なこと |
|---|---|---|
| dig | BIND 付属、UNIX 標準 | 情報量最大。診断・トレース・DNSSEC・スクリプト処理すべて |
| nslookup | 古典、Windows 既定 | シンプル。Windows でちゃっと引くだけ。診断には情報不足 |
| host | BIND 付属、簡易版 | 短い出力で名前 ⇄ IP の素早い確認 |
| drill | NLnet Labs (ldns) | DNSSEC のチェイン検証を可視化 |
| kdig | Knot DNS 付属 | DoT / DoH の検証、最新拡張への追従が早い |
| whois | 登録情報照会 | 所有者・登録レジストラ・委譲 NS の確認。厳密には DNS じゃない |
$ nslookup example.com # 基本
$ nslookup example.com 8.8.8.8 # サーバー指定
$ nslookup -type=MX example.com
$ host example.com
$ host -t MX example.com
$ host -a example.com # ANY 相当
$ host 93.184.216.34 # 逆引き
$ whois example.com # 登録情報・NS 設定DNSSEC / DoT / DoH / DoQ #
素の DNS は UDP/53 の平文。経路上の ISP・公共 Wi-Fi・中間者から盗聴・改ざん・偽応答が容易だった。これに対する段階的な拡張が以下の 4 つ。DNSSEC は真正性を、DoT/DoH/DoQ は機密性を担保する — 役割が違うので組み合わせて使う。
DNSSEC — 応答の真正性を公開鍵で証明 #
RFC 4033-4035 (2005)。ゾーンに DNSKEY (公開鍵) と RRSIG (各 RR への署名) を置き、DS (子ゾーンの鍵フィンガープリント) を親ゾーンに登録することで、ルート → TLD → 権威ゾーン へと検証の連鎖 (Chain of Trust) ができる。リゾルバが検証に成功すると応答ヘッダの AD フラグ が立つ。
- DNSKEY — そのゾーンの公開鍵
- RRSIG — 各 RR セットへの署名
- DS — 親ゾーンに置かれる子の鍵フィンガープリント
- NSEC / NSEC3 — 「その名前は存在しない」ことを署名付きで証明 (NXDOMAIN の改ざん防止)
DNSSEC が保証するのは「応答が改ざんされていない」だけ。経路上の盗聴者には中身が見える。中身まで隠したいなら DoT / DoH / DoQ と組み合わせる。「真正性 (DNSSEC) × 機密性 (DoT 系)」 が完全形。
DoT (DNS over TLS, RFC 7858) #
DNS のクエリ/応答を TLS で包んで TCP/853 で送る。中継 ISP・公共 Wi-Fi の盗聴・改ざんから守る。Android 9+ の "Private DNS" や iOS 14+ で OS 全体に適用できる。
$ kdig -d @1.1.1.1 +tls example.com
;; DEBUG: TLS, imported X certificate
;; DEBUG: TLS, established
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
# ポートは 853/tcp 固定。証明書検証 OK でクエリが流れるDoH (DNS over HTTPS, RFC 8484) #
クエリを HTTPS の POST/GET でカプセル化。HTTPS と同じ TCP/443 を使うので、ファイアウォール越しに DNS だけブロックすることが難しい。Firefox / Chrome / Edge のブラウザ単独で透過的に有効化できる。
$ kdig -d @8.8.8.8 +https example.com
;; DEBUG: HTTPS session (HTTP/2)
;; DEBUG: stream id=1, response received
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34
# HTTPS POST /dns-query, content-type: application/dns-messageDoQ (DNS over QUIC, RFC 9250, 2022) #
QUIC (HTTP/3 の基盤プロトコル) 上で DNS を運ぶ最新仕様。0-RTT 接続再開 と 多重ストリーム によって DoT より低遅延。AdGuard / NextDNS など先進リゾルバが対応中。
$ kdig @dns.adguard.com +quic example.com
;; ANSWER SECTION:
example.com. 300 IN A 93.184.216.34
# UDP/443 (QUIC) で 0-RTT, 並列ストリームDoT は専用ポート 853 を使うので「DNS 通信である」ことは外から見える (中身は秘匿)。OS 全体への適用に向く。DoH は通常の HTTPS と区別がつかないため、検閲やフィルタを潜り抜けやすい — 反面、企業内では「制御外の DNS」として嫌われやすい。両者は競合より補完関係。
主な攻撃と対策 #
DNS は「信頼の起点」 であるがゆえに攻撃対象になりやすい。代表的な攻撃と、いま打てる対策をまとめる。
ダン・カミンスキーが公表した、当時すべてのリゾルバに影響した重大脆弱性。リゾルバが上位サーバーに問い合わせている隙に、攻撃者が偽応答を大量に送りつける。当時の DNS は 16 bit のトランザクション ID だけで応答を識別していたため、誕生日攻撃で偽応答が刺さりやすかった。一度キャッシュが汚染されると、TTL が切れるまで全ユーザーが偽 IP に誘導される。
対策: ソースポートのランダム化 (16+16 bit のエントロピー) — 全主要リゾルバが対応済み。根本対策は DNSSEC。
ローカルセグメント上の中間者 (ARP スプーフィング後など) が 偽の DNS 応答を返す。一般 ISP を信頼している前提が崩れるため、フリー Wi-Fi で深刻。
対策: DoT / DoH でエンドツーエンド暗号化、信頼できるリゾルバの利用、VPN 併用。
「短いクエリで大きな応答が返る」DNS の特性を悪用した 反射型 DDoS。攻撃者は送信元 IP を被害者に偽装して open recursive リゾルバへ ANY や DNSKEY を問い合わせ、リゾルバが大きな応答 (増幅率 100 倍超もある) を被害者に投げ込む。被害者の帯域が一斉に飽和する。
対策: open recursive を作らない (内部限定運用) / BCP 38 (Source Address Validation) で送信元偽装を ISP が遮断 / Response Rate Limiting (RRL) で同一送信元への大量応答を抑制。
DNS クエリ/応答にデータをエンコードして埋め込み、FW が許可している DNS チャネルを通じて C2 通信やデータ持ち出しを行う。dnscat2 / iodine 等が有名。低速だが検出が難しい。
対策: クエリの長さ・頻度・パターン監視 (異常に長い TXT 応答や、特定ドメインへの大量クエリ) / DPI / Response Policy Zone (RPZ) で既知 C2 ドメインを遮断。
old-blog.example.com のようなサブドメインが CNAME で外部サービス (GitHub Pages / Heroku / S3 / Azure 等) を指したまま、そのサービス側のリソースは削除されているケース。攻撃者が同名のリソースを作成すれば、そのサブドメインを完全に乗っ取れる — CORS や Cookie の同一オリジン保護を回避してフィッシングや MFA バイパスに直結。
対策: 退役 CNAME を必ず削除 / 定期的な棚卸し / 自動検出ツール (subjack / nuclei)。
ランダムな存在しないサブドメイン (xyz123.example.com) を大量に問い合わせる。リゾルバはキャッシュヒットせず、毎回権威サーバーに問い合わせるため、権威サーバーが過負荷になる。
対策: 権威サーバーへのレート制限 / 上流リゾルバの NXDOMAIN キャッシュ / Anycast による分散吸収。
運用のベストプラクティス #
権威 DNS / リゾルバ / ドメイン管理それぞれで「やっておけば事故が減る」基本セット。
- 権威とリゾルバは分離 — 同居させると open recursive リスクが上がる
- NS は最低 2 系統を異なる AS / 地理に置く (片方が落ちても解決継続)
- Anycast 配信で広域 DDoS を吸収 (Cloudflare / Route 53 / NS1 などのホスティングなら標準)
- DNSSEC 署名を有効化し、親ゾーンに DS を登録 (Chain of Trust 完成)
- CAA レコードで証明書発行可能な CA を絞る (誤発行・乗っ取り対策)
- SPF / DKIM / DMARC を TXT で正しく公開 — なりすましメール対策の基本
- ゾーン転送 (AXFR) は許可リストで制限 — 任意の相手にゾーン丸ごと返さない
- open recursive にしない — アクセス元 IP で必ず制限
- ソースポートランダム化が有効になっているか確認 (Kaminsky 対策)
- DNSSEC 検証を有効化 (Unbound / Knot Resolver / BIND いずれもデフォルト推奨)
- QNAME minimization (RFC 7816) — 権威に必要最小限のラベルしか送らない
- Response Rate Limiting (RRL) で増幅攻撃の踏み台化を防ぐ
- RPZ で既知マルウェア C2 / フィッシングドメインをシンクホール
- レジストラに 2FA + レジストラロックを有効化 (ドメイン乗っ取り対策)
- CNAME を退役時に必ず削除 — サブドメインテイクオーバーの起点
- TTL は用途別に設定 — 切替が必要な A は短く、組織情報の NS / MX は長く
- レコードの棚卸しを定期的に (不要 TXT / CNAME / 古い MX が残ると攻撃面が増える)
- 失効間近の証明書 / DNSKEY ロールオーバーをモニタリング