Come posso eseguire ricerche DNS in Python, incluso il riferimento a / etc / hosts?


97

dnspython eseguirà le mie ricerche DNS molto bene, ma ignora completamente il contenuto di /etc/hosts.

C'è una chiamata alla libreria Python che farà la cosa giusta? cioè fare prima il check-in etc/hostse ripiegare solo sulle ricerche DNS altrimenti?


Ho creato un problema per questo: github.com/rthalley/dnspython/issues/149
Greg Dubicki

1
dnspython non lo implementerà. Per semplici ricerche in avanti, utilizzare il proposto socket.gethostbyname, per query più complesse, utilizzare dnspython.
sebix

Risposte:


118

Non sono davvero sicuro se vuoi fare tu stesso le ricerche DNS o se vuoi solo l'ip di un host. Nel caso in cui desideri quest'ultimo,

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

1
Qualcuno sa a quale livello questa ricerca viene memorizzata nella cache? All'interno di Python? O OS? O server DNS?
Simon East

@ Simon Non memorizzato nella cache da Python, né dal sistema operativo. Dipende da qualsiasi server DNS coinvolto se memorizza nella cache o meno. - In generale: il DNS viene memorizzato nella cache solo dall'applicazione stessa o dai server DNS di risoluzione nascosti nella catena di risoluzione.
Robert Siemer

@Jochen se "localhost" proviene o meno dal file hosts dipende dalla configurazione!
Robert Siemer

@RobertSiemer Ci scusiamo per il commento in ritardo: il risultato potrebbe essere memorizzato nella cache dal risolutore locale. nscde nslcdsu macchine Unix possono farlo. Potrebbe anche essere memorizzato nella cache da un server dei nomi locale configurato per la memorizzazione nella cache (una configurazione comune, una volta. Probabilmente non così tanto ora). Sfortunatamente, non è un semplice "no". Queste cose raramente lo sono. :)
Alexios

questo restituirà sempre e solo un singolo indirizzo no? Quindi, se hai un dns round robin, questo non esporrà tutti gli indirizzi associati al nome host.
ThorSummoner

91

La normale risoluzione dei nomi in Python funziona bene. Perché hai bisogno di DNSpython per questo. Proprio l'uso presa 's getaddrinfoche segue le regole configurate per il sistema operativo (su 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
sarebbe bello aggiungere il passaggio di trasformazione. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]mi dà l'elenco degli IP.
Alex

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

ti fornisce un elenco degli indirizzi per www.example.com. (ipv4 e ipv6)


1

Questo codice funziona bene per restituire tutti gli indirizzi IP che potrebbero appartenere a un particolare URI. Poiché molti sistemi si trovano ora in un ambiente ospitato (AWS / Akamai / ecc.), I sistemi possono restituire diversi indirizzi IP. La lambda è stata "presa in prestito" da @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

La risposta sopra era pensata per Python 2. Se stai usando Python 3, ecco il codice.

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

-2

Ho trovato questo modo per espandere un nome host DNS RR che si espande in un elenco di IP, nell'elenco dei nomi host dei membri:

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

Che, quando lo eseguo, elenca alcuni hostname 1e100.net:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.