DNS クライアントを作ってみよう (1)

前へ << UDP を使ってみよう (5) DNS クライアントを作ってみよう (2) >> 次へ

DNS クライアントとは

UDP の習作として、DNS クライアント、つまり を作りましょう。

こういう名前解決を行うコマンドは nslookup・host・dig などが有名です。 また、これとは別に OS には resolver (リゾルバまたはレゾルバ) と呼ばれるライブラリが標準で実装されています。 具体的には res_init(3), res_query(3), res_send(3) などです。

これまで本ページで作ってきたプログラムでも gethostbyname(3) や inet_aton を使用して

use Socket;
$iaddr = inet_aton("X68000.startshop.co.jp");
というふうに名前解決を行っていました。 これらのライブラリ関数も内部で res_init(3), res_query(3), res_send(3) などを呼び出しています。

今回は gethostbyname(3) を使わず、res_*(3) も使わず、 全てを自分で行うプログラムを作ります。 実用に耐えるようなライブラリを作るつもりは全くありませんが、 まーさわりだけでも作ってみれば何か得るもんがあるんちゃうの? ということで。

実際作ってみた後に nslookup や dig のマニュアルを見ると、 「ああこれはこういうことだったのね」と思えてきたりします。 ま、この学習方法が効率的かと言えば違うでしょうけれども。

DNS クライアントあれこれ

まずはコマンドを叩いてお勉強です。 ひとむかし前は DNS クライアントと言えば nslookup だったのですが (少なくとも当ページ管理人の中では)、 FreeBSD 4.7-RELEASE で nslookup を実行すると、
Note:  nslookup is deprecated and may be removed from future releases.
Consider using the `dig' or `host' programs instead.
つまり nslookup を保守している BIND のチーム自身が 「nslookup は将来はなくなるかもしれんよ。代わりに dig や host を使ってね」 と言っている始末。

そして djb 界隈では nslookupについての注意 だの、 BIND を通じて得た知識は疑ってかかりましょう だの、 BIND の呪縛 だの書かれています。

そして、当ページ管理人の環境では nslookup が全く使えないのも事実。

当ページ管理人は NAT 環境に住んでいます。DNS サーバは 192.168.0.1、つまり プライベートアドレスです。で、nslookup は起動したら DNS サーバの逆引きを行います。 数年前ならこれは問題ありませんでした。なぜなら昔は IANA がプライベートアドレスの PTR レコードを提供してくれていたので、プライベートアドレスの逆引きは成功していたからです。 しかし、数年前に IANA はそれをやめてしまいました。その理由は知りませんが、 本来プライベートアドレスをインターネット上に流すべきではないので、 IANA を責めるわけにもいきません。 その結果、現在 192.168.0.1 の逆引きは失敗してしまいます。そして nslookup は DNS サーバの逆引きに失敗したらエラーとして即座に終了し、 当ページ管理人も求める名前解決を全く行ってくれません。

よって、当ページ管理人の環境では現在 nslookup を使うことはできません。

昔は IANA がプライベートアドレスの逆引きを提供していたというのは、もしかしたら記憶違いかも。 BLACKHOLE.ISI.EDUって何ですか? read-rfc1918-for-details.iana.netって何ですか? と勘違いしているかもしれません。

というわけで nslookup には見切りを付けて、dig を使ってみることにしましょう。
と言っても、dig も nslookup と同様に BIND 開発チームによって保守されているんですけどね。

dig の使い方 - 正引き編

まずは正引きから。www.jp.FreeBSD.org の IP アドレスを引きたい場合は以下のようにします。
% dig www.jp.FreeBSD.org
; <<>> DiG 8.3 <<>> www.jp.FreeBSD.org
;; res options: init recurs defnam dnsrch
;; got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 2
;; QUERY SECTION:
;;      www.jp.FreeBSD.org, type = A, class = IN

;; ANSWER SECTION:
www.jp.FreeBSD.org.     58m41s IN A     203.139.121.132

;; AUTHORITY SECTION:
jp.FreeBSD.org.         58m41s IN NS    ns2.spnet.ne.jp.
jp.FreeBSD.org.         58m41s IN NS    castle.jp.FreeBSD.org.
jp.FreeBSD.org.         58m41s IN NS    ns.isoternet.org.

;; ADDITIONAL SECTION:
castle.jp.FreeBSD.org.  39m40s IN A     210.226.20.15
castle.jp.FreeBSD.org.  58m41s IN AAAA  2001:218:422:1::15

