Python DNS Library のメモ書き
Python で DNS 問い合わせを色々と送信する必要があったので、以下のライブラリを使用した。付属している test スクリプトだと細かな使用方法まで言及していない。このライブラリを利用する上で必要となりそうな、問い合わせに必要な情報・レスポンスがどのように格納されるのか、といった点をまとめた。実行結果は Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)] on win32 の Python Shell で試したもの。
>>> import DNS >>> DNS.defaults # 初期パラメータを格納した辞書 defautls {'protocol': 'udp', 'server': [], 'rd': 1, 'opcode': 0, 'timeout': 30, 'timing': 1, 'qtype': 1, 'port': 53} >>> DNS.DiscoverNameServers() # Windows Registry に設定した DNS サーバの設定を抽出し、defaults に設定 >>> DNS.defaults # x.x.x.x が Windows に設定した DNS サーバ。マスクしてます {'protocol': 'udp', 'server': ['x.x.x.x', '0.0.0.0'], 'rd': 1, 'opcode': 0, 'timeout': 30, 'timing': 1, 'qtype': 1, 'port': 53} >>> req = DNS.Request(qtype="ANY") >>> res = req.req(name="www.example.com",qtype="A") # 問い合わせ先の DNS サーバを変更したい場合、req の引数として server を設定する。 # res = req.req(name="www.example.com",qtype="A",server="x.x.x.x") >>> res.show() # dig と同様の形式で出力する ; <<>> PDG.py 1.0 <<>> www.example.com A ;; options: recurs ;; got answer: ;; ->>HEADER<<- opcode 0, status NOERROR, id 9409 ;; flags: qr rd ra; Ques: 1, Ans: 1, Auth: 2, Addit: 2 ;; QUESTIONS: ;; www.example.com, type = A, class = IN ;; ANSWERS: www.example.com 36360 A 208.77.188.166 ;; AUTHORITY RECORDS: example.com 6196 NS b.iana-servers.net example.com 6196 NS a.iana-servers.net ;; ADDITIONAL RECORDS: a.iana-servers.net 12013 A 192.0.34.43 b.iana-servers.net 72874 A 193.0.0.236 ;; Total query time: 31 msec ;; To SERVER: x.x.x.x ;; WHEN: Sun Sep 13 22:17:10 2009 >>> res.header # DNS レスポンスのヘッダ情報を格納した辞書 header {'aa': 0, 'status': 'NOERROR', 'qr': 1, 'nscount': 2, 'opcodestr': 'QUERY', 'qdcount': 1, 'tc': 0, 'rd': 1, 'arcount': 2, 'opcode': 0, 'ra': 1, 'z': 0, 'rcode': 0, 'id': 9409, 'ancount': 1} >>> res.answers # DNS レスポンスの RR(Resource Record) Answer レコードを格納したリスト answer # Answer レコードが複数ある場合、それぞれのレコードが 1 辞書形式でリストに登録される [{'name': 'www.example.com', 'data': '208.77.188.166', 'typename': 'A', 'classstr': 'IN', 'ttl': 36360, 'type': 1, 'class': 1, 'rdlength': 4}] >>> res.authority # DNS レスポンスの RR(Resource Record) Authority レコードを格納したリスト authority [{'name': 'example.com', 'data': 'b.iana-servers.net', 'typename': 'NS', 'classstr': 'IN', 'ttl': 6196, 'type': 2, 'class': 1, 'rdlength': 20}, {'name': 'example.com', 'data': 'a.iana-servers.net', 'typename': 'NS', 'classstr': 'IN', 'ttl': 6196, 'type': 2, 'class': 1, 'rdlength': 4}] >>> res.additional # DNS レスポンスの RR(Resource Record) Authority レコードを格納したリスト additional [{'name': 'a.iana-servers.net', 'data': '192.0.34.43', 'typename': 'A', 'classstr': 'IN', 'ttl': 12013, 'type': 1, 'class': 1, 'rdlength': 4}, {'name': 'b.iana-servers.net', 'data': '193.0.0.236', 'typename': 'A', 'classstr': 'IN', 'ttl': 72874, 'type': 1, 'class': 1, 'rdlength': 4}] >>> res = req.req(name="wwwww.example.com",qtype="A") # 存在しないホスト名を問い合わせると、どうなるか。 # 特に例外が生じるわけではない >>> res.show() ; <<>> PDG.py 1.0 <<>> wwwww.example.com A ;; options: recurs ;; got answer: ;; ->>HEADER<<- opcode 0, status NXDOMAIN, id 22029 ;; flags: qr rd ra; Ques: 1, Ans: 0, Auth: 1, Addit: 0 ;; QUESTIONS: ;; wwwww.example.com, type = A, class = IN ;; ANSWERS: ;; AUTHORITY RECORDS: example.com 10800 SOA ('dns1.icann.org', 'hostmaster.icann.org', ('serial', 2007051703), ('refresh ', 7200, '2 hours'), ('retry', 3600, '1 hours'), ('expire', 1209600, '2 weeks'), ('minimum', 86400, '1 days')) ;; ADDITIONAL RECORDS: ;; Total query time: 140 msec ;; To SERVER: x.x.x.x ;; WHEN: Sun Sep 13 22:20:30 2009 >>> res.header # 通常の DNS 問い合わせ同様、ヘッダ Status=NXDOMAIN で返答される {'aa': 0, 'status': 'NXDOMAIN', 'qr': 1, 'nscount': 1, 'opcodestr': 'QUERY', 'qdcount': 1, 'tc': 0, 'rd': 1, 'arcount': 0, 'opcode': 0, 'ra': 1, 'z': 0, 'rcode': 3, 'id': 22029, 'ancount': 0} >>> res = req.req(name="www.example.com",qtype="A",server="192.168.0.123") # プライベートアドレスの存在しない DNS サーバに問い合わせした場合、 # DNSError が例外として生じる。このライブラリを利用する場合、 # except DNSError で例外処理を実装すればよい Traceback (most recent call last): File "<pyshell#16>", line 1, in <module> res = req.req(name="www.example.com",qtype="A",server="192.168.0.123") File "G:\Python25\Lib\site-packages\DNS\Base.py", line 206, in req self.sendUDPRequest(server) File "G:\Python25\Lib\site-packages\DNS\Base.py", line 236, in sendUDPRequest r=self.processUDPReply() File "G:\Python25\Lib\site-packages\DNS\Base.py", line 104, in processUDPReply raise DNSError, 'Timeout' DNSError: Timeout