Як я можу шукати DNS у Python, включаючи посилання на / etc / hosts?


96

dnspython буде робити мої пошуки в DNS дуже красиво, але повністю ігнорує вміст /etc/hosts.

Чи існує виклик бібліотеки python, який буде робити правильно? тобто спочатку зареєструватися etc/hosts, а в іншому випадку повернутися до пошуку DNS?


Я створив для цього випуск: github.com/rthalley/dnspython/issues/149
Грег Дубіцький

1
dnspython не буде реалізовувати це. Для простих переглядів вперед використовуйте запропоновані socket.gethostbyname, для більш складних запитів - dnspython.
sebix

Відповіді:


116

Я не дуже впевнений, чи хочете ви самостійно шукати DNS, чи просто хочете ip хоста. Якщо ви хочете останнє,

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

1
Хтось знає, на якому рівні цей пошук кешований? У Python? Або ОС? Або DNS-сервер?
Саймон Іст

@Simon Не кешовано ні Python, ні ОС. Це кешування чи ні, залежить від будь-якого задіяного DNS-сервера. - Взагалі кажучи: DNS кешується лише самою програмою або DNS-серверами, що розпізнають, вбудованими в ланцюг розпізнавання.
Роберт Сімер,

@Jochen, якщо “localhost” походить із файлу hosts, чи ні, залежить від конфігурації!
Роберт Сімер,

@RobertSiemer Вибачте за пізній коментар: результат може бути кешований локальним вирішувачем. nscdі nslcdна коробках Unix це можна зробити. Він також може бути кешований локальним сервером імен, налаштованим на кешування (загальна установка, колись давно. Можливо, зараз не так багато). На жаль, це не пряма відповідь «ні». Такі речі бувають рідко. :)
Alexios

це поверне лише одну адресу ні? Отже, якщо у вас є dns round robin, це не відображатиме всіх адрес, пов'язаних з іменем хосту.
ThorSummoner

90

Звичайна роздільна здатність імен у Python працює нормально. Навіщо вам для цього потрібен DNSpython. Просто використовуйте сокет , getaddrinfoякий відповідає правилам, налаштованим для вашої операційної системи (на 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))]

4
було б непогано додати крок трансформації. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]дає мені список ips.
Олексій

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

надає вам список адрес для www.example.com. (ipv4 та ipv6)


1

Цей код добре працює для повернення всіх IP-адрес, які можуть належати певному URI. Оскільки зараз багато систем перебувають у розміщеному середовищі (AWS / Akamai / тощо), системи можуть повертати кілька IP-адрес. Лямбда була "запозичена" у @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

Відповідь вище призначена для Python 2. Якщо ви використовуєте Python 3, ось код.

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

-2

Я знайшов такий спосіб розширити ім'я хосту 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:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.