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

7cjasjjr  于 2023-06-28  发布在  Python
关注(0)|答案(7)|浏览(106)

dnspython可以很好地完成我的DNS查找,但它完全忽略了/etc/hosts的内容。
有没有一个python库调用可以做正确的事情?即检查第一次在etc/hosts,只有回落到DNS查找,否则?

6ovsh4lw

6ovsh4lw1#

我真的不确定你是想自己做DNS查找,还是只想得到主机的IP地址。如果你想要后者,
/!\ socket.gethostbyname已弃用,请选择socket.getaddrinfo
man gethostbyname
gethostbyname*(),gethostbyaddr*(),[...]函数已过时。应用程序应该使用getaddrinfo(3),getnameinfo(3),

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

qmb5sa222#

Python中的正常名称解析工作正常。你为什么需要DNSpython。只需使用socketgetaddrinfo,它遵循为您的操作系统配置的规则(在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))]
9ceoxa92

9ceoxa923#

听起来你不想自己解析DNS。dnspython是一个独立的DNS客户端,可以理解它会忽略你的操作系统,因为它绕过了操作系统的实用程序。
我们可以查看一个名为getent的shell实用程序,以了解(类似Debian 11的)操作系统如何为程序解析DNS。这可能是所有使用套接字实现的类似 *nix的系统的标准。
参见man getent的“hosts”部分,其中提到了getaddrinfo的使用,我们可以将其视为man getaddrinfo
为了在Python中使用它,我们必须从数据结构中提取一些信息:

import socket

def get_ipv4_by_hostname(hostname):
    # see `man getent` `/ hosts `
    # see `man getaddrinfo`

    return list(
        i        # raw socket structure
            [4]  # internet protocol info
            [0]  # address
        for i in 
        socket.getaddrinfo(
            hostname,
            0  # port, required
        )
        if i[0] is socket.AddressFamily.AF_INET  # ipv4

        # ignore duplicate addresses with other socket types
        and i[1] is socket.SocketKind.SOCK_RAW  
    )

print(get_ipv4_by_hostname('localhost'))
print(get_ipv4_by_hostname('google.com'))
hxzsmxv2

hxzsmxv24#

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

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

wmvff8tz

wmvff8tz5#

这段代码可以很好地返回可能属于特定URI的所有IP地址。由于许多系统现在处于托管环境(AWS/Akamai/等)中,因此系统可能会返回多个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')
wxclj1h5

wxclj1h56#

你可以使用python dns模块进行dns查询。

import urllib.parse
import dns.resolver

try:
    parsed_url = urllib.parse.urlparse(url)
    hostname = parsed_url.hostname
    answers = dns.resolver.query(hostname, 'A')
    for rdata in answers:
        print(rdata.address)
except dns.resolver.NXDOMAIN:
    print('ip not found.')
hfyxw5xn

hfyxw5xn7#

我发现了这样的方法来扩展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主机名:

相关问题