Python Network Programming Learning Note (iv): Domain Name System

Source: Internet
Author: User
Tags rfc mx record nslookup
first, what is the domain Name System

DNS computer Domain Name System (DNS) is composed of a parser and a domain name server. When we are on the Internet, the usual input is the URL, in fact, this is a domain name, and our computer network computers can only use IP address to identify each other. Again, we go to a Web server to request a Web page, we can enter the URL in the browser or the corresponding IP address, for example, we want to on the Sina network, we can enter the URL in the address bar of IE, can also enter the IP address, but this kind of IP address we can't remember or say is difficult to remember, So with the domain name, such a domain name will make it easy for us to remember.

Name

Meaning

Characteristics

Domain Name server

Save the domain name and corresponding IP address for all hosts on the network , and have a server that translates the domain name to the IP address feature.

The domain name must correspond to an IP address, and the IP address does not necessarily correspond to only one domain name , with a hierarchical structure similar to the directory tree.

Domain Name resolution server

conversion between a domain name and an IP address

The query order in the domain name resolution process is: local cache record, zone record, forwarding domain name server, root name server.



Second, access to DNS method one: Using the socket module

1. DNS Query

Take the query www.external.example.com as an example. First, the program communicates with the local name server specified by the operating system configuration file. This server is a recursive name server that receives requests and passes them in the appropriate way. The first thing a recursive server does is ask for a. com domain, and the answer is given in the form of a nomination that points to another foreign name server. This name server can provide information that contains. com in the name. When the query is sent to the server, the server responds with another nomination answer, pointing to another server that can provide example.com name information. This loop repeats several times until you query the name server to the External.example.com service.

2. Forward Query

The most basic query is a forward query, which is to look up an IP address based on a host name. The socket library can implement this query, mainly using the function Socket.getaddrinfo (). Note that this function is incompatible with IPv6.

Getaddrinfo (Host,port[,family[,sockettype[,proto[,flags]])

The parameter host is a domain name, given as a string representing an Ipv4/ipv6 address or none.
Parameter port if the string form represents a service name, such as "http" "FTP" "email", or a number, or none
Parameter family is the landlord family, can be af_inet, Af_inet6, Af_unix.
The parameter Socketype can be Sock_stream (TCP) or Sock_dgram (UDP)
The parameter proto is typically 0 and can be ignored directly
The parameter flags are a combination of ai_*, such as Ai_numerichost, which affects the return value of the function.

The function return value is a list of tuple, each tuple is as follows:

(FAMILY,SOCKTYPE,PROTO,CANONNAME,SOCKADDR)

Where sockaddr is actually the address and port of the remote machine, which is the data of the query.

For example:

>>> Import Socket
>>> print socket.getaddrinfo (' www.baidu.com ', None)
[(2, 0, 0, ", (' 61.135.169.125 ', 0)), (2, 0, 0,", (' 61.135.169.105 ', 0))]
>>> print socket.getaddrinfo (' www.baidu.com ', None) [0][4][0]
61.135.169.125
>>> print socket.getaddrinfo (' www.baidu.com ', None) [0][4][1]
0

Note: Because a site may have multiple URLs, it is normal to have different results for two queries. Here is a piece of code that lists all the query results:

Copy the Code code as follows:


##@ Xiao Wu Yi
Import socket
Host=raw_input (' Host: ')
Result=socket.getaddrinfo (Host,none)
Counter=0
For I in Result:
Print "%-2d:%s"% (Counter,i[4])
Counter+=1

The results of the operation are as follows:

>>>
Host:www.baidu.com
0:(' 61.135.169.105 ', 0)
1:(' 61.135.169.125 ', 0)
>>>
Host:www.yahoo.com
0:(' 106.10.170.118 ', 0)
>>>
Host:www.163.com
0:(' 60.210.18.169 ', 0)
1:(' 123.132.254.15 ', 0)
3. Reverse Query
A reverse query is a domain name that is queried by an IP address. It's used here to gethostbyaddr.
GETHOSTBYADDR (Addr,len,type)
The parameter addr can be an IP address of IPv4 or IPV6, the parameter len is the length of the parameter addr, and the parameter type is af_inet.

The following is an example that will reverse-query the domain name of the IP address.

Copy the Code code as follows:


##@ Xiao Wu Yi
Import socket
Hostip=raw_input (' IP: ')
Try
RESULT=SOCKET.GETHOSTBYADDR (HostIP)
Print "hostname:" +result[0]
print "\ n Addresses:"
For I in result[2]:
Print "" +i
Except Socket.herror, E:
Print "counld not look Up name:", E

The operating result is:

>>>

ip:127.0.0.1

Hostname:localhost

Addresses:

127.0.0.1

>>>

ip:216.109.118.73

Hostname:gi-2-19.bas1-1-con.ac2.yahoo.com

Addresses:

216.109.118.73

>>>

ip:123.132.254.15

COUNLD not look up name: [Errno 11004] Host not found

>>>

ip:60.210.18.169

COUNLD not look up name: [Errno 11004] Host not found

From the results of the run, the first query to the two IP put in, but the reverse query not to the domain name, here I do not understand what is the reason, waiting for expert answers.

Third, access to DNS method two: Use Pydns for advanced query

Pydns provides a more powerful interface for accessing the DNS system. Its download address is http://pydns.sourceforge.net. One of the Py3dns is for python3.x, My Learning environment is python2.6, so download installed Pydns. Unzip the download and copy the DNS folder to the Lib\site-packages\ folder under the Python installation folder.

1, simple Pydns query

First call Dns.discovernameservers () to find the name server in the system. Then create a Request Object Dns.request (). Dns. The Req () method of the Request () is used to perform the actual query. Typically there are two parameters: name gives the actual query names; qtype specifies the record type. When a request object is used to make a query request, PYDNS returns an Answer object (Answer object) that contains the result, which has a property called answers, which contains all the returned answer lists.

Before giving an example, the first list of most DNS records is listed below:
A Address. The URL record (fixed to the right) is defined in RFC 1035.
AAAA IPv6 Address. (6th-Generation Web Site table method). Defined in RFC 1886.
AFSDB AFS Data Dase location. Defined in RFC 1183.
The CNAME Canonical name (formal name), defined in RFC 1035. This is the usage of the indicator for the fixed alias (alias). Alias is set in LHS, the official name is set in RHS.
GPOS geographic POSition (geographic location), defined in RFC 1712. Deprecated (obsolete) usage, not recommended. .
HINFO Host Information (basic machine information; OS, hardware, ...), defined in RFC 1035.
ISDN ISDN (Integrated Digital Network URL notation), defined in RFC 1183.
Key Publick key (public gold key; DNS data, through encoding, password communication), is defined in RFC 2065.
LOC location (the geographic area in which the network resides; the latitude and longitude of the table), as set out in RFC 1876.
MB MailBox. (mailbox; is rarely used), as defined in RFC 1035. -Refer to MX record items.
MD is defined in RFC 1035. Deprecated (obsolete) usage, not recommended. -Refer to MX record items.
MF is defined in RFC 1035. Deprecated (obsolete) usage, not recommended. -Refer to MX record items.
MG is defined in RFC 1035.
MINFO is defined in RFC 1035.
The MR is defined in RFC 1035.
MX Mail EXchanger. (e-mail, delivery settings). defined in RFC 1035. The basic usage is that when an email address contains the LHS of an MX record, then the email delivery system will forward the e-mail message to the system indicated by the RHS of the MX, to be processed further.
Null empty records (such as blank lines, etc.), which are not intended for practical purposes, are defined in RFC 1035.
The NS name Server (which represents RHS as a domain name servo machine) is defined in RFC 1035.
NSAP Network Services Access point address. (Iso-osi Network Service, URL notation) is defined in RFC 1348, and is redefined by RFC 1637 and 17,062 times, respectively.
NSAP-PTR is defined in RFC 1348. Obsolete usage.
The NXT is defined in RFC 2065.
PTR PoinTeR. (indicator), defined in RFC 1035. Usually used to addr IP. Just go back to one of the corresponding domain name.

The following is a simple example:

Copy the Code code as follows:


##@ Xiao Wu Yi
#-*-coding:cp936-*-
Import DNS
Query=raw_input (' Input DNS: ')
Dns. Discovernameservers ()

Reqobj=dns. Request ()
Answerobj=reqobj.req (Name=query,qtype=dns. Type.any)
If not Len (answerobj.answers):
Print "Not Found"
For I in Answerobj.answers:
Print "%-5s%s"% (i[' typename '],i[' data ')

Operation Result:

Input dns:163.com

TXT [' V=spf1 Include:spf.163.com-all ']
A 123.58.180.8
A 123.58.180.5
A 123.58.180.6
A 123.58.180.7
MX (, ' 163mx03.mxmail.netease.com ')
MX (+, ' 163mx00.mxmail.netease.com ')
MX (, ' 163mx01.mxmail.netease.com ')
MX (, ' 163mx02.mxmail.netease.com ')
NS ns2.nease.net
NS ns4.nease.net
NS ns3.nease.net
NS ns1.nease.net
Input DNS:www.yahoo.com
CNAME fd-fp3.wg1.b.yahoo.com

2, query the special name server

In the previous example, for any type of query, there is a special case where the MX records is sometimes lost without prior request. As a result, any is not used under normal circumstances. The workaround is to bypass the local name server and send the query directly to the authoritative name server in the domain. To do so, you need to use the system's default name server to find the authoritative name server. This is accomplished by finding the NS records that are close to the current domain. The following example:

Copy the Code code as follows:


##@ Xiao Wu Yi
#-*-coding:cp936-*-
Import DNS
def hierquery (Qstring,qtype):
Reqobj=dns. Request ()
Try
Print Query
Answerobj=reqobj.req (Name=query,qtype=qtype)
answers=[x[' data ' for x in Answerobj.answers if x[' type ']==qtype]
Print answers
Except DNS. Base.dnserror:
Answers=[]
If Len (answers):
Return answers
Else
Remainder=qstring.split (".", 1)
If Len (remainder) ==1:
Return None
Else
Return Hierquery (Remainder[1],qtype)
def findnameservers (hostname):
Return Hierquery (Hostname,dns. TYPE.NS)
def getrecordsfromnameserver (qstring,qtype,nslist):
For NS in Nslist:
Reqobj=dns. Request (Server=ns)
Try
Answers=reqobj.req (Name=qstring,qtype=qtype). answers
If Len (answers):
Return answers
Except DNS. Base.dnserror:
Pass
return []

Def nslookup (qstring,qtype,verbose=1):
Nslist=findnameservers (qstring)
If Nslist==none:
Raise RuntimeError, ' server not found '
If verbose:
Print "Server:", ",". Join (Nslist)
Return Getrecordsfromnameserver (Qstring,qtype, Nslist)
If __name__== ' __main__ ':
Query=raw_input (' Enter website: ')
Dns. Discovernameservers ()
Answers=nslookup (Query,dns. Type.any)
If not Len (answers):
Print "Not Found! "
For I in answers:
Print "%-5s%s"% (i[' typename '],i[' data ')

The results of the operation are as follows:

Input website: 163.com

Server: Ns3.nease.net,ns1.nease.net,ns2.nease.net,ns4.nease.net

A 123.58.180.8
A 123.58.180.5
A 123.58.180.6
A 123.58.180.7
MX (, ' 163mx02.mxmail.netease.com ')
MX (, ' 163mx03.mxmail.netease.com ')
MX (+, ' 163mx00.mxmail.netease.com ')
MX (, ' 163mx01.mxmail.netease.com ')
TXT [' V=spf1 Include:spf.163.com-all ']
NS ns4.nease.net
NS ns1.nease.net
NS ns2.nease.net
NS ns3.nease.net

SOA (' ns4.nease.net ', ' admin.nease.net ', (' serial ', 20014505), (' Refresh ', 801, ' minutes '), (' Retry ', 3600, ' 1 hours ') , (' Expire ', 604800, ' 1 weeks '), (' Minimum ', 18000, ' 5 hours '))

Enter website: baidu.com

Server: dns.baidu.com,ns4.baidu.com,ns2.baidu.com,ns3.baidu.com

SOA (' dns.baidu.com ', ' sa.baidu.com ', (' serial ', 2012081509), (' Refresh ', ', ' 5 minutes '), (' Retry ', ' 5 minutes '), (' Expire ', 2592000, ' 4 weeks '), (' Minimum ', 7200, ' 2 hours '))

TXT [' v=spf1 ip4:61.135.163.0/24 ip4:220.181.50.0/24 ip4:220.181.18.241 ip4:61.208.132.13 ip4:220.181.27.29 IP4 : 202.108.22.171 ip4:61.135.162.0/24 ip4:220.181.5.0/24 ip4:123.125.66.0/24 ip4:61.135.168.0/24 a mx ptr ~all ']

A 123.125.114.144
A 220.181.111.85
A 220.181.111.86
MX (the ' jpmx.baidu.com ')
MX (the ' mx50.baidu.com ')
MX (, ' mx.mailcdn.baidu.com ')
MX (the ' mx1.baidu.com ')
NS ns4.baidu.com
NS ns2.baidu.com
NS ns3.baidu.com
NS dns.baidu.com

3. Decomposition of query results

Some records, especially NS, PTR, and CNAME, contain another host name in the data returned. In order to obtain the final IP, the returned information needs to be decomposed. This is done using the following code:

Copy the Code code as follows:


##@ Xiao Wu Yi
Import sys, DNS, re
def hierquery (Qstring,qtype):
Reqobj=dns. Request ()
Try
Answerobj=reqobj.req (Name=query,qtype=qtype)
answers=[x[' data ' for x in Answerobj.answers if x[' type ']==qtype]
Except DNS. Base.dnserror:
Answers=[]
If Len (answers):
Return answers
Else
Remainder=qstring.split (".", 1)
If Len (remainder) ==1:
Return None
Else
Return Hierquery (Remainder[1],qtype)
def findnameservers (hostname):
Return Hierquery (Hostname,dns. TYPE.NS)
def getrecordsfromnameserver (qstring,qtype,nslist):
For NS in Nslist:
Reqobj=dns. Request (Server=ns)
Try
Answers=reqobj.req (Name=qstring,qtype=qtype). answers
If Len (answers):
Return answers
Except DNS. Base.dnserror:
Pass
return []

Def nslookup (qstring,qtype,verbose=1):
Print qstring
Nslist=findnameservers (qstring)
Print Nslist
If Nslist==none:
Raise RuntimeError, ' server not found '
If verbose:
Print "Server:", ",". Join (Nslist)
Return Getrecordsfromnameserver (Qstring,qtype, Nslist)

def getreverse (query):
"" "Given the query, returns an appropriate reverse lookup string
Under IN-ADDR. ARPA if query is an IP address; Otherwise, returns None.
This function was not ipv6-compatible. ""
If Re.search (' ^/d+/./d+/./d+/./d+$ ', query):
octets = Query.split ('. ')
Octets.reverse ()
Return '. '. Join (octets) + '. In-addr. ARPA '
Return None

Def formatline (Index, TypeName, DESCR, data):
RetVal = "%-2s%-5s"% (index, typename)
if Isinstance (data,list) :
return retval
Else:

data = Data.replace ("/n", "/n")
if descr! = None and Len (DESCR):
RetVal + = "%-12s"% (Descr + ":")
return retval + "+ data

DNS. Discovernameservers ()
Query1=raw_input (' Enter Web site: ')
queries = [(Query1, DNS. Type.any)]
Donequeries = []
descriptions = {' A ': ' IP address ',
' TXT ': ' Data ',
' PTR ': ' Host name ',
' CNAME ': ' Alias for ',
' NS ': ' Name server '}

while Len (queries):
(query, Qtype) = Queries.pop (0)
if query in Do Nequeries:
# Don ' t look up the same thing twice
continue
Donequeries.append (query)
Print "-" *
Prin T "Results for%s (lookup type%s)"% (query, DNS. Type.typestr (qtype))
Print
Rev = getreverse (query)
If Rev:
Print "IP address given; Doing reverse lookup using ", rev
query = Rev

Answers = nslookup (query, qtype, verbose = 0)
If not Len (ANSW ERS):
print "not found."

Count = 0
For answer in answers:
Count + = 1
If answer[' typename '] = = ' MX ':
Print Formatline (count, answer[' TypeName '),
' Mail server ',
"%s, priority%d"% (answer[' data '][1],
answer[' data '][0]))
Queries.append ((answer[' data '][1], DNS. TYPE.A))
Elif answer[' typename '] = = ' SOA ':
data = "/n" + "/n". Join ([STR (x) for x in answer[' data '])
# #print Data
Print Formatline (count, ' SOA ', ' Start of authority ', data)
Elif answer[' TypeName '] in descriptions:
# #print answer[' data '
Print Formatline (count, answer[' TypeName '),
Descriptions[answer[' TypeName '], answer[' data ')
Else
Print Formatline (count, answer[' TypeName '), None,
STR (answer[' data '))
If answer[' TypeName '] in [' CNAME ', ' PTR ']:
Queries.append ((answer[' data '), DNS. Type.any))
If answer[' typename '] = = ' NS ':
Queries.append ((answer[' data '), DNS. TYPE.A))

I am running, always error, did not find the reason, looking for expert guidance.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.