【DNS入門 第5回】リソースレコード前編 ― ゾーンファイルの書き方とSOA・NS・A/AAAA・CNAME

DNS サーバー
スポンサーリンク
スポンサーリンク

「example.jpそのものをCDNに向けたいので、CNAMEを書いたらエラーになりました」
「MXを追加したのに、メールが届きません」

どちらも、リソースレコードのルールを知っていれば防げるトラブルです。後者は、たった1文字(末尾のドット)が原因ということもよくあります。

第4回では、DNSメッセージの「入れ物」を見ました。第5回と第6回では、その中身であるリソースレコードを見ていきます。前編の今回は、ゾーンファイルの書き方と、ゾーンの骨格になるSOA・NS・A/AAAA・CNAMEです。メールや証明書に関わるレコードは後編で扱います。


ゾーンファイルの書き方

まずは、BINDなどで使われるゾーンファイルの書き方です。Route 53などのクラウドのDNSでも、インポート・エクスポートの形式として使われるので、読めるようにしておくと役に立ちます。

$ORIGIN example.jp.
$TTL 3600
@       IN  SOA   ns1.example.jp. hostmaster.example.jp. (
                  2026092501 ; シリアル
                  3600 900 1209600 900 )
        IN  NS    ns1.example.jp.
        IN  NS    ns2.example.jp.
        IN  MX    10 mail.example.jp.
@   300 IN  A     192.0.2.10
www     IN  CNAME example.jp.
ns1     IN  A     192.0.2.53
ns2     IN  A     198.51.100.53
mail    IN  A     192.0.2.25
ゾーンファイルの1行が名前・TTL・クラス・タイプ・値の順に並ぶことと、$ORIGIN・$TTL・@・コメント・括弧・空白で始まる行の意味を注釈した図

読み方のルールは次のとおりです。

  • 1行が1レコード:名前・TTL・クラス(IN)・タイプ・値の順。TTLを省くと$TTLの値になる
  • $ORIGIN:相対名に付け足すドメイン名。@は$ORIGINそのもの(ゾーンの頂点)
  • 名前の欄が空白で始まる行は、直前の行と同じ名前になる(上のNS・MXは@のもの)
  • ;から行末まではコメント。( )で1つのレコードを複数行に分けて書ける

3つ目のルールは要注意です。見やすくしようと字下げのつもりで入れた空白で、名前が変わってしまう事故が起きます。


相対名と末尾のドットの落とし穴

第2回で触れた「末尾のドット」が、ゾーンファイルでは特に効いてきます。末尾にドットが無い名前は、$ORIGINが付け足された相対名として扱われます。

書いた値($ORIGIN example.jp.)解釈される名前判定
wwwwww.example.jp.正しい(相対名)
www.example.jp.www.example.jp.正しい(FQDN)
@example.jp.正しい(頂点)
www.example.jp(ドットなし)www.example.jp.example.jp.誤り
MX 10 mail.example.jp(ドットなし)mail.example.jp.example.jp.誤り(メールが届かない)
CNAME cdn.example.net(ドットなし)cdn.example.net.example.jp.誤り(引けない)

厄介なのは、構文としては正しいため、ドット忘れがエラーにならないことが多い点です。冒頭の「MXを追加したのにメールが届かない」の正体が、このドット忘れだったということもよくあります。

反映前にnamed-checkzoneで読み込みを確認し、反映後はdigで実際の値を確かめる、という2段構えにしましょう。

$ named-checkzone example.jp /var/named/example.jp.zone
zone example.jp/IN: loaded serial 2026092501
OK

SOA:ゾーンの「表紙」

SOA(Start Of Authority)は、ゾーンの頂点に必ず1つだけ置く、ゾーン全体の管理情報です。

フィールド意味値の目安
MNAMEプライマリの権威DNSサーバー名ns1.example.jp.
RNAME管理者のメールアドレス(@を.に置き換える)hostmaster.example.jp.
SERIALゾーンの版番号。増えたときだけ転送されるYYYYMMDDnn(第7回)
REFRESHセカンダリが更新を確認する間隔3600〜86400秒(NOTIFYを使うなら長めでよい)
RETRY確認に失敗したときの再試行の間隔600〜3600秒(REFRESHより短く)
EXPIRE更新できないまま、ゾーンを捨てるまでの時間1209600〜2419200秒(2〜4週間、RFC 1912)
MINIMUMネガティブキャッシュのTTL300〜3600秒(RFC 2308は1〜3時間を例示)

REFRESH・RETRY・EXPIREの3つは、セカンダリの動きを決めるタイマーです。

セカンダリがREFRESHごとにプライマリのSOAを確認し、プライマリ停止後はRETRYごとに再試行し、EXPIREを過ぎるとゾーンを捨てて応答をやめることを示すタイムライン

