¿Cómo puedo realizar búsquedas de DNS en Python, incluida la referencia a / etc / hosts?

96

dnspython hará muy bien mis búsquedas de DNS, pero ignora por completo el contenido de /etc/hosts.

¿Existe una llamada a la biblioteca de Python que hará lo correcto? es decir, registrarse primero etc/hostsy, de lo contrario, solo recurrir a las búsquedas de DNS?

Toby White
fuente
Creé
Greg Dubicki
1
dnspython no implementará esto. Para búsquedas sencillas, use el propuesto socket.gethostbyname, para consultas más complejas, use dnspython.
sebix

Respuestas:

116

No estoy realmente seguro de si desea realizar búsquedas de DNS usted mismo o si solo desea la IP de un host. En caso de que desee lo último,

import socket
print(socket.gethostbyname('localhost')) # result from hosts file
print(socket.gethostbyname('google.com')) # your os sends out a dns query
Jochen Ritzel
fuente
1
¿Alguien sabe en qué nivel se almacena en caché esta búsqueda? ¿Dentro de Python? ¿O SO? ¿O servidor DNS?
Simon East
@Simon No almacenado en caché por Python, ni el sistema operativo. Depende de cualquier servidor DNS involucrado si almacena en caché o no. - En términos generales: el DNS se almacena en caché solo por la propia aplicación o por los servidores DNS de resolución metidos en la cadena de resolución.
Robert Siemer
@Jochen, si “localhost” proviene del archivo hosts o no, ¡depende de la configuración!
Robert Siemer
@RobertSiemer Lo siento por la tarde comentario: el resultado puede ser almacenado en caché por el sistema de resolución local. nscdy nslcden cajas Unix puede hacer esto. También podría ser almacenado en caché por un servidor de nombres local configurado para el almacenamiento en caché (una configuración común, alguna vez. Probablemente no tanto ahora). Lamentablemente, no es una respuesta sencilla "no". Estas cosas rara vez lo son. :)
Alexios
esto solo devolverá una única dirección, ¿no? Entonces, si tiene un dns round robin, esto no expondrá todas las direcciones asociadas con el nombre de host.
ThorSummoner
90

La resolución de nombres normal en Python funciona bien. ¿Por qué necesitas DNSpython para eso? Uso solo socket 's getaddrinfoque siguen las reglas configuradas para su sistema operativo (en Debian, se deduce /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))]
Bortzmeyer
fuente
4
Sería bueno agregar el paso de transformación. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]me da la lista de ips.
Alex
2
list( map( lambda x: x[4][0], socket.getaddrinfo( \
     'www.example.com.',22,type=socket.SOCK_STREAM)))

le ofrece una lista de las direcciones de www.example.com. (ipv4 e ipv6)

Peter Silva
fuente
1

Este código funciona bien para devolver todas las direcciones IP que podrían pertenecer a un URI en particular. Dado que muchos sistemas se encuentran ahora en un entorno alojado (AWS / Akamai / etc.), los sistemas pueden devolver varias direcciones IP. La lambda fue "prestada" 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')
come comida
fuente
1

La respuesta anterior fue para Python 2. Si está usando Python 3, aquí está el código.

>>> import socket
>>> print(socket.gethostbyname('google.com'))
8.8.8.8
>>>
Sabrina
fuente
-2

Encontré esta forma de expandir un nombre de host DNS RR que se expande en una lista de IP, en la lista de nombres de host de miembros:

#!/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, cuando lo ejecuto, enumera algunos nombres de host de 1e100.net:

silbido
fuente