Comment puis-je effectuer des recherches DNS en Python, y compris en faisant référence à / etc / hosts?


96

dnspython fera très bien mes recherches DNS, mais il ignore entièrement le contenu de /etc/hosts.

Existe-t-il un appel de bibliothèque python qui fera la bonne chose? c'est-à-dire vérifier d'abord etc/hosts, et ne revenir qu'aux recherches DNS sinon?


J'ai créé un numéro pour cela: github.com/rthalley/dnspython/issues/149
Greg Dubicki

1
dnspython ne l'implémentera pas. Pour des recherches socket.gethostbynamedirectes simples, utilisez la proposition , pour des requêtes plus complexes, utilisez dnspython.
sebix

Réponses:


116

Je ne sais pas vraiment si vous voulez faire des recherches DNS vous - même ou si vous voulez simplement l'IP d'un hôte. Au cas où vous voudriez ce dernier,

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

1
Quelqu'un sait-il à quel niveau cette recherche est mise en cache? Dans Python? Ou OS? Ou serveur DNS?
Simon East

@Simon Non mis en cache par Python, ni par le système d'exploitation. Cela dépend de tout serveur DNS impliqué s'il met en cache ou non. - De manière générale: le DNS est mis en cache uniquement par l'application elle-même, ou par des serveurs DNS de résolution nichés dans la chaîne de résolution.
Robert Siemer

@Jochen si «localhost» provient ou non du fichier hosts dépend de la configuration!
Robert Siemer

@RobertSiemer Désolé pour le commentaire tardif: le résultat peut être mis en cache par le résolveur local. nscdet nslcdsur les boîtes Unix peut le faire. Il pourrait également être mis en cache par un serveur de noms local configuré pour la mise en cache (une configuration courante, il était une fois. Probablement pas tellement maintenant). Ce n'est pas une réponse directe «non», malheureusement. Ces choses le sont rarement. :)
Alexios

cela ne renverra jamais qu'une seule adresse non? Donc, si vous avez un round robin DNS, cela n'exposera pas toutes les adresses associées au nom d'hôte.
ThorSummoner

90

La résolution de nom normale en Python fonctionne correctement. Pourquoi avez-vous besoin de DNSpython pour cela. Il suffit d' utiliser la prise « s getaddrinfoqui suit les règles configurées pour votre système d'exploitation (sur Debian, il suit /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
serait bien d'ajouter l'étape de transformation. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]me donne la liste des ips.
Alex

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

vous donne une liste des adresses pour www.example.com. (ipv4 et ipv6)


1

Ce code fonctionne bien pour renvoyer toutes les adresses IP qui pourraient appartenir à un URI particulier. Étant donné que de nombreux systèmes se trouvent désormais dans un environnement hébergé (AWS / Akamai / etc.), les systèmes peuvent renvoyer plusieurs adresses IP. Le lambda a été "emprunté" à @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 réponse ci-dessus était destinée à Python 2. Si vous utilisez Python 3, voici le code.

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

-2

J'ai trouvé cette façon d'étendre un nom d'hôte DNS RR qui se développe dans une liste d'adresses IP, dans la liste des noms d'hôte des membres:

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

Qui, lorsque je l'exécute, répertorie quelques noms d'hôte 1e100.net:

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.