注意点が2つあります。

  • MINIMUMの意味は変わった:RFC 1035では既定のTTLでしたが、RFC 2308でネガティブキャッシュのTTLに意味が変わりました(第3回)。古い手順書の86400をそのまま使うと、「追加したのに1日引けない」が起きます。
  • EXPIREを短くしすぎない:短くしすぎると、プライマリが止まった連休中に、セカンダリが応答をやめてしまいます。

NS:ゾーンの権威DNSサーバー

NS(Name Server)レコードは、そのゾーンの権威DNSサーバーを示します。第2回で見たとおり、NSは2か所に現れます。

  • 親ゾーンに置かれた、委任のためのNS
  • 自分のゾーンの頂点に置くNS
親ゾーンjpの委任のNS・グルーと、子ゾーンexample.jpの頂点のNSを一致させ、ns1とns2を別の拠点に置くことを示す図

両者の内容は一致させます。一致していない状態や、NSに書かれたサーバーがそのゾーンに答えない状態はlame delegationと呼ばれ、断続的な名前解決の失敗の典型的な原因です。キャッシュDNSがどのNSを選ぶかは毎回変わるので、「ときどき引けない」という症状になります。

NSのルールも押さえておきましょう。

  • 値には、A/AAAAレコードで解決できるホスト名を書く
  • IPアドレスを直接書くことはできず、CNAMEの名前を書くことも禁止されている(RFC 2181)
  • NSのホスト名が自分のゾーンの中にあるときは、親ゾーンにグルーレコードが必要
  • 可用性のため、権威DNSサーバーは少なくとも2台とし、別のネットワークや別の拠点に分けて置く(RFC 2182)

ポイント
・親の委任のNSと、子の頂点のNSを一致させる
・値はA/AAAAで引けるホスト名。IPアドレスやCNAMEは不可
・2台以上を、別のネットワーク・拠点に分けて置く


AとAAAA:DNSラウンドロビンの誤解

Aレコードは名前にIPv4アドレスを、AAAAレコードはIPv6アドレスを対応づける、最も基本的なレコードです(Aが4つで128ビット、と覚えます)。

1つの名前に複数のA/AAAAを置くことができ、これを負荷分散に使う方法をDNSラウンドロビンと呼びます。

www.example.jpのDNSの答えとして2つのAと1つのAAAAが返り、Happy Eyeballsのクライアントが複数のアドレスへ並行して接続を試し、停止中のアドレスにも答えが返ることを示す図

ただし、ここには大きな誤解が潜んでいます。

  • どのアドレスを使うかは、クライアントの実装しだいで、並び順どおりとは限らない
  • 現在のOSやブラウザーは、複数のアドレスへ並行して接続を試すHappy Eyeballs(RFC 8305)を使うため、並び順の意味はさらに薄れている
  • DNSにはヘルスチェックが無く、止まったサーバーのアドレスも返し続ける

つまり、DNSラウンドロビンを可用性の対策と考えてはいけません。1台止まっても、DNSはそのアドレスを返し続けます。止まったサーバーを外すには、ロードバランサーや、ヘルスチェック付きのDNSサービス(第10回のRoute 53のフェイルオーバーなど)を使います。

一方、別々の名前が同じIPアドレスを指すのは問題ありません。1台で複数の役割を持つ場合の、普通の書き方です。


CNAMEの制約

CNAME(Canonical NAME)は、ある名前を別の名前の別名にするレコードです。CDNやSaaSに独自ドメインを向ける公式の手順として広く使われますが、守るべき制約があります。

正しいCNAMEの例と、頂点にCNAMEを置く、MXの値がCNAMEの名前、CNAMEと別のレコードが同居するという3つの誤りの例を示す図

1. CNAMEを置いた名前には、他のレコードを置けない(RFC 1034。DNSSECの署名などを除く)
ゾーンの頂点には必ずSOAとNSがあるため、example.jpそのものにはCNAMEを置けません。冒頭の「頂点にCNAMEを書いたらエラー」はこれです。

2. MX・NS・SRVの値に、CNAMEの名前を書いてはいけない(RFC 2181 等)

3. 1つの名前に複数のCNAMEは置けない
負荷分散のつもりで2つ書くと、どちらが使われるかは決まりません。

CNAMEの先がまたCNAMEというCNAMEチェーンは、遅くなり障害の原因も増えるため避けます。値の末尾のドットも忘れないようにしましょう。CNAMEは、その名前のすべてを別の名前に置き換える、と覚えておくとルールを思い出しやすくなります。

ポイント
・CNAMEは他のレコードと共存不可。頂点には置けない
・MX・NS・SRVの値にCNAMEの名前を書かない
・1つの名前にCNAMEは1つ。チェーンは避ける


頂点を別名で向ける:ALIAS・ANAME・Route 53エイリアス

では、example.jpそのものをクラウドのロードバランサーやCDNに向けたいときは、どうすればよいのでしょうか。

頂点にはCNAMEを置けないが、Route 53エイリアスならキャッシュDNSのA問い合わせにALBのIPアドレスをAレコードとして直接返し、IPを自動で追従することを示す図
方式仕組み頂点に置けるか注意
CNAME別名を返し、続きはリゾルバーが解決する置けない標準の仕組み。どのDNSでも使える
Route 53 エイリアスRoute 53が、ALB・CloudFront等のIPアドレスをA/AAAAとして直接返す置けるAWSのリソース宛ての問い合わせは無料。TTLは指定できない
ALIAS/ANAME、CNAMEフラット化権威DNSが裏で名前を解決し、結果をA/AAAAとして返す置ける各DNS事業者の独自機能。標準化されていない
HTTPS レコード(AliasMode)頂点から別の名前へ、標準の仕組みで向ける置ける対応するクライアントだけが使う(第6回)

つまり、頂点では、名前ではなくアドレスで答える仕組みを使います。

$ dig example.jp A +short          # Route 53 エイリアスで ALB に向けた例
192.0.2.80
192.0.2.81

PS> (Resolve-DnsName example.jp -Type A).IPAddress   # PowerShell で値だけ

Route 53のエイリアスは、digでは普通のAレコードとして見え、エイリアスかどうかはRoute 53の画面やAPIでしか分かりません。独自機能なので、DNS事業者を移すときは、同じ機能があるかを確認しましょう(第10回)。


ワイルドカード

最後に、ワイルドカードです。

*.example.jp.     3600 IN A 192.0.2.10
www.example.jp.   3600 IN A 192.0.2.20
*.example.jpとwww.example.jpがあるとき、存在しない名前には*から答えが合成され、存在する名前や頂点には効かないことを示す図
  • abc.example.jpやa.b.example.jpのように存在しない名前の問い合わせには、*のレコードから答えが合成される(192.0.2.10)
  • 存在する名前には効かない:www.example.jpのMXを聞いても、ワイルドカードは使われずNODATAになる。x.www.example.jpもNXDOMAIN(RFC 4592)
  • example.jp(頂点そのもの)には効かない。ワイルドカード証明書*.example.jpが1階層だけに効くのとは規則が違う点にも注意

便利な反面、注意点もあります。

  • 打ち間違えた名前まで引けてしまい、設定の誤りに気づきにくい。searchドメイン(第3回)と組み合わさると、意図しない名前が解決されることがある
  • 外部サービスへ向けたワイルドカードのCNAMEは、サブドメインの乗っ取り(第9回)の入り口になり得る。使う範囲は最小限にする

考えてみよう

  1. 自社のドメイン名(例:example.jp)そのもので、クラウドのロードバランサーやCDNに向けたい場合、どのような方法がありますか。DNS事業者を変えるときの影響も考えてみましょう。
  2. ゾーンファイルを手で編集する運用で、ドット忘れや空白の事故を防ぐには、どんな確認の手順を入れればよいでしょうか。
  3. 自社の権威DNSサーバーは何台あり、それぞれどこに置かれていますか。親ゾーンのNSと一致していますか。

ヒント:この記事の「頂点を別名で向ける」「相対名と末尾のドットの落とし穴」「NS」が手がかりです。


まとめ

  • ゾーンファイルは1行1レコード。空白で始まる行は直前と同じ名前
  • 末尾のドット忘れはエラーにならない。named-checkzoneとdigの2段構えで確認
  • SOAのMINIMUMはネガティブキャッシュのTTL。EXPIREは短くしすぎない
  • NSは親と子で一致させ、2台以上を別の場所に。ずれるとlame delegation
  • DNSラウンドロビンは可用性の対策ではない
  • CNAMEは頂点に置けない。頂点はRoute 53エイリアスやALIASで向ける

次回(後編)は、メール(MX・SPF・DKIM・DMARC)、SRV・PTR、証明書(CAA)、そして新しいHTTPS/SVCBレコードを扱います。


連載「DNS入門」全12回

  1. DNSとは?名前解決の全体像と3つの登場人物
  2. ドメイン名の階層と委任
  3. 名前解決の流れ
  4. DNSメッセージとトランスポート
  5. リソースレコード 前編(この記事)
  6. リソースレコード 後編
  7. 権威DNSサーバーの運用
  8. コマンドで調べる
  9. DNSのセキュリティ
  10. クラウド・社内環境のDNS
  11. DNSトラブルシュート
  12. DNS設計演習

コメント

タイトルとURLをコピーしました