Hoe kan ik DNS-lookups doen in Python, inclusief het verwijzen naar /etc/hosts?

dnspythonzal mijn DNS-lookups heel goed doen, maar het negeert volledig de inhoud van /etc/hosts.

Is er een python-bibliotheekoproep die het juiste doet? dwz controleer eerst in etc/hosts, en val anders alleen terug op DNS-lookups?


Antwoord 1, autoriteit 100%

Ik weet niet zeker of je zelfDNS-lookups wilt doen of dat je alleen het IP-adres van een host wilt. Als je het laatste wilt,

/!\ socket.gethostbyname is verouderd, geef de voorkeur aan socket.getaddrinfo

van man gethostbyname:

De functies gethostbyname*(), gethostbyaddr*(), […] zijn verouderd. Toepassingen moeten getaddrinfo(3), getnameinfo(3),

. gebruiken

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


Antwoord 2, autoriteit 77%

De normale naamresolutie in Python werkt prima. Waarom heb je daar DNSpython voor nodig. Gebruik gewoon socket‘s getaddrinfodie de geconfigureerde regels volgt voor uw besturingssysteem (op Debian volgt dit /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))]

Antwoord 3, autoriteit 3%

Het klinkt alsof je dns niet zelf wilt oplossen (dit kan de verkeerde nomenclatuur zijn) dnspython lijkt een zelfstandige dns-client te zijn die begrijpelijkerwijs je besturingssysteem negeert omdat het de hulpprogramma’s van het besturingssysteem omzeilt.

We kunnen kijken naar een shell-hulpprogramma met de naam getentom te begrijpen hoe het (debian 11 gelijkaardige) besturingssysteem dns voor programma’s oplost, dit is waarschijnlijk de standaard voor alle *nix-achtige systemen die een socket gebruiken implementatie.

zie de sectie “hosts” van man getent, waarin het gebruik van getaddrinfowordt genoemd, wat we kunnen zien als man getaddrinfo

en om het in python te gebruiken, moeten we wat informatie uit de datastructuren halen

.

import socket
def get_ipv4_by_hostname(hostname):
    # see `man getent` `/ hosts `
    # see `man getaddrinfo`
    return list(
        i        # raw socket structure
            [4]  # internet protocol info
            [0]  # address
        for i in 
        socket.getaddrinfo(
            hostname,
            0  # port, required
        )
        if i[0] is socket.AddressFamily.AF_INET  # ipv4
        # ignore duplicate addresses with other socket types
        and i[1] is socket.SocketKind.SOCK_RAW  
    )
print(get_ipv4_by_hostname('localhost'))
print(get_ipv4_by_hostname('google.com'))


Antwoord 4, autoriteit 2%

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

geeft u een lijst van de adressen voor www.example.com. (ipv4 en ipv6)


Antwoord 5

Deze code werkt goed voor het retourneren van alle IP-adressen die mogelijk tot een bepaalde URI behoren. Aangezien veel systemen zich nu in een gehoste omgeving bevinden (AWS/Akamai/etc.), kunnen systemen meerdere IP-adressen retourneren. De lambda is “geleend” van @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')

Antwoord 6

Ik heb deze manier gevonden om een ​​DNS RR-hostnaam uit te breiden die uitbreidt naar een lijst met IP’s, naar de lijst met hostnamen van leden:

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

Wat, als ik het run, een paar 1e100.net-hostnamen opsomt:

Other episodes