मैं Python में DNS लुकअप कैसे कर सकता / सकती हूं, जिसमें / / / मेजबानों का जिक्र भी शामिल है?


96

dnspython मेरे DNS लुकिंग को बहुत अच्छी तरह से करेगा, लेकिन यह पूरी तरह से सामग्री को अनदेखा करता है /etc/hosts

क्या एक अजगर पुस्तकालय कॉल है जो सही काम करेगा? यानी पहले चेक इन करेंetc/hosts , और केवल DNS लुकअप पर वापस जाएं अन्यथा नहीं?


मैंने इसके लिए एक मुद्दा बनाया: github.com/rthalley/dnspython/issues/149
ग्रेग डबिकि

1
dnspython इसे लागू नहीं करेगा। सरल फॉरवर्ड लुकअप के लिए, प्रस्तावित का उपयोग करें socket.gethostbyname, अधिक जटिल प्रश्नों के लिए, dnspython का उपयोग करें।
सेबिक्स

जवाबों:


116

यदि आप DNS लुकअप खुद करना चाहते हैं या यदि आप केवल होस्ट का आईपी चाहते हैं तो मुझे वास्तव में यकीन नहीं है । यदि आप बाद में चाहते हैं,

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

1
क्या किसी को पता है कि यह खोज किस स्तर पर कैश की गई है? अजगर के भीतर? या OS? या DNS सर्वर?
साइमन ईस्ट

@ साइमन पायथन द्वारा कैश नहीं किया गया, न ही ओएस। यह किसी भी DNS सर्वर पर निर्भर करता है अगर वह कैश करता है या नहीं। - आम तौर पर बोलना: डीएनएस केवल एप्लिकेशन द्वारा या कैचिंग-डीएनएस-सर्वरों द्वारा हल की गई श्रृंखला में टक किया जाता है।
रॉबर्ट सीमर

@Jochen अगर "लोकलहोस्ट" होस्ट फ़ाइल से आता है या नहीं, कॉन्फ़िगरेशन पर निर्भर करता है!
रॉबर्ट सीमर

@RobertSiemer देर से टिप्पणी के लिए क्षमा करें: परिणाम स्थानीय रिज़ॉल्वर द्वारा कैश किया जा सकता है। nscdऔर nslcdयूनिक्स बॉक्स पर ऐसा कर सकते हैं। यह कैशिंग के लिए कॉन्फ़िगर किए गए स्थानीय नाम सर्वर द्वारा कैश किया जा सकता है (एक बार एक सामान्य सेटअप, एक बार में। शायद अब ऐसा नहीं है)। यह दुर्भाग्य से एक सीधा 'नहीं' जवाब है। ये बातें शायद ही कभी होती हैं। :)
एलेक्सियो

यह कभी भी केवल एक ही पता नहीं लौटाएगा? इसलिए यदि आपके पास एक डीएनएस राउंड रॉबिन है तो यह होस्टनाम से जुड़े सभी पतों को उजागर नहीं करेगा।
ThorSummoner

90

पायथन में सामान्य नाम संकल्प ठीक काम करता है। उसके लिए आपको DNSpython की आवश्यकता क्यों है। बस सॉकेट का उपयोग करें getaddrinfoजो आपके ऑपरेटिंग सिस्टम के लिए कॉन्फ़िगर किए गए नियमों का अनुसरण करता है (डेबियन पर, यह निम्नानुसार है /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 / etc।) में हैं, इसलिए सिस्टम कई IP पते वापस कर सकते हैं। लंबर @Peter सिल्वा से "उधार" लिया गया था।

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

उपरोक्त उत्तर पाइथन 2 के लिए था। यदि आप पाइथन 3 का उपयोग कर रहे हैं, तो यहां कोड है।

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

-2

मुझे DNS आरआर होस्टनाम का विस्तार करने का यह तरीका मिला जो आईपी की सूची में, सदस्य होस्टनाम की सूची में विस्तारित होता है:

#!/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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.