;; Total query time: 12 msec
;; FROM: localhost to SERVER: default -- 192.168.0.1
;; WHEN: Sun Mar 23 04:24:17 2003
;; MSG SIZE  sent: 36  rcvd: 173
うだうだ長いですが、とりあえず下線を引いた ANSWER SECTION を見てください。 あなたの求めている www.jp.FreeBSD.org の IP アドレスは 203.139.121.132 であることがわかります。

そしてあなたの投げた Query は

www.jp.FreeBSD.org, type = A, class = IN
となっています。class=IN というのは Internet ということ、 type=A は「A というタイプを要求した」ということです。 そして、
www.jp.FreeBSD.org.     58m41s IN A     203.139.121.132
この「A」は、A レコードを返したということです。

「IN は Internet だ」なんてのは即座に忘れても構いませんが、 正引きというのは「A というタイプを要求するということ」 というのはとても重要です。

本来は、どのタイプを要求するかをコマンドラインで指定します。つまり、

% dig www.jp.FreeBSD.org A
こういうことです。しかし、正引きは頻繁に行われますので、タイプ省略時には タイプ A と仮定するように dig は作られています。

dig の使い方 - 逆引き編

次に逆引きです。IP アドレス 203.139.121.132 から www.jp.FreeBSD.org を求めてみましょう。逆引きというのは PTR レコードを求めることです。 また、IP アドレス aaa.bbb.ccc.ddd の逆引きをしたい場合は、 IP アドレスをひっくりかえして最後に .in-addr.arpa を付けたもの、 つまり ddd.ccc.bbb.aaa.in-addr.arpa の PTR レコードを求めないといけません。

まとめると、203.139.121.132 の逆引きというのは 132.121.139.203.in-addr.arpa のタイプ PTR を要求すること です。つまり、

% dig 132.121.139.203.in-addr.arpa ptr
こうなります。と言っても、逆引きのたびに IP アドレスをひっくりかえすのは 面倒ですので、そういう場合は -x オプションを付けると dig が勝手に 203.139.121.132 → 132.121.139.203.in-addr.arpa の変換をしてくれます。
% dig -x 203.139.121.132 ptr
(略)
;; QUERY SECTION:
;;      132.121.139.203.in-addr.arpa, type = PTR, class = IN
(略)
;; ANSWER SECTION:
132.121.139.203.in-addr.arpa.  11h8m47s IN PTR  updraft2.jp.freebsd.org.
(略)
てっきり www.jp.FreeBSD.org が返ってくるかと思ったら、 意外にも updraft2.jp.FreeBSD.org が返ってきました。 では updraft2 の A レコードを引いてみましょう。
% dig updraft2.jp.FreeBSD.org A
(略)
;; QUERY SECTION:
;;      updraft2.jp.freebsd.org, type = A, class = IN
(略)
;; ANSWER SECTION:
updraft2.jp.freebsd.org.  5m9s IN A  203.139.121.132
(略)
updraft2 と www には同じ IP アドレス 203.139.121.132 が振られているようです。

dig の使い方 - その他編

A や PTR 以外にもいろいろなタイプがあります。タイプ AAAA は IPv6 アドレスを要求します。
% dig www.jp.freebsd.org AAAA
(略)
;; QUERY SECTION:
;;      www.jp.freebsd.org, type = AAAA, class = IN
(略)
;; ANSWER SECTION:
www.jp.freebsd.org.     11m37s IN AAAA  3ffe:501:185b:101:2a0:24ff:fe57:e561
(略)
タイプ MX はメール受信用サーバを要求するためのものです。 MX は Mail eXchanger の略で、MX レコードを使うとメールアドレスを短く記述したり、 複数のホストに属するユーザのメールを一元管理することができます。
% dig jp.freebsd.org mx
(略)
;; QUERY SECTION:
;;      jp.freebsd.org, type = MX, class = IN
(略)
;; ANSWER SECTION:
jp.freebsd.org.         1H IN MX        10 mx.jp.freebsd.org.
(略)
jp.freebsd.org の MX レコードは mx.jp.freebsd.org であることがわかります。

つまり「ユーザ名@jp.FreeBSD.org」宛にメールを送る場合は、 mx.jp.freebsd.org の SMTP サーバに接続しなければならない、 ということです。

前へ << UDP を使ってみよう (5) DNS クライアントを作ってみよう (2) >> 次へ

$Id: resolver-1.html,v 1.3 2004/06/12 05:28:24 68user Exp $