PerlのNet::DNSモジュールを使用して、DNSに問い合わせを行ってみる。
Net::DNSモジュールのインストール
標準ではNet::DNSがインストールされていないため、cpanにてインストールを行う。
$ su -
Password: **********
# perl -MCPAN -e shell
cpan>install Net::DNS
これでインストールは完了。
cpanを最初に利用する場合は設定などを聞かれるが、私の場合、ほぼ全てを初期値のままで設定した。「Asia」、「Japan」とダウンロード先のサーバを指定した程度だ。
Windowsの場合はPPMなどを利用すると良いだろう。その辺りのことについては別の機会に投稿しようと思う。
正引き(ホスト名→IPアドレス)
ホスト名からIPアドレスを取得する。
use strict;
use Net::DNS;
my $host = 'spring.sakurasaita.net';
my $res = Net::DNS::Resolver->new;
if(my $query = $res->search($host, 'A')){
print map {$_->address."\n"} grep($_->type eq 'A', $query->answer);
}else{
print $res->errorstring, "\n";
}
answerの結果でtypeがAレコードの場合のみaddressを取得している。これには訳があり、取得しようとするホスト名がCNAMEレコードだった場合、addressが使用できず、「$_->address」でエラーが発生してしまうためだ。
レコードの種類については、「@IT:主なDNSレコードの種類」が参考になる。
上記のスクリプトを実行すると以下のような結果になる。
$ perl dns.pl
210.250.97.3
$ perl dns.pl
66.249.89.104
66.249.89.147
66.249.89.99
逆引き(IPアドレス→ホスト名)
IPアドレスからホスト名を取得する。IPアドレスは任意のものに変更した方が確実に動作するかもしれない。
use strict;
use Net::DNS;
my $ip = '66.249.89.99';
my $res = Net::DNS::Resolver->new;
if(my $query = $res->search($ip, 'PTR')){
print map {$_->ptrdname."\n"} grep($_->type eq 'PTR', $query->answer);
}else{
print $res->errorstring;
}
answerの結果でtypeがPTRレコードの場合のみホスト名を取得している。これを実行すると以下のような結果になる。
$ perl dns.pl
jp-in-f99.google.com
任意のDNSサーバに問い合わせる 正引き(ホスト名→IPアドレス)
DNSサーバのIPアドレスを更新した場合、周囲のDNSサーバに変更が反映されるまでには多少の時間が必要になる。例えば、ダイナミックDNSサービスを使用していて、IPアドレスの更新を行い、更新が正常に行われているか確認するとする(VALUE-DOMAINなどたまに更新されていないことがある)。その際、プロバイダのDNSサーバに問い合わせたのではタイムラグの問題で変更が反映されていない可能性がある。よって、ドメインを管理している大元のDNSサーバに問い合わせるのが最も確実な方法となる。
下記のスクリプトは、ドメインを管理しているDNSサーバを取得し、取得したDNSサーバに問い合わせを行っている。
use strict;
use Net::DNS;
my $domain = 'sakurasaita.net';
my $host = 'spring.sakurasaita.net';
my $res = Net::DNS::Resolver->new;
my @ns;
if(my $query = $res->query($domain, 'NS')){
@ns = map {$_->nsdname} grep($_->type eq 'NS', $query->answer);
print "DNSサーバ:\n";
print map {"$_\n"} @ns;
}else{
print $res->errorstring, "\n";
exit;
}
$res->nameservers(@ns) if(@ns > 0);
if(my $query = $res->search($host, 'A')){
print "IPアドレス:\n";
print map {$_->address."\n"} grep($_->type eq 'A', $query->answer);
}else{
print $res->errorstring, "\n";
}
上記のスクリプトを実行すると以下のような結果になる。
$ perl dns.pl
DNSサーバ:
ns3.value-domain.com
ns1.value-domain.com
ns2.value-domain.com
IPアドレス:
210.250.97.3
「spring.sakurasaita.net」のIPアドレスを問い合わせているのに、DNSサーバの一覧を取得する部分では「sakurasaita.net」を指定している。これは、「spring.sakurasaita.net」にNSレコード(ドメインを管理するDNSサーバを定義するレコード)を指定していないからであって、必ずしも上位レベルのドメインを指定しなければいけないというわけではない。
私の場合、一部のサブドメインにNSレコードを設定しているが、そのサブドメインはDNSサーバの一覧取得にも使用できる。
my $domain = 'flower.sakurasaita.net';
my $host = 'flower.sakurasaita.net';
上記の変更を行った後に実行すると以下のような結果になる。
$ perl dns.pl
DNSサーバ:
ns1.dns.ne.jp
ns2.dns.ne.jp
IPアドレス:
219.94.128.32
ダイナミックDNSのIPアドレスを更新した後、問い合わせるDNSサーバを指定した場合としなかった場合とで結果を比べてみれば違いが分かると思う。
まとめ
CGIを作成するのであればあまり必要の無い知識だが、スクリプトで手軽にDNS問い合わせを行えるのはおもしろい。このモジュールを利用してダイナミックDNSサービスのIPアドレスを更新するスクリプトを作成してみようと思う(というより、既に作成してあるのでまとめて投稿しようと思う)。