Bagaimana saya bisa melakukan pencarian DNS dengan Python, termasuk merujuk ke / etc / hosts?


97

dnspython akan melakukan pencarian DNS saya dengan sangat baik, tetapi sepenuhnya mengabaikan konten /etc/hosts.

Apakah ada panggilan pustaka python yang akan melakukan hal yang benar? yaitu, periksa dulu etc/hosts, dan hanya kembali ke pencarian DNS jika tidak?


Saya membuat masalah untuk itu: github.com/rthalley/dnspython/issues/149
Greg Dubicki

1
dnspython tidak akan menerapkan ini. Untuk pencarian sederhana ke depan, gunakan usulan socket.gethostbyname, untuk kueri yang lebih kompleks, gunakan dnspython.
sebix

Jawaban:


118

Saya tidak begitu yakin apakah Anda ingin melakukan pencarian DNS sendiri atau jika Anda hanya ingin ip host. Jika Anda menginginkan yang terakhir,

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

1
Adakah yang tahu di tingkat mana pencarian ini di-cache? Dalam Python? Atau OS? Atau server DNS?
Simon East

@Simon Tidak di-cache oleh Python, maupun OS. Itu tergantung pada server DNS yang terlibat apakah cache atau tidak. - Secara umum: DNS hanya di-cache oleh aplikasi itu sendiri, atau dengan server-DNS penyelesaian yang terselip di rantai penyelesaian.
Robert Siemer

@Jochen jika "localhost" berasal dari file host atau tidak tergantung pada konfigurasinya!
Robert Siemer

@RobertSiemer Maaf atas komentar yang terlambat: hasil mungkin di -cache oleh resolver lokal. nscddan nslcdpada kotak Unix dapat melakukan ini. Itu juga bisa di-cache oleh server nama lokal yang dikonfigurasi untuk cache (pengaturan umum, sekali waktu. Mungkin tidak begitu banyak sekarang). Sayangnya, ini bukan jawaban 'tidak' yang langsung. Hal-hal ini jarang terjadi. :)
Alexios

ini hanya akan mengembalikan satu alamat, bukan? Jadi jika Anda memiliki dns round robin, ini tidak akan mengekspos semua alamat yang terkait dengan nama host.
ThorSummoner

91

Resolusi nama normal dengan Python berfungsi dengan baik. Mengapa Anda membutuhkan DNSpython untuk itu. Hanya menggunakan socket 's getaddrinfoyang mengikuti aturan dikonfigurasi untuk sistem operasi Anda (pada Debian, maka /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
alangkah baiknya menambahkan langkah transformasi. addrs = [ str(i[4][0]) for i in socket.getaddrinfo(name, 80) ]memberi saya daftar ips.
Alex

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

memberi Anda daftar alamat untuk www.example.com. (ipv4 dan ipv6)


1

Kode ini berfungsi dengan baik untuk mengembalikan semua alamat IP yang mungkin dimiliki oleh URI tertentu. Karena banyak sistem sekarang berada dalam lingkungan yang dihosting (AWS / Akamai / dll.), Sistem dapat mengembalikan beberapa alamat IP. Lambda tersebut "dipinjam" dari @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

Jawaban di atas dimaksudkan untuk Python 2. Jika Anda menggunakan Python 3, berikut kodenya.

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

-2

Saya menemukan cara ini untuk memperluas nama host DNS RR yang berkembang menjadi daftar IP, ke dalam daftar nama host anggota:

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

Yang mana, ketika saya menjalankannya, mencantumkan beberapa nama host 1e100.net:

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.