ひとりRFCの旅 introduction && RFC1035 DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
こんにちは、まれいんです。
この記事は ひとりRFCの旅 Advent Calender 1日目の記事です。 こんな誰得アドベントカレンダーに興味を持って下さり、ありがとうございます。
今回はDNSの基本中の基本、RFC1035を見て行こうと思います。
私自身は既に読んだことがあるのですが、wire formatあたりはよく出てくることになるので復習を兼ねて簡単に紹介します。
はじめに
DNSというプロトコルを理解するのに、最初にどのRFCを読むか?といわれたら間違いなく? RFC1035でしょう。 基本的な仕組み自体はRFC973で発表されていましたが、その後の議論を経てRFC973をUpdateしたものがこのRFC1035です。 歴史が知りたい人は以下の記事などが参考になりそうです。
当然基本的なRFCですから、ページ数も多く73ページもあり、これを全部読んでいては日が暮れてしまいます。 というわけで重要そうな部分の概要をさらっていく方向で簡単に書いていこうと思います。
例外的に実際にパケットの中で使われるwire formatについては、自分の興味関心があるところなので、 ここについては出来るだけ触れていきます。
DNSの仕組み
仕組みについてはSect. 2.2にてがっつり語られます。 以下はスタブリゾルバ、フルサービスリゾルバ、権威サーバについての図です。
ローカルホスト | 外部 | +---------+ +----------+ | +--------+ | |ユーザーの問合わせ| |問合わせ | | | | ユーザー |-------------->| |---------|->| 外部 | | プログラム | | リゾルバー | | | ネーム | | |<--------------| |<--------|--| サーバー | | |ユーザーへの応答 | | 応答 | | | +---------+ +----------+ | +--------+ | A | キャッシュ追加 | | 参照 | V | | +----------+ | | 共有 | | | データベース | | +----------+ | A | | +---------+ リフレッシュ | | 参照 | / /| | V | +---------+ | +----------+ | +--------+ | | | | | 応答 | | | | | | | Name |---------|->| 外部 | | マスター |-------------->| Server | | | リゾルバー| | ファイル | | | |<--------|--| | | |/ | | 問合わせ| +--------+ +---------+ +----------+ | A | 保守 | +--------+ | +------------|->| | | 問合わせ | | 外部 | | | | ネーム | +------------------|--| サーバー | 保守応答 | +--------+
また、権威DNSやリゾルバの実装についても注意事項が記載されています。例えば以下のようなものです。
ネームサーバーがゾーンリフレッシュや問い合わせ処理のためにTCPデータを待っている間、 UDPリクエストのサービスをブロックするようなことは断じて許容されない。
ネームサーバーは、マスターファイルから ゾーンをリロードしたり、リフレッシュされたゾーンをデータベースに新たに 組み入れたりする際に、リクエストを大幅に遅延させるべきではない。
一般に、我々はリゾルバーが応答で受信した全データをキャッシュすることを 期待する。将来におけるクライアントリクエストへの回答に有益だろうと思われる からである。しかし、キャッシュされるべきではない幾つかのデータのタイプが 存在する。それを以下に示す。
wire format
DNSのヘッダや、主要なリソースレコードのwire formatについてもここで記載があります。 見ていきましょう。
header
Headerについては4.1.1に書いてあります。
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 | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
field | 意味 |
---|---|
ID | トランザクションID。クエリ/レスポンスで同じ値が使われる。UDP通信の場合はsource portとIDが特定できれば詐称できる(ToT) |
QR | クエリ(0) or レスポンス(1) |
Opcode | 問い合わせの種類。0以外は使われない。 |
AA | 権威サーバからの応答のときは1 |
TC | 応答が長すぎて切り詰められたかどうかのフラグ。(UDPは512bytesまで) |
RD | 再帰解決要求、スタブリゾルバがフルサービスリゾルバへ投げるときに使われる |
RA | 再帰解決が出来る場合は応答に1が設定される |
Z | reserved。現在はAD bitやCD bitがある。 |
RCODE | 応答コード。のちに拡張される |
QDCOUNT | Question sectionの数 |
ANCOUNT | Answer sectionの数 |
NSCOUNT | Authority sectionの数 |
ARCOUNT | Additional sectionの数 |
question
問い合わせについては4.1.2にあります。
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / QNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
field | 意味 |
---|---|
QNAME | 問い合わせるドメイン名 |
QTYPE | 問い合わせるリソースレコードタイプ |
QCLASS | 1しか使われない |
ちなみに、ドメイン名をパケットの中で表記するときは3.1にある、以下の表記法が使われます。(読み流してください)
メッセージに含まれるドメイン名は、ラベルの並びとして表現される。 各ラベルは、1オクテットのラベル長に、その数だけオクテットが続くもの として表現される。あらゆるドメイン名はルートのヌルラベルで終了するため、 ドメイン名はゼロが指定されたラベル長オクテットで終端される。あらゆる ラベル長オクテットの上位2ビットはゼロでなければならない。ラベル長 フィールドの残りは6ビットであるから、ラベルは63オクテット以下に制限される。
分かりづらいですが、以下のようにして書き下すことができます。
- ドメイン名をラベルに分ける
- 最初のラベルの長さを1byte目にいれる
- ラベルのASCII文字列をそのまま2byte目以降にいれる
- 2-3をルートラベル(=長さ0のラベル)まで繰り返す。
例えば、maleic1618.hatenablog.jpを表すと以下のようになります。
00000000 0a 6d 61 6c 65 69 63 31 36 31 38 0a 68 61 74 65 |.maleic1618.hate| 00000010 6e 61 62 6c 6f 67 02 6a 70 00 |nablog.jp.|
resource record
リソースレコードについては4.1.3に書いてあります。
1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
field | 意味 |
---|---|
NAME | リソースレコードの関連するドメイン名 |
TYPE | リソースレコードタイプ。Aは1、CNAMEは5など。 |
CLASS | 1固定 |
TTL | キャッシュしてよい時間。 |
RDLENGTH | RDATAのフィールド長 |
RDATA | データ部 |
RDATAは各リソースレコードタイプ毎に規定されています。 例えばAレコードは4bytes確保されてIPv4 addrが入っていますし、CNAMEは参照先のドメイン名が入っています。
ちなみに、同じドメイン名を何度も使うときのために4.1.4にポインターの仕組みが導入されています。 以下の要領でoffsetを指定してやることで他の場所に書いてあるドメイン名を参照させることができます。
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | 1 1| OFFSET | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
おわりに
というわけで今回は基礎となるDNSのwire formatを紹介しました。 実は今回紹介したものと同じようなテーマでかつもっとわかりやすい記事があるのですが、 RFCという原典に当たるというのが今回のテーマなので、今回は泥臭く説明しました。
分かりやすい記事: www.atmarkit.co.jp
次回以降も自分の興味のいくRFCを漁っていこうと思います。どうぞお楽しみに!
参考
今回のadvent calenderを書くに当たり、お世話になった、かつこれからもお世話になるサイトです。 ありがとうございます。
qiita.com DNSに関連するRFC一覧です。今でも定期的にupdateしていただけているようです。
jprs.jp DNS関連のRFCの日本語訳です。技術広報目的で、JPRSさんが訳文を提供してくださっています。 (今回の記事でも引用させていただきました。) 今後読むRFCでもすでに訳されているものがあれば積極的にこちらから引用する予定です。
DNS RFCs DNSのRFCで、関連するものをまとめた系統図です。 同サイトにある「DNSのRFCの歩き方」も参考になります。