首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:如何区分不可用DNS服务器和不存在的地址

Python:如何区分不可用DNS服务器和不存在的地址
EN

Stack Overflow用户
提问于 2014-07-20 21:41:08
回答 1查看 2.6K关注 0票数 2

名称解析可能会失败,因为没有与主机名关联的ip,或者因为无法到达DNS服务器。不幸的是,Python的socket.create_connectionsocket.gethostbyname函数在这两种情况下似乎都会产生相同的错误:

代码语言:javascript
复制
$ python3 -c 'import socket; socket.create_connection(("www.google.com_bar", 80))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.4/socket.py", line 491, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/usr/lib/python3.4/socket.py", line 530, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

$ python3 -c 'import socket; socket.gethostbyname("www.google_bar.com")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
socket.gaierror: [Errno -5] No address associated with hostname

$ sudo vim /etc/resolv.conf # point to non-existing nameserver

$ python3 -c 'import socket; socket.create_connection(("www.google.com", 80))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3.4/socket.py", line 491, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "/usr/lib/python3.4/socket.py", line 530, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

$ python3 -c 'import socket; socket.gethostbyname("www.google.com")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
socket.gaierror: [Errno -5] No address associated with hostname

有没有办法区分这两种情况,而不需要对“已知-好”主机名执行第二次查找?

这个解决方案应该在Linux下工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-22 15:02:17

您可以使用德斯利布库客户端自己提出DNS请求。客户端提供了类似于dig的功能,它可以指示地址是否失败解析(NXDOMAIN),而不只是解析失败(不幸的是,这只是块-参见下面的修补程序)。

你就这样用它:

代码语言:javascript
复制
from dnslib import DNSRecord, RCODE

# I have dnsmasq running locally, so I can make requests to localhost.
# You need to find the address of the DNS server.
# The /etc/resolv.conf file is quite easily parsed, so you can just do that.
DNS_SERVER = "127.0.0.1"

query = DNSRecord.question("google.com")
response = DNSRecord.parse(query.send(DNS_SERVER, 53, False))
print RCODE[response.header.rcode]  # prints 'NOERROR'

query = DNSRecord.question("google.com_bar")
response = DNSRecord.parse(query.send(DNS_SERVER, 53, False))
print RCODE[response.header.rcode]  # prints 'NXDOMAIN'

# To avoid making the DNS request again when using the socket
# you can get the resolved IP address from the response.

当连接到不存在的DNS服务器时,问题就出现了。每次我试着这样做,请求就会挂起。(当我在命令行上发出相同的请求时,使用类似于netcat的东西,请求也会挂起。我可能选择的随机IP很差,并且遭受防火墙的痛苦,只是丢包)

无论如何,您可以修改源代码以添加超时。您可以在源这里中查看相关的方法(也可以在github上镜像)。我改变的是:

代码语言:javascript
复制
--- a/dns.py
+++ b/dns.py
@@ -357,6 +357,7 @@
             response = response[2:]
         else:
             sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
+            sock.settimeout(10)
             sock.sendto(self.pack(),(dest,port))
             response,server = sock.recvfrom(8192)
             sock.close()

完成此操作后,DNS请求超时。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24855168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档