Como posso fazer pesquisas de DNS em Python, incluindo referência a / etc / hosts?


96

dnspython fará minhas pesquisas DNS muito bem, mas ignora totalmente o conteúdo de /etc/hosts.

Existe uma chamada de biblioteca python que fará a coisa certa? ou seja, verifique primeiro etc/hostse só retorne às pesquisas de DNS caso contrário?



1
dnspython não irá implementar isso. Para pesquisas socket.gethostbynamediretas simples, use o proposto ; para consultas mais complexas, use dnspython.
sebix

Respostas:


116

Não tenho certeza se você deseja fazer pesquisas de DNS sozinho ou se apenas deseja o ip de um host. Caso você queira o último,

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

1
Alguém sabe em que nível esta pesquisa é armazenada em cache? Dentro do Python? Ou sistema operacional? Ou servidor DNS?
Simon East

@Simon Não armazenado em cache pelo Python, nem pelo sistema operacional. Depende de qualquer servidor DNS envolvido se ele armazena em cache ou não. - De um modo geral: o DNS é armazenado em cache apenas pelo próprio aplicativo ou resolvendo-DNS-servidores dobrados na cadeia de resolução.
Robert Siemer

@Jochen se “localhost” vem do arquivo hosts ou não depende da configuração!
Robert Siemer

@RobertSiemer Desculpe pelo comentário tardio: o resultado pode ser armazenado em cache pelo resolvedor local. nscde nslcdem caixas Unix pode fazer isso. Ele também pode ser armazenado em cache por um servidor de nomes local configurado para armazenamento em cache (uma configuração comum, uma vez. Provavelmente não tanto agora). Infelizmente, não é uma resposta direta "não". Essas coisas raramente são. :)
Alexios

isso sempre retornará um único endereço, não? Portanto, se você tiver um round robin de dns, isso não exibirá todos os endereços associados ao nome do host.
ThorSummoner

90

A resolução de nome normal em Python funciona bem. Por que você precisa do DNSpython para isso. Basta usar soquete , getaddrinfoque segue as regras configuradas para seu sistema operacional (no Debian, segue /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
seria bom adicionar a etapa de transformação. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]me dá a lista de ips.
Alex

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

fornece uma lista dos endereços de www.example.com. (ipv4 e ipv6)


1

Este código funciona bem para retornar todos os endereços IP que podem pertencer a um determinado URI. Como muitos sistemas agora estão em um ambiente hospedado (AWS / Akamai / etc.), Os sistemas podem retornar vários endereços IP. O lambda foi "emprestado" de @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

A resposta acima foi destinada ao Python 2. Se você estiver usando o Python 3, aqui está o código.

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

-2

Descobri essa maneira de expandir um nome de host DNS RR que se expande em uma lista de IPs, na lista de nomes de host de membros:

#!/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

Que, quando eu executo, lista alguns nomes de host 1e100.net:

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.