Pythonで複数のIPアドレスの逆引きNS(パッシブDNS)レコードを取得
2005年にFlorian Weimerによって導入されたパッシブDNSは、現在ではIPセキュリティ調査やドメインネームシステム(DNS)運用のセキュリティなどにおいて中心的なリソースとなっている。パッシブDNSデータベースは、DNS通信においてIPがドメイン名に解決されるたびに観測されるイベントを含む。したがって、これは現在の状態やDNS自体の物理的なインフラストラクチャから独立したデータベースである。さらに、このデータベースには時間情報が含まれる。つまり、このような解決が最初に観測された日時と最後に観測された日時である。
このようなデータを取得する最も簡単な方法の1つは、WhoisXML APIのサービスを利用することです。今回のブログでは、逆引きに焦点を当てます。IPv4アドレスを使用して、これらのIPが特定の日付に属していたドメイン名を明らかにしたいと思います。
LinuxまたはMac OS XのコマンドラインでPythonを使用するが、Pythonが機能するのであれば、Windowsのコマンドライン環境でも同じことが簡単にできる。Pythonとシェルスクリプトのごく基本的なスキルのみを想定しています。逆IP APIと、APIの使用を非常に簡単にする提供されたPythonパッケージを使用する。このライブラリはPythonのパッケージ・マネージャであるpipを使ってインストールすることができる。以下のコマンドをシェルから実行すると、ライブラリがダウンロードされ、インストールされる:
pip3 reverse-ip をインストールする
(オプションとして、システム全体でライブラリーを利用できるようにするために、rootユーザーで行うか、インストール範囲を限定するためにPython仮想環境で行うこともできます)。
reverse-ipパッケージは、技術的には使用可能な状態になっているが、APIへのサブスクリプションも必要である。サブスクリプションを行うと、APIキー(文字列)が発行されます。
すべての前提条件が手元に揃ったので、これでタスクを達成できる。ips_demo.csvというファイルにIPアドレスのリストがあると仮定しよう。デモのために、以下の例を使用する:
172.67.155.63 104.21.20.75
これらはWhoisXML APIのウェブサービスに属するIPアドレスですが、弊社のウェブプロバイダーによって他のサービスとも共有されています。
標準入力からIPアドレスを読み込み、カンマ区切り(csv)形式で標準出力に書き出すスクリプトを実装します。それでは、スクリプトget_reverse_ip_of_a_list.pyを適当なプログラマ用のテキストエディタで編集してみましょう。まず、IPを読み込んで標準出力に繰り返し出力してみましょう。この初期コードはこうなります:
#usr/bin/env python3 インポート sys for line in sys.stdin.readlines(): ip = line.strip() sys.stdout.write('"%s",'%ip) sys.stdout.write("♪n")
IPを読み取るのにもっと洗練された方法を選ぶこともできるが、ここではシンプルにしておこう。標準入力から来る行を読み、.strip()で改行のような付加的な文字を削除し、IPを標準出力に書き出す。それから改行を書く。スクリプトのメイン部分の2つのsys.stdout.write呼び出しの間はすでに空けてあるからだ。
しかし、拡張する前に試してみましょう。シェルコマンドラインで、次のようにしてみましょう。
chmod +x get_reverse_ip_of_a_list.py get_reverse_ip_of_a_list.py < ips_demo.csv
その結果、次のような出力が得られた:
"172.67.155.63", "104.21.20.75",
これは予想通りの結果です。
では、スクリプトを拡張して、その仕事をさせてみよう。このスクリプトはこう読む:
#usr/bin/env python3 import datetime from time import sleep from reverseip import Client reverseip = Client('YOUR_API_KEY') for line in sys.stdin.readlines(): ip = line.strip() sys.stdout.write('"%s",'%ip) data = reverseip.data(ip) for record in data['result']: sys.stdout.write('"%s","%s","%s",'%(record['name']、 datetime.datetime.fromtimestamp( int(record['first_seen'])).strftime('%c')、 datetime.datetime.fromtimestamp( int(レコード['last_visit'])).strftime('%c'))) sys.stdout.write("♪n") sleep(.1)
YOUR_API_KEYを実際のAPIキーに置き換えて動作させることを忘れないでください。モジュールからClientクラスをインポートし、APIキーを渡すインスタンスreverseipを作成するだけです。そして、reverseip.dataを呼び出すと、Python辞書に読み込まれた結果が得られます; 出力データフォーマットの詳細については、APIのドキュメントを参照してください。
当面は、出力の結果フィールド、すなわちdata['result']が、見つかったレコードのイテレータであることを知っていれば十分である。(より正確には、300レコードまでである)。一般に、あるIPのドメイン名の数が50や100を超えるときはいつでも、インフラストラクチャは共有され、すべてのレコードを持つことはあまり意味がないかもしれない。しかし、すべてのレコードが必要な場合は、APIドキュメントにその方法が記載されている)。
そこで、もしレコードがあれば、それを繰り返し検索する。各レコードには3つのフィールドがあり、nameは実際のドメイン名、first_seenとlast_visitはこのIP-nameペアの最初と最後の観測日時を示す。これはAPIからタイムスタンプの形で提供される。我々は、datetime標準Pythonライブラリの一見面倒だが論理的な関数によって、日付フォーマットとローカルシステムのタイムゾーンで読み取り可能なデータタイムに変換する。各トリプレットを指定された出力行に追加します。
最後に、APIのスロットリング制限にかからないように0.1秒待つ。(1秒あたりの最大リクエスト数は実際には30なので、これは省略してもよいだろう)。何ができたか見てみよう:
./get_reverse_ip_of_a_list.py < ips_demo.csv
次のような結果になります。
"172.67.155.63", "labbry.com", "Fri Jul 26 07:03:05 2019", "Fri May 7 11:09:07 2021", "livitte.com", "Fri Sep 13 07:15:39 2019", "Fri May ... "104.21.20.75", "taalmedia.com", "Fri Jun 21 13:50:38 2019", "Fri Apr 23 18:12:27 2021"、
少なくともこのブログを書いている時点では。(誤字脱字のため、2行目は切り捨てています。) 標準出力をファイルに出力することもできます:
./get_reverse_ip_of_a_list.py < ips_demo.csv > ips_pdns.csv
ips_pdns.csvがお気に入りのオフィススプレッドシートでインポートできるようにします。
結論として、Pythonで非常に簡単にパッシブDNSデータを取得する方法を紹介しました。一方、上級のPythonプログラマーにとっては、Reverse-ip Pythonパッケージをインストールし、WhoisXML APIからAPIキーを入手した後に、このメッセージが表示されます、
from reverseip import Client reverseip = Client('YOUR_API_KEY') data = reverseip.data(ip)
は、IPアドレスのパッシブDNSレコードを含むPython辞書を提供します。そして、これはおそらく1回の関数呼び出しでそのようなデータを取得する最も簡単な方法です。