メモ的ななにか

@Maleic1618

ひとりRFCの旅 introduction && RFC1035 DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION

こんにちは、まれいんです。

この記事は ひとりRFCの旅 Advent Calender 1日目の記事です。 こんな誰得アドベントカレンダーに興味を持って下さり、ありがとうございます。

qiita.com

今回はDNSの基本中の基本、RFC1035を見て行こうと思います。

私自身は既に読んだことがあるのですが、wire formatあたりはよく出てくることになるので復習を兼ねて簡単に紹介します。

はじめに

DNSというプロトコルを理解するのに、最初にどのRFCを読むか?といわれたら間違いなく? RFC1035でしょう。 基本的な仕組み自体はRFC973で発表されていましたが、その後の議論を経てRFC973をUpdateしたものがこのRFC1035です。 歴史が知りたい人は以下の記事などが参考になりそうです。

xtech.nikkei.com

当然基本的な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オクテット以下に制限される。

分かりづらいですが、以下のようにして書き下すことができます。

  1. ドメイン名をラベルに分ける
  2. 最初のラベルの長さを1byte目にいれる
  3. ラベルのASCII文字列をそのまま2byte目以降にいれる
  4. 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                   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

おわりに

というわけで今回は基礎となるDNSwire formatを紹介しました。 実は今回紹介したものと同じようなテーマでかつもっとわかりやすい記事があるのですが、 RFCという原典に当たるというのが今回のテーマなので、今回は泥臭く説明しました。

分かりやすい記事: www.atmarkit.co.jp

次回以降も自分の興味のいくRFCを漁っていこうと思います。どうぞお楽しみに!

参考

今回のadvent calenderを書くに当たり、お世話になった、かつこれからもお世話になるサイトです。 ありがとうございます。

qiita.com DNSに関連するRFC一覧です。今でも定期的にupdateしていただけているようです。

jprs.jp DNS関連のRFCの日本語訳です。技術広報目的で、JPRSさんが訳文を提供してくださっています。 (今回の記事でも引用させていただきました。) 今後読むRFCでもすでに訳されているものがあれば積極的にこちらから引用する予定です。

DNS RFCs DNSRFCで、関連するものをまとめた系統図です。 同サイトにある「DNSRFCの歩き方」も参考になります。