使用 Python | 反向 IP/DNS API | WhoisXML API 获取 IP 列表的反向 NS(又称被动 DNS)记录

在 Python 中获取 IP 列表的反向 NS(又名被动 DNS)记录

Florian Weimer于 2005 年提出的被动 DNS 现在已成为 IP 安全调查、域名系统 (DNS) 运行安全等方面的核心资源。被动 DNS 数据库包含在 DNS 通信中 IP 解析到域名时观察到的事件。因此,它是一个独立于 DNS 本身的当前状态和物理基础设施的数据库。此外,它还包含时间信息:首次和最后一次观察到此类解析的日期和时间;这一点无法从 DNS 中找到。 

获取此类数据的最简单方法之一就是使用 WhoisXML API 服务。在本博客中,我们重点讨论反向查询:使用 IPv4 地址,我们希望揭示这些 IP 在特定日期所属的域名。 

我们将在 Linux 或 Mac OS X 命令行环境下使用 Python,但只要 Python 能够正常运行,在 Windows 命令行环境下也能轻松完成同样的工作。我们的描述面向初学者;只假定他们具备非常基本的 Python 和 shell 脚本技能。我们将使用反向 IP API和所提供的Python 软件包,它能让 API 的使用变得非常简单。可以使用 Python 的软件包管理器 pip 安装该库。在 shell 中运行以下命令即可下载并安装它:

pip3 install reverse-ip

(也可以选择以根用户身份安装,使整个系统都能使用该库,或者在Python 虚拟环境中安装,以限制安装范围)。  

从技术上讲,reverse-ip 软件包现在已经可以使用,但还需要订阅 API,也可以免费订阅。订阅后,您将收到一个 API 密钥(字符串),在下文中将称为 YOUR_API_KEY。 

有了所有前提条件,我们现在就可以完成任务了。因此,让我们假设在名为 ips_demo.csv 的文件中有一个 IP 地址列表。为便于演示,我们将使用以下示例: 

172.67.155.63
104.21.20.75

这些 IP 地址属于 WhoisXML API 的网络服务,但也由我们的网络提供商与其他服务共享。 

我们将执行一个脚本,从标准输入端读取 IP 地址,并以逗号分隔值(csv)格式将输出写入标准输出端。因此,让我们使用合适的程序员文本编辑器编辑 get_reverse_ip_of_a_list.py 脚本。首先,让我们读取 IP,然后在标准输出中重复这些 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 写入标准输出,在双引号和逗号之间;结果将在这里显示。然后再写入换行符,因为我们已经为脚本的主要部分保留了两个 sys.stdout.write 调用之间的空间。 

但在扩展之前,让我们先试一试:在 shell 命令行中执行以下操作

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
 
导入日期时间
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(record['last_visit'])).strftime('%c'))
    sys.stdout.write("\n")
    sleep(.1)

不要忘记将 YOUR_API_KEY 替换为实际的 API 密钥,这样才能正常工作。我们要做的非常简单:只需从模块中导入客户端类,然后创建实例 reverseip,并在其中传递 API 密钥。然后调用 reverseip.data 即可获得结果,并以 Python 字典形式显示;有关输出数据格式的详细信息,请查阅API 文档。 

目前只需知道输出结果字段,即 data['result'] 是找到的记录的迭代器即可。(更准确地说,是最多 300 条记录的迭代器。一般来说,只要一个 IP 的域名数超过 50 或 100,就需要共享基础架构,拥有所有记录的意义可能不大。不过,如果您需要所有记录,API 文档会说明如何操作)。 

因此,如果有记录,我们就会遍历这些记录。每条记录都有 3 个字段,name 是实际域名,first_seen 和 last_visit 则是首次和最后一次观察该 IP 名称对的日期时间。这是由 API 以时间戳的形式提供的;我们使用看似繁琐但合乎逻辑的 datetime 标准 Python 库函数,将其转换为本地系统日期格式和时区的可读日期时间。我们将每个三元组附加到给定的输出行中。 

最后,我们等待 0.1 秒,以避免遇到 API 的节流限制。(每秒的最大请求数实际上是 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"、

至少在撰写本博客时是这样。(由于排版原因,我们截去了第二行):

./get_reverse_ip_of_a_list.py < ips_demo.csv > ips_pdns.csv

这样,就可以将 ips_pdns.csv 导入您最喜欢的办公电子表格。 

总之,我们已经演示了如何用 Python 非常轻松地获取被动 DNS 数据,即使你刚刚开始使用 Python,也能很快上手。同时,对于高级 Python 程序员来说,只需安装 reverse-ip Python 软件包并从 WhoisXML API 获取 API 密钥即可、

从 reverseip 导入客户端
 
reverseip = Client('YOUR_API_KEY')
 
data = reverseip.data(ip)

为您提供了一个包含 IP 地址被动 DNS 记录的 Python 字典。这也许是通过单个函数调用获取此类数据的最简单方法。