Làm cách nào để tôi có thể tra cứu DNS bằng Python, bao gồm cả việc tham chiếu đến / etc / hosts?


96

dnspython sẽ thực hiện tra cứu DNS của tôi rất tốt, nhưng nó hoàn toàn bỏ qua nội dung của /etc/hosts.

Có lệnh gọi thư viện python sẽ thực hiện đúng không? tức là kiểm tra đầu tiên etc/hostsvà chỉ quay lại tra cứu DNS nếu không?


Tôi tạo ra một vấn đề cho rằng: github.com/rthalley/dnspython/issues/149
Greg Dubicki

1
dnspython sẽ không thực hiện điều này. Đối với các tra cứu đơn giản, sử dụng đề xuất socket.gethostbyname, đối với các truy vấn phức tạp hơn, hãy sử dụng dnspython.
sebix

Câu trả lời:


116

Tôi không thực sự chắc chắn nếu bạn muốn tự mình tra cứu DNS hay bạn chỉ muốn ip của một máy chủ. Trong trường hợp bạn muốn cái sau,

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

1
Có ai biết tra cứu này được lưu trữ ở cấp độ nào không? Trong Python? Hoặc hệ điều hành? Hoặc máy chủ DNS?
Simon East

@Simon Không được lưu trong bộ nhớ cache của Python, cũng không phải hệ điều hành. Nó phụ thuộc vào bất kỳ máy chủ DNS nào có liên quan nếu nó được lưu vào bộ nhớ cache hay không. - Nói chung: DNS chỉ được lưu trữ trong bộ nhớ cache của chính ứng dụng hoặc bởi các máy chủ DNS phân giải nằm trong chuỗi phân giải.
Robert Siemer

@Jochen nếu “localhost” đến từ tệp máy chủ hay không phụ thuộc vào cấu hình!
Robert Siemer

@RobertSiemer Xin lỗi vì nhận xét muộn: kết quả có thể được lưu vào bộ nhớ cache bởi trình giải quyết cục bộ. nscdnslcdtrên các hộp Unix có thể làm được điều này. Nó cũng có thể được lưu trong bộ nhớ cache bởi một máy chủ định danh cục bộ được định cấu hình để lưu vào bộ nhớ đệm (một thiết lập phổ biến, ngày xưa. Có lẽ bây giờ không còn nhiều). Thật không may, đó không phải là một câu trả lời thẳng thắn 'không'. Những điều này hiếm khi có. :)
Alexios

điều này sẽ chỉ trả về một địa chỉ duy nhất không? Vì vậy, nếu bạn có một vòng lặp dns, điều này sẽ không hiển thị tất cả các địa chỉ được liên kết với tên máy chủ.
ThorSummoner

90

Độ phân giải tên bình thường trong Python hoạt động tốt. Tại sao bạn cần DNSpython cho điều đó. Chỉ cần sử dụng ổ cắm 's getaddrinfomà sau các quy tắc cấu hình cho hệ điều hành của bạn (trên Debian, nó sau /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
sẽ rất tốt nếu thêm bước chuyển đổi. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]cho tôi danh sách các ips.
Alex

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

cung cấp cho bạn danh sách các địa chỉ cho www.example.com. (ipv4 và ipv6)


1

Mã này hoạt động tốt để trả về tất cả các địa chỉ IP có thể thuộc về một URI cụ thể. Vì nhiều hệ thống hiện đang ở trong môi trường được lưu trữ (AWS / Akamai / v.v.), các hệ thống có thể trả về một số địa chỉ IP. Lambda được "mượn" từ @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

Câu trả lời ở trên dành cho Python 2. Nếu bạn đang sử dụng Python 3, đây là mã.

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

-2

Tôi đã tìm thấy cách này để mở rộng tên máy chủ DNS RR mở rộng thành danh sách IP, vào danh sách tên máy chủ thành viên:

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

Khi tôi chạy nó, liệt kê một số tên máy chủ 1e100.net:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.