セクションは5種類ありますが、1つのDNSメッセージにすべてのセクションが含まれている訳ではありません。問い合わせや応答を行うプログラム(リゾルバ&ネームサーバー)が、必要なセクションを組み合わせてDNSメッセージを構成します。
ヘッダ部は必須(1つのメッセージに1つのヘッダ)ですが、ヘッダ以外のセクションは状況によってその数が変化します。またヘッダ部のサイズは12バイト固定長ですが、他のセクションは可変長になっています。
ヘッダ部のサイズは12バイト固定長で、次の項目で構成されています。下の表は1行が2バイト(16ビット)に相当します。
ID |
QR | OPCode | AA | TC | RD | RA | Z | RCode |
QDCount |
ANCount |
NSCount |
ARCount |
- ID (IDentification) [size : 16bit]
メッセージ識別用のID。
問い合わせ送出側が設定する数値で、応答メッセージにコピーされます。
問い合わせ側はIDをチェックすることで、問い合わせと応答の対応を確認します。
- QR (Query/Response) [size : 1bit]
メッセージが[問い合わせ]なのか[応答]なのかを示すフラグ。
- OPCode (OPeration Code) [size : 4bit]
問い合わせのタイプを数値で示します。値は次の意味を持ちます。
0 | : | 標準問い合わせ (Standard Query)
通常(正引き、逆引き)の問い合わせ。
|
1 | : | 逆問い合わせ (Inverse Query)
例えば、Aレコードはホスト名からIPアドレスを検索する目的で記述されますが、このAレコードを対象にして、IPアドレスからホスト名を検索することを逆問い合わせといいます。この機能は、あまりサポートされてないようです。
|
2 | : | サーバーの状態 (STATUS) |
- AA (Authoritative Answer) [size : 1bit]
問い合わされたドメイン(ホスト)名に、権威を持っているネームサーバーの応答か否かを示すフラグ。(応答メッセージでのみ有効)
0 | : | 権威を持っていないネームサーバーの応答。
|
1 | : | 権威を持っているネームサーバーの応答。 |
- TC (TrunCation) [size : 1bit]
応答メッセージのサイズが既定値(512バイト)を超えたことを示すフラグ。
ネームサーバーは応答メッセージが512バイトを超えてしまう時、512バイト以降のメッセージを切り捨て TC=1 にセットします。
TC=1 の応答メッセージを受けた問い合わせ元は、通信方式をTCP(Transmission Control Protocol)に変更して問い合わせをやり直します。
- RD (Recursion Desired) [size : 1bit]
再帰要求のフラグ。
RD=1 のセットは、問い合わせ先のネームサーバーに再帰的な処理を要求します。
0 | : | 反復的処理を要求。 |
1 | : | 再帰的処理を要求。 |
- RA (Recursion Available) [size : 1bit]
再帰可能のフラグ。(応答メッセージでのみ有効)
ネームサーバーが再帰的な問い合わせをサポートしているか否かを表します。
0 | : | 再帰的問い合わせをサポートしていない。 |
1 | : | 再帰的問い合わせをサポートしている。 |
- Z (Zero) [size : 3bit]
将来の拡張用です。常に 0 にしておきます。
- RCode (Reply Code) [size : 4bit]
応答コード。問い合わせの処理状況を表します。
0 | : | エラーなし。 |
1 | : | フォーマットエラー。解釈できない問い合わせ。 |
2 | : | サーバー障害。 |
3 | : | ドメイン(ホスト)名エラー。 問い合わせで指定されたドメイン(ホスト)名が存在しない。 |
4 | : | 未実装。要求された種類の問い合わせをサポートしていない。 |
5 | : | 拒否。ネームサーバーに設定されたアクセス制御等により、要求や問い合わせが拒否された。 |
- QDCount(Query Count) [size : 16bit]
問い合わせ部のエントリ数。(問い合わせの数)
- ANCount(ANswer Count) [size : 16bit]
回答部の資源レコード数。
- NSCount(Authority Count) [size : 16bit]
権威部の資源レコード数
- ARCount(Additional information Count) [size : 16bit]
付加情報部の資源レコード数。
問い合わせ内容を定義する以下の項目で構成されます。各項目のサイズは固定長の部分と可変長の部分があります。
問い合わせ部のエントリ数はヘッダ部のQDCountにセットされますが、通常は1つです。
- QNAME (Query NAME) [size : 可変長]
問い合わせのドメイン(ホスト)名を、下記要領で変換して格納します。
- 各ラベルの先頭に、そのラベルの文字数を6ビットの数値で付加します。
- ラベルを連結しているドット(.)は省略します。
- ルートドメインの部分は文字数 0x00 が入ります。
0x00(いわゆるNULL)は、QNAMEの末尾(終了部)を表すことになります。
例えば www.project.ed.jp. は次のように変換されます。
変換前の文字 | | w | w | w | . | p | r | o | j | e | c | t | . | e | d | . | j | p | . |
ASCIIコード | 03 | 77 | 77 | 77 | 07 | 70 | 72 | 6F | 6A | 65 | 63 | 74 | 02 | 65 | 64 | 02 | 6A | 70 | 00 |
- QTYPE (Query TYPE) [size : 16bit]
問い合わせる資源レコードのタイプを2バイト(16ビット)の数値で指定します。
代表的なタイプは以下の通りです。
数値 | 1 | 2 | 5 | 6 | 12 | 13 | 14 | 15 |
レコードタイプ | A | NS | CNAME | SOA | PTR | HINFO | MINFO | MX |
- QCLASS (Query CLASS) [size : 16bit]
問い合わせる資源レコードのクラスを2バイト(16ビット)の数値で指定します。
現在は IN(internet) 用を表す 1 のみが使われています。
ネームサーバーは、問い合わせ部のQNAME(ドメイン/ホスト名), QTYPE(資源レコードタイプ)に一致する資源レコードを検索し、一致した資源レコードのデータを下記フォーマットで記述します。回答部の数はヘッダ部のANCountにセットされます。
NAME |
TYPE |
CLASS |
TTL |
RDLENGTH |
RDATA |
- NAME [size : 可変長]
資源レコードを定義しているドメイン(ホスト)名。資源レコードのowner欄と同じ名称になります。
名称の記述は問い合わせ部のQNAMEと同じ要領で変換されますが、応答メッセージ内にすでに同じような名称がある場合、それを利用してメッセージの圧縮を行います。
- TYPE [size : 16bit]
資源レコードのタイプを2バイト(16ビット)の数値で表します。タイプと数値の対応は問い合わせ部のQTYPEを参照して下さい。
- CLASS [size : 16bit]
資源レコードのクラス。問い合わせ部のQCLASSと同じになります。
- TTL [size : 32bit]
資源レコードの有効期間(キャッシュ用)。資源レコードのttl欄と同じ値になります。
- RDLENGTH [size : 16bit]
RDATAの長さをバイト(8ビット)単位で示します。長さにはラベルを表している文字列の外に、ラベルの文字数、メッセージ圧縮の記号も含みます。
- RDATA [size : 可変長]
資源レコードの資源の部分(name-server-dname, address, canonical-name等)が入ります。SOAレコードの場合はsource-dname, mbox, serial〜minimumまで入ります。
このフィールドに記述されるドメイン(ホスト)名も問い合わせ部のQNAMEと同じ要領で変換され、メッセージ圧縮の対象になります。
回答部と同じフォーマットで、権威部の数はヘッダ部のNSCountにセットされます。
回答部の資源レコードに対して権威を持っているNSレコードのデータが入ります(省略されることもあるようです)。参照先ネームサーバーのNSレコードも権威部に記述されます。
問い合わせの内容が存在しないホスト(サブドメイン)や資源レコードの時には、権威部にはSOAレコードが記述されます。
回答部と同じフォーマットで、付加情報部の数はヘッダ部のARCountにセットされます。
回答部や権威部に対応した資源レコード(Aレコード)がある時、そのデータは付加情報部に記述されます(省略されることもあるようです)。
DNSメッセージは資源レコードを扱っているため、同じドメイン(ホスト)名が多数含まれていることがあります。同じ名称をいくつも記述する代わりに、すでに記述してある位置の情報(ポインタ)を示して同じ内容であるということにすれば、メッセージサイズを抑えることができます。DNSメッセージのこうした操作をメッセージの圧縮といいます。
記述位置を示すポインタは、2ビットのフラグと14ビットのoffset(合計16ビット:2バイト)で構成されます。
- flag
先頭2ビットのフラグによって、ポインタ前半(1バイト:8ビット)の残り6ビットは次のように判断されます。
フラグ | フラグの意味 |
11 | ポインタ。残り6ビットと、後続の8ビット(計14ビット)はoffset。 |
10 | ポインタ拡張用に予約。 |
01 | ポインタ拡張用に予約。 |
00 | ラベル文字数。残り6ビットはラベル文字数。 |
- offset
記述済みドメイン(ホスト)名の位置が、DNSメッセージの先頭から何バイト離れているかを示す情報で、DNSメッセージの先頭を 0 (ゼロ)として算出します。
ポインタはドメイン(ホスト)名の代わりに記述されます。DNSメッセージのドメイン名欄のデータは、ラベル文字なのかポインタなのか、ラベル文字数(ポインタ前半)欄の先頭2ビットを見ないと判断できません。
先頭の2ビットが"11"であれば、続く14ビットはポインタのoffset、"00"なら続く6ビットはラベル文字数と解釈されます。
メッセージの圧縮はどのようなものか、以下にその例を示します。
【 例1. Aレコード検出時の応答 】
下表は、IPアドレスの問い合わせ [QNAME=www.project.ed.jp.、QTYPE=A (ホスト名 → IPアドレス検索)] に対する応答メッセージで、該当ホスト名のAレコードが検出された結果のイメージです。
分かり易くするためラベル名以外の項目は省略し、ラベル名もASCIIコードではなくアルファベットで表現しています。
addr | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0000 | ヘッダ部 | 03 | w | w | w |
0010 | 07 | p | r | o | j | e | c | t | 02 | e | d | 02 | j | p | 00 | Q- |
0020 | -TYPE | QCLASS | C0 | 0C | TYPE | CLASS | TTL | RDLENGTH |
0030 | IP-address | 権威部 |
0040 | 以下省略 |
ヘッダ部に続く 0x000C 〜 0x0023 がコピーされた問い合わせ部、0x0024 〜 0x0033 が回答部になります。
回答部(0x0024〜)の先頭には NAME欄 があります。この位置(赤で表示)を見ると、0xC0(ビット表示:1100 0000) となっていてポインタであることが分かります。
ポインタのoffsetは直後のデータ 0x0C を連結した値 0x000C になるので、ここを参照先(青で表示)として組み立てた文字列が NAME と解釈されます。
参照先address | data | 摘要 |
0x000C | 03 | 文字数 = 3 |
0x000D 〜 0x000F | 文字コード | www (3文字) |
0x0010 | 07 | 文字数 = 7 |
0x0011 〜 0x0017 | 文字コード | project (7文字) |
0x0018 | 02 | 文字数 = 2 |
0x0019 〜 0x001A | 文字コード | ed (2文字) |
0x001B | 02 | 文字数 = 2 |
0x001C 〜 0x001D | 文字コード | jp (2文字) |
0x001E | 00 | 文字数 = 0 |
文字数 = 0 となったところ(ルート)で文字列の組み立ては終了し、今回の場合は www.project.ed.jp.が得られます。
【 例2. CNAMEレコード検出時の応答 】
上記はホスト名全体が一致した場合の例ですが、後半部分が一致した時にもメッセージの圧縮は行われます。例えば該当ホスト名のレコードがCNAMEだった時の応答メッセージは以下のようになります。
例として www.project.ed.jp. の正規名は nsw.project.ed.jp. であると仮定します。
addr | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
0000 | ヘッダ部 | 03 | w | w | w |
0010 | 07 | p | r | o | j | e | c | t | 02 | e | d | 02 | j | p | 00 | Q- |
0020 | -TYPE | QCLASS | C0 | 0C | TYPE | CLASS | TTL | RDLENGTH |
0030 | 03 | n | s | w | C0 | 10 | C0 | 30 | TYPE | CLASS | TTL |
0040 | RDLENGTH | IP-address | 権威部 |
0050 | 以下省略 |
ヘッダ部とコピーされた問い合わせ部は前回と同じですが、その後には2つの回答部が続きます。それぞれのメッセージ圧縮の部分を見てみましょう。
- 1つ目の回答部 [CNAMEレコード] 0x0024 〜 0x0035
- NAME欄には[Aレコード検出時の応答]と同じポインタフラグとoffsetがあります。同じ処理が行われて、NAMEは www.project.ed.jp.と解釈されます。
- CNAMEレコードのRDATA欄にはホストの正規名が入ります。今回のRDATA欄は 0x0030 〜 0x0035 に割り当てられていて次のように解釈されます。
RDATA | data | 摘要 |
0x0030 | 03 | 文字数 = 3 |
0x0031 〜 0x0033 | 文字コード | nsw (3文字) |
0x0034 | C0 | ポインタフラグ ON |
0x0035 | 10 | offsetは 0x0010 |
nsw 以降はポインタの指示する参照先をルートまで連結して完成します。
参照先address | data | 摘要 |
0x0010 | 07 | 文字数 = 7 |
0x0011 〜 0x0017 | 文字コード | project (7文字) |
以下省略 (【例1. Aレコード検出時の応答】を参照) |
正規ホスト名は nsw.project.ed.jp. と解釈されます。
- 2つ目の回答部 [Aレコード] 0x0036 〜 0x0045
NAME欄(0x0036〜)はポインタになっています。offsetは 0x0030 になっていて、1つ目回答部 [CNAMEレコード]のRDATA欄の先頭を指しています。
参照先にもポインタがありますが、CNAMEレコードの正規ホスト名の時と同じ処理が行われて、NAME=nsw.project.ed.jp. と解釈されます。
この値を 0 にセットします。