/ etc / hostsの参照を含め、PythonでDNSルックアップを行うにはどうすればよいですか?


96

dnspythonはDNSルックアップを非常にうまく実行しますが、の内容は完全に無視します/etc/hosts

正しいことを行うPythonライブラリの呼び出しはありますか?つまりetc/hosts、最初にでチェックし、それ以外の場合はDNSルックアップのみにフォールバックしますか?


私はそのために問題を作成しました:github.com/rthalley/dnspython/issues/149
Greg Dubicki 2016年

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内?またはOS?またはDNSサーバー?
サイモンイースト、

@Simon PythonでもOSでもキャッシュされません。キャッシュするかどうかは、関与するDNSサーバーに依存します。–一般的に言えば、DNSはアプリケーション自体によって、または解決チェーンに組み込まれた解決DNSサーバーによってのみキャッシュされます。
Robert Siemer 2013年

@Jochen「localhost」がhostsファイルからのものかどうかは、構成に依存します。
Robert Siemer 2013年

@RobertSiemer最近のコメントで申し訳ありません。結果ローカルリゾルバによってキャッシュされる可能性があります。nscdそして、nslcdUnixのボックスでこれを行うことができます。また、キャッシュ用に構成されたローカルネームサーバーによってキャッシュすることもできます(かつての一般的な設定です。たぶん今はそれほど多くありません)。残念ながら、これは簡単な「いいえ」の回答ではありません。これらはめったにありません。:)
Alexios 2014

これは単一のアドレスのみを返すでしょうか?したがって、DNSラウンドロビンを使用している場合、ホスト名に関連付けられているすべてのアドレスが公開されるわけではありません。
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のリストが表示されます。
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

このコードは、特定のURIに属している可能性のあるすべてのIPアドレスを返すのに適しています。現在、多くのシステムがホスト環境(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を対象としたものです。Python3を使用している場合、コードは次のとおりです。

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

-2

IPのリスト、メンバーのホスト名のリストに展開するDNS RRホスト名を展開するこの方法を見つけました。

#!/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ホスト名がリストされます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.