digとtcpdumpを利用してDNSの反復問い合わせの挙動を確認しよう

84件のシェア(ちょっぴり話題の記事)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。サービスグループの武田です。

インターネットを利用する上で必要不可欠なしくみとしてDNS(Domain Name System)があります。DNSはホスト名からIPアドレスを調べる名前解決のしくみですね。それではこのDNSというサーバは実際にどのように名前解決を行っているのでしょうか?

今回はコマンドを使って、簡単に挙動を確認してみましょう。

なおこの記事では、DNSサーバが階層構造となってドメイン管理をしていることの説明はしません。

問い合わせには2種類ある

DNSサーバは実際にレコードを保持して管理する DNSコンテンツサーバ と、コンテンツは保持せず問い合わせの解決と結果をキャッシュする DNSキャッシュサーバ があります。一般的にクライアント(DNS用語では スタブリゾルバ と呼ぶ)はDNSキャッシュサーバに対して問い合わせを行います。

さてDNSキャッシュサーバはコンテンツを保持していないので、スタブリゾルバから受けたリクエスを解決するには、実際にコンテンツを保持しているDNSコンテンツサーバに助けてもらう必要があります。整理すると、DNSの名前解決のしくみには次の2種類の問い合わせがあることになります。

  • スタブリゾルバがDNSキャッシュサーバに問い合わせをして名前解決をする
  • DNSキャッシュサーバがDNSコンテンツサーバに問い合わせをして名前解決をする

それぞれ次のように名前が付いています。

  • 再帰問い合わせ
  • 反復問い合わせ

普段プログラミングをしている方は、再帰と聞くと「繰り返し問い合わせるのかな?」と想像すると思いますが、繰り返し問い合わせを行うのは 反復問い合わせ の方で、「完全な結果を返してね」という意味での再帰です。

再帰問い合わせ

スタブリゾルバがDNSキャッシュサーバに問い合わせをする、ある意味一般的な問い合わせ方法です。ブラウザにURLを入力したときや、pingコマンドでホスト名を指定したときなど、日常のさまざまな場面で利用されています。

それではコンソールを2つ起動して、再帰問い合わせの挙動を確認してみましょう。

順序としては、先にtcpdumpコマンドを実行してキャプチャ状態にしてから、digコマンドを実行します。

$ dig www.classmethod.jp

; <<>> DiG 9.8.3-P1 <<>> www.classmethod.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15452
;; flags: qr rd ra; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.classmethod.jp.		IN	A

;; ANSWER SECTION:
www.classmethod.jp.	300	IN	CNAME	classmethod.jp.
classmethod.jp.		16	IN	A	52.222.201.44
classmethod.jp.		16	IN	A	52.222.201.39
classmethod.jp.		16	IN	A	52.222.201.210
classmethod.jp.		16	IN	A	52.222.201.195
classmethod.jp.		16	IN	A	52.222.201.75
classmethod.jp.		16	IN	A	52.222.201.170
classmethod.jp.		16	IN	A	52.222.201.36
classmethod.jp.		16	IN	A	52.222.201.239

;; Query time: 23 msec
;; SERVER: 192.168.100.1#53(192.168.100.1)
;; WHEN: Thu Feb  8 19:05:16 2018
;; MSG SIZE  rcvd: 178
$ sudo tcpdump -n -vv dst port 53
19:05:16.787159 IP (tos 0x0, ttl 64, id 42967, offset 0, flags [none], proto UDP (17), length 64)
    192.168.100.192.55377 > 192.168.100.1.53: [udp sum ok] 15452+ A? www.classmethod.jp. (36)

tcpdumpの結果を見ると、クエリは一度のみ送信されています。送信先は192.168.100.1となっていますが、これは実行環境のルータのIPアドレスです。つまりこの場合は、ルータがDNSキャッシュサーバということになります。

反復問い合わせ

スタブリゾルバから問い合わせを受けたDNSキャッシュサーバが、DNSコンテンツサーバに繰り返し問い合わせをして、名前解決をする問い合わせ方法です。通常、エンドユーザーからは見えず、DNSサーバが裏で実行しています。

それではコンソールを2つ起動して、反復問い合わせの挙動を確認してみましょう。

$ dig www.classmethod.jp +trace

; <<>> DiG 9.8.3-P1 <<>> www.classmethod.jp +trace
;; global options: +cmd
.			306961	IN	NS	j.root-servers.net.
.			306961	IN	NS	k.root-servers.net.
.			306961	IN	NS	l.root-servers.net.
.			306961	IN	NS	m.root-servers.net.
.			306961	IN	NS	a.root-servers.net.
.			306961	IN	NS	b.root-servers.net.
.			306961	IN	NS	c.root-servers.net.
.			306961	IN	NS	d.root-servers.net.
.			306961	IN	NS	e.root-servers.net.
.			306961	IN	NS	f.root-servers.net.
.			306961	IN	NS	g.root-servers.net.
.			306961	IN	NS	h.root-servers.net.
.			306961	IN	NS	i.root-servers.net.
;; Received 508 bytes from 192.168.100.1#53(192.168.100.1) in 36 ms

jp.			172800	IN	NS	a.dns.jp.
jp.			172800	IN	NS	b.dns.jp.
jp.			172800	IN	NS	c.dns.jp.
jp.			172800	IN	NS	d.dns.jp.
jp.			172800	IN	NS	e.dns.jp.
jp.			172800	IN	NS	f.dns.jp.
jp.			172800	IN	NS	g.dns.jp.
jp.			172800	IN	NS	h.dns.jp.
;; Received 492 bytes from 199.7.83.42#53(199.7.83.42) in 283 ms

classmethod.jp.		86400	IN	NS	ns-266.awsdns-33.com.
classmethod.jp.		86400	IN	NS	ns-1421.awsdns-49.org.
classmethod.jp.		86400	IN	NS	ns-1722.awsdns-23.co.uk.
classmethod.jp.		86400	IN	NS	ns-576.awsdns-08.net.
;; Received 176 bytes from 203.119.40.1#53(203.119.40.1) in 27 ms

www.classmethod.jp.	300	IN	CNAME	classmethod.jp.
classmethod.jp.		60	IN	A	52.222.201.44
classmethod.jp.		60	IN	A	52.222.201.39
classmethod.jp.		60	IN	A	52.222.201.210
classmethod.jp.		60	IN	A	52.222.201.170
classmethod.jp.		60	IN	A	52.222.201.36
classmethod.jp.		60	IN	A	52.222.201.195
classmethod.jp.		60	IN	A	52.222.201.239
classmethod.jp.		60	IN	A	52.222.201.75
classmethod.jp.		172800	IN	NS	ns-1421.awsdns-49.org.
classmethod.jp.		172800	IN	NS	ns-1722.awsdns-23.co.uk.
classmethod.jp.		172800	IN	NS	ns-266.awsdns-33.com.
classmethod.jp.		172800	IN	NS	ns-576.awsdns-08.net.
;; Received 318 bytes from 205.251.198.186#53(205.251.198.186) in 234 ms
$ sudo tcpdump -n -vv dst port 53
19:15:35.380966 IP (tos 0x0, ttl 64, id 39190, offset 0, flags [none], proto UDP (17), length 45)
    192.168.100.192.62067 > 192.168.100.1.53: [udp sum ok] 12674 NS? . (17)
19:15:35.418101 IP (tos 0x0, ttl 64, id 53452, offset 0, flags [none], proto UDP (17), length 64)
    192.168.100.192.58115 > 199.7.83.42.53: [udp sum ok] 57530 A? www.classmethod.jp. (36)
19:15:35.701870 IP (tos 0x0, ttl 64, id 53379, offset 0, flags [none], proto UDP (17), length 64)
    192.168.100.192.54363 > 203.119.40.1.53: [udp sum ok] 8216 A? www.classmethod.jp. (36)
19:15:35.729498 IP (tos 0x0, ttl 64, id 22194, offset 0, flags [none], proto UDP (17), length 64)
    192.168.100.192.54373 > 205.251.198.186.53: [udp sum ok] 4630 A? www.classmethod.jp. (36)

digコマンドに+traceオプションをつけると反復問い合わせの流れを確認できます。tcpdumpの結果とdigの結果を突き合わせると、次のような流れになっていることがわかります。

  1. 192.168.100.1.(ルートネームサーバ)を問い合わせ
    • ルートネームサーバとして13個教えてもらった
  2. 199.7.83.42www.classmethod.jp.を問い合わせ
    • 1の結果(ルートネームサーバ)のうちの1つに再度問い合わせている
    • jp.のネームサーバとして8個教えてもらった
  3. 203.119.40.1www.classmethod.jp.を問い合わせ
    • 2の結果(jp.ドメインのネームサーバ)のうちの1つに再度問い合わせている
    • classmethod.jp.のネームサーバとして4個教えてもらった
  4. 205.251.198.186www.classmethod.jp.を問い合わせ
    • 3の結果(classmethod.jp.ドメインのネームサーバ)のうちの1つに再度問い合わせている
    • www.classmethod.jp.のIPアドレスを8個教えてもらった

これで本来の目的であったwww.classmethod.jpの名前解決ができました。DNSキャッシュサーバは、スタブリゾルバから再帰問い合わせを受けると、今確認したような流れで反復問い合わせを行い、結果を返しているわけです。

まとめ

digコマンドとtcpdumpコマンドを利用して、DNSクエリの流れを簡単に追ってみました。再帰問い合わせと反復問い合わせを理解すると、DNSの理解も一気に進むのではないでしょうか。

みなさんもぜひ、いろいろ試してみてください。