Как я могу выполнять поиск DNS в Python, включая ссылку на / etc / hosts?


97

dnspython будет очень хорошо выполнять мой поиск в DNS, но полностью игнорирует содержимое /etc/hosts.

Есть ли вызов библиотеки Python, который будет делать правильные вещи? т.е. сначала зарегистрируйтесь etc/hosts, а в противном случае вернитесь только к поиску DNS?


Я создал для этого проблему: github.com/rthalley/dnspython/issues/149
Грег Дубицки

1
dnspython этого не реализует. Для простого прямого просмотра используйте предложенный socket.gethostbyname, для более сложных запросов используйте dnspython.
sebix

Ответы:


118

Я не совсем уверен , что если вы хотите сделать поиск в DNS самостоятельно , или если вы просто хотите , И. П. хозяина. Если вы хотите последнее,

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, это не будет отображать все адреса, связанные с именем хоста.
ThorSummoner

91

Нормальное разрешение имен в 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.
Alex

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.