为什么getaddrinfo不返回所有IP地址?

Phi*_*ipB 5 python sockets

我正在尝试获取所有IP地址:earth.all.vpn.airdns.org在Python中:

def hostnamesToIps(hostnames):
  ip_list = []

  for hostname in hostnames:
      try:
          ais = socket.getaddrinfo(hostname, None)
          for result in ais:
              #print (result[4][0])
              ip_list.append(result[-1][0])
      except:
          eprint("Unable to get IP for hostname: " + hostname)

return list(set(ip_list))
Run Code Online (Sandbox Code Playgroud)

(f eprint是打印错误的函数).输出给了我29个地址.

但当我这样做时:

nslookup earth.all.vpn.airdns.org
Run Code Online (Sandbox Code Playgroud)

我得到大约100个托管.

如何在python中实现这一点?为什么我没有得到所有的"getaddrinfo"?

此行为仅使用Windows(python 3)出现.当我在我的Linux(python 2.7)上执行代码时,它给出了与使用nslookup相同的结果.

info:如答案所解释的那样,它不依赖于系统.


在不改变任何内容的情况下,nslookup和getaddrinfo的结果现在是相同的.

cod*_*kel 3

dig像、host和 等工具nslookup直接使用 UDP/TCP 和它们自己的 DNS 查询实现来查询默认 DNS 服务器,而 Python 的socket模块使用操作系统的 DNS 查找接口,通常使用更复杂的查找机制,例如 dns 缓存、主机文件、域名后缀、链接本地名称解析等。

strace显示 Pythonsocket.getaddrinfo最终使用 netlink (AF_NETLINK) 套接字来查询系统以进行 DNS 查找(Ubuntu 12.04 上的 Python 2.7)。nslookup但是,从端口 53 读取默认 DNS 服务器/etc/resolv.conf并打开 UDP 套接字。

我认为您获得不同条目计数的原因有两个:

  1. DNS 条目非常不稳定,可能随时发生变化
  2. Python 返回系统 DNS 缓存提供的缓存条目,而nslookup始终检索“新鲜”结果。

此外,nslookup可能会产生与系统解析器略有不同的 DNS 查询(产生另一个答案)。可以使用 Wireshark 进行检查,但我现在先不做这个。

另一个问题可能是使用 UPD 时 DNS 响应被截断。如果有大量条目,它们将无法容纳在单个 UDP 包中,因此答案包含截断标志。它取决于客户端通过 TCP 套接字重新发送 DNS 查询以检索所有结果。(被截断的答案实际上是空的)。

编辑:关于缓存/易失性的注释

即使不匹配不是由于本地 DNS 缓存造成的,也可能是由于服务器端缓存造成的。我尝试了多个 DNS 服务器,但对于该特定名称,所有服务器都给出了不同的结果。这意味着由于 DNS 在生存时间 (TTL) 内发生变化,它们不同步。