PythonでDNSの正引きと逆引き
諸般の事情からスクリプトでホスト名とIPアドレスの対応を取りたいことがありますのでメモしておきます。
socket
socket --- 低水準ネットワークインターフェイス — Python 3.8.3 ドキュメント
標準ライブラリで実現できるシンプルな方法です。
import socket # 正引き socket.gethostbyname("www.google.com") #=> '172.217.31.164' # 逆引き socket.gethostbyaddr("172.217.31.164") #=> ('nrt12s22-in-f4.1e100.net', ['164.31.217.172.in-addr.arpa'], ['172.217.31.164'])
逆引きの結果はタプルになっていて、最初の値がホスト名です。
dnspython
高度な機能を使うにはこちらのようなライブラリを使うとよさそうです。本稿執筆時点のバージョンは1.16.0です。
$ pip install dnspython
socketと同じことをやってみます。
from dns import resolver, reversename # 正引き answers = resolver.query("www.google.com") #=> <dns.resolver.Answer object at 0x104829050> [answer.to_text() for answer in answers] #=> ['172.217.174.100'] # 逆引き answers = resolver.query(reversename.from_address("172.217.174.100"), "PTR") #=> <dns.resolver.Answer object at 0x104eebfd0> [answer.to_text() for answer in answers] #=> ['nrt12s28-in-f4.1e100.net.']
クエリの結果は複数の場合があるのでリストとして扱っています。to_text
関数を使って値を文字列として取り出すことができます。
逆引きするには、IPアドレスを逆向きにしたようなホスト名をPTRレコードとして問い合わせます。reversename.from_address
が逆向きのホスト名を作る関数です。次のような値になっています。
reversename.from_address("172.217.174.100") #=> <DNS name 100.174.217.172.in-addr.arpa.>
さらに様々な理由によって、問い合わせ先のネームサーバーの指定が必要だとします。これは(おそらく)socketでは素直にできないです。
新しいresolverを作ってそれにネームサーバーを設定します。あとはそれを使って先ほどと同じようにquery
関数を呼ぶだけです。
res = resolver.Resolver() res.nameservers = ["8.8.8.8"] answers = res.query("www.google.com")