如何在Python中进行DNS查找,包括引用/ etc / hosts?


96

dnspython可以很好地完成我的DNS查找,但是它完全忽略的内容/etc/hosts

是否有一个python库调用将做正确的事情?即首先检查etc/hosts,否则仅回退到DNS查找?



1
dnspython不会实现这一点。对于简单的正向查找,请使用建议的socket.gethostbyname;对于更复杂的查询,请使用dnspython的。
sebix '16

Answers:


116

我真的不知道,如果你想要做的DNS查找自己或者如果你只是想要一台主机的IP地址。如果您想要后者,

import socket
print(socket.gethostbyname('localhost')) # result from hosts file
print(socket.gethostbyname('google.com')) # your os sends out a dns query

1
有人知道此查询被缓存在哪个级别吗?在Python中?还是操作系统?还是DNS服务器?
西蒙·伊斯特

@Simon既不由Python也不由操作系统缓存。是否缓存是否依赖于所涉及的任何DNS服务器。–一般而言:DNS仅由应用程序本身或包含在解析链中的解析DNS服务器缓存。
罗伯·西默

@Jochen是否“ localhost”来自hosts文件取决于配置!
罗伯·西默

@RobertSiemer对不起,您的最新评论:本地解析器可能会缓存结果。nscdnslcd在Unix服务器可以做到这一点。也可以通过配置用于缓存的本地名称服务器来缓存它(一种常见的设置,曾几何时。现在可能不多了)。不幸的是,这不是一个简单的“不”答案。这些东西很少。:)
Alexios

这样只会返回一个地址吗?因此,如果您有DNS轮询,则不会暴露与主机名关联的所有地址。
ThorSummoner

90

Python中的正常名称解析可以正常工作。为什么您需要DNSpython。仅在使用插座getaddrinfo下面配置为您的操作系统的规则(Debian的,它遵循/etc/nsswitch.conf

>>> print socket.getaddrinfo('google.com', 80)
[(10, 1, 6, '', ('2a00:1450:8006::63', 80, 0, 0)), (10, 2, 17, '', ('2a00:1450:8006::63', 80, 0, 0)), (10, 3, 0, '', ('2a00:1450:8006::63', 80, 0, 0)), (10, 1, 6, '', ('2a00:1450:8006::68', 80, 0, 0)), (10, 2, 17, '', ('2a00:1450:8006::68', 80, 0, 0)), (10, 3, 0, '', ('2a00:1450:8006::68', 80, 0, 0)), (10, 1, 6, '', ('2a00:1450:8006::93', 80, 0, 0)), (10, 2, 17, '', ('2a00:1450:8006::93', 80, 0, 0)), (10, 3, 0, '', ('2a00:1450:8006::93', 80, 0, 0)), (2, 1, 6, '', ('209.85.229.104', 80)), (2, 2, 17, '', ('209.85.229.104', 80)), (2, 3, 0, '', ('209.85.229.104', 80)), (2, 1, 6, '', ('209.85.229.99', 80)), (2, 2, 17, '', ('209.85.229.99', 80)), (2, 3, 0, '', ('209.85.229.99', 80)), (2, 1, 6, '', ('209.85.229.147', 80)), (2, 2, 17, '', ('209.85.229.147', 80)), (2, 3, 0, '', ('209.85.229.147', 80))]

4
添加转换步骤会很好。 addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]给我ip列表。
亚历克斯(Alex)

2
list( map( lambda x: x[4][0], socket.getaddrinfo( \
     'www.example.com.',22,type=socket.SOCK_STREAM)))

为您提供www.example.com的地址列表。(ipv4和ipv6)


1

该代码很好地用于返回可能属于特定URI的所有IP地址。由于许多系统现在处于托管环境(AWS / Akamai / etc)中,因此系统可能会返回几个IP地址。该lambda是从@Peter Silva“借来的”。

def get_ips_by_dns_lookup(target, port=None):
    '''
        this function takes the passed target and optional port and does a dns
        lookup. it returns the ips that it finds to the caller.

        :param target:  the URI that you'd like to get the ip address(es) for
        :type target:   string
        :param port:    which port do you want to do the lookup against?
        :type port:     integer
        :returns ips:   all of the discovered ips for the target
        :rtype ips:     list of strings

    '''
    import socket

    if not port:
        port = 443

    return list(map(lambda x: x[4][0], socket.getaddrinfo('{}.'.format(target),port,type=socket.SOCK_STREAM)))

ips = get_ips_by_dns_lookup(target='google.com')

1

上面的答案是针对Python 2的。如果您使用的是Python 3,则代码如下。

>>> import socket
>>> print(socket.gethostbyname('google.com'))
8.8.8.8
>>>

-2

我发现这种方法可以将DNS RR主机名扩展为IP列表,成员主机名列表:

#!/usr/bin/python

def expand_dnsname(dnsname):
    from socket import getaddrinfo
    from dns import reversename, resolver
    namelist = [ ]
    # expand hostname into dict of ip addresses
    iplist = dict()
    for answer in getaddrinfo(dnsname, 80):
        ipa = str(answer[4][0])
        iplist[ipa] = 0
    # run through the list of IP addresses to get hostnames
    for ipaddr in sorted(iplist):
        rev_name = reversename.from_address(ipaddr)
        # run through all the hostnames returned, ignoring the dnsname
        for answer in resolver.query(rev_name, "PTR"):
            name = str(answer)
            if name != dnsname:
                # add it to the list of answers
                namelist.append(name)
                break
    # if no other choice, return the dnsname
    if len(namelist) == 0:
        namelist.append(dnsname)
    # return the sorted namelist
    namelist = sorted(namelist)
    return namelist

namelist = expand_dnsname('google.com.')
for name in namelist:
    print name

当我运行它时,它列出了一些1e100.net主机名:

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.