2008年02月05日(火) 23:00 [Perl

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;

#ホスト名のIPアドレスを取得(正引き)
if(my $query = $res->search($host, 'A')){
    # Aレコードのみを取得し、IPアドレスの一覧を印字
    print map {$_->address."\n"} grep($_->type eq 'A', $query->answer);
}else{
    print $res->errorstring, "\n";
}

answerの結果でtypeがAレコードの場合のみaddressを取得している。これには訳があり、取得しようとするホスト名がCNAMEレコードだった場合、addressが使用できず、「$_->address」でエラーが発生してしまうためだ。

レコードの種類については、「@IT:主なDNSレコードの種類」が参考になる。

上記のスクリプトを実行すると以下のような結果になる。

# $hostが「spring.sakurasaita.net」の場合
$ perl dns.pl
210.250.97.3
# $hostが「www.google.com」の場合
$ 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;

# IPアドレスのホスト名を取得(逆引き)
if(my $query = $res->search($ip, 'PTR')){
    # 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;

# ドメインを管理しているDNSサーバの一覧を取得
if(my $query = $res->query($domain, 'NS')){
    # NSレコードのみを取得し、DNSサーバの一覧を取得
    @ns = map {$_->nsdname} grep($_->type eq 'NS', $query->answer);
    # 取得したDNSサーバの一覧を印字
    print "DNSサーバ:\n";
    print map {"$_\n"} @ns;
}else{
    print $res->errorstring, "\n";
    exit;
}

# 問い合わせるDNSサーバを設定する
$res->nameservers(@ns) if(@ns > 0);

# ホスト名のIPアドレスを取得(正引き)
if(my $query = $res->search($host, 'A')){
    # Aレコードのみを取得し、IPアドレスの一覧を印字
    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アドレスを更新するスクリプトを作成してみようと思う(というより、既に作成してあるのでまとめて投稿しようと思う)。

コメント
  1. by Coopz 2008 年 4 月 11 日 15:01 [No.1

    My problem is that there’s nothing special online anymore. I’m searching for something very interesting and cant find anything!

トラックバック / RSS
投稿

Copyright 2008 As You Like It All rights reserved.
Powered by Wordpress, Base template by WEB MAGIC, Photo by Encyclorecorder