域名系统(DNS)是一个分布式数据库,用来把主机名编程IP地址,DNS以及想关系统之所以存在,有以下两个原因:域名例如www.jevylee.com比IP地址例如222.11.111.22更好记。此外,一个域名在不同的时间段可以使不同的IP,使一个网站可以有多个服务器。当前,对python来说,有几种不同的DNS模块,PyDNS就是其中一种。其他的有dnspython,可以从www.dnspython.org得到。还可以从http://pilcrow.madison.wi.us/得到dnslook。还有adns,一个异步DNS库,可以从http://dustman.net/andy/python/adns-python得到。
DNS是一个庞大的、全球分布式数据库。运作过程如下:首先,您的程序会和操作系统配置文件指定的本地DNS服务器通信。这个服务器是一个递归的名称服务器,它收到请求并以适当的方式传递下去,它会完成大量工作。距离查询external.example.com,递归服务器做的第一件事情是询问.com域。后者有个内置的顶级域名列表,这些服务器可以分发世界上顶级域名的信息,例如.com。对于.com的回答以一种指向另外一个名称服务器的提名形式给出的。这个民称服务器可以提供名称中包含.com的信息。查询会发送到这个服务器,然后改.com服务器以另外一个提名进行回答,这个提名回答指向另外一台服务器,而这个服务器可以提供example。com的名称信息。这个循环重复多次,直到最终查询到达为external.example.com服务的名称服务器。这个服务器知道问题中的IP地址,并返回它。操作系统提供执行基本DNS查找的服务,这些服务对大多数程序来说是足够的,直接节约了花费在DNS查询上的时间。Python在它的socket模块中,提供了访问这些基本操作系统服务的接口。第三方模块还提供了很多更高级的功能。
操作系统本身带有一些用于DNS查找的功能(经常被称为resolver库),这些功能可以满足大部分应用程序的需求。有些程序,有其是邮件服务器和DNS查询程序,则需要一些更先进的工具。很多UNIX系统包含一个名为/etc/hosts的文件,其中定义了主机名和IP地址。操作系统对于查询通常会先查看/etc/hosts,如果没有找到答案,则会去DNS查询。一般来说,windows机器是不是用主机文件的。同样,每种操作系统都会为管理员提供一个办法来为DNS服务器指定IP地址,这样才能解决查询问题。在UNIX系统上是通过/etc/resolv.conf来实现的,而在windows系统上,则是通过注册表,并且是通过控制面板中的网络连接的TCP/IP设置来维护的。在这两种机器上,提供了默认的名称服务器和默认的域名。
最基本的查询是正向查询,它根据一个主机名来查找IP地址。例如,如果您想从www.example.com上下载一个web页面,首先,您需要找到IP地址。某些时候,python的Socket库会实现这种正向查询,在Python中使用的是socket.getaddrinfo()。python的定义如下:
getaddrinfo(host,port[,family[,socktype[,proto[,flags]]]])
C程序员会很熟悉gethostbyname()函数。python确实也提供了一个类似的socket.gethostbyname()函数,但是这个函数和IPv6不兼容。getaddrinfo函数host参数就是寻找的域名,其他参数只有当你想把结果传给socket.socket()或socket.connect()的时候才用到。它们会在输出中限制显示什么协议,以及为了建立Socket而填写根据默认值得到的结果。可以设置port值为none,然后省略其他参数来进行一个基本查询。python定义socket.getaddrinfo()的返回值是一列tuple,每一个tuple看上去如下:(family,socktype,proto,canonname,sockaddr)sockaddr实际上就是机器的地址,是执行查找时要找的数据,因为python tuple中的元素以0开始,他是结果中的第四个元素。socket.getaddrinfo()函数返回一个tuple的列表是因为对于一个查询,可能有多个答案。例如,一个网站有几个服务器,就会对一个域名返回多个IP地址。可以使用其中的任何一个,这样可以解决负载的问题。

也可以通过getaddrinfo()获得全部的条目也可以:

反向查找对于一个IP地址,完全有可能不存在反向映射。很多IP地址都没有对应的域名。下面是一个用python实现反向擦好找的例子,它会把命令行中给出的IP地址作为参数,并返回相应的域名,代码如下:

有时候会有一些客户端使用伪造的hostname来欺骗服务器,从而连接到服务器。服务器可以使用下面的程序来发现这个现象:

这个例子,IP地址不是非常有用,因为只是用来回查接口地址。大多数机器都有回路和至少一个配置的网络设备,所以IP地址可能有多个。这个例子中最有用的是本地主机名。很多系统是在私有网络上的,在公共的Internet上既得不到主机名,也得不到完整的名称。

下面讲述一些DNS Records的知识,熟悉DNS系统的人都知道记录值的概念,A记录值给出一个主机名的IP地址,AAAA记录值给出一个主机的IPv6地址,CNAME记录值给出主机别名,CNAME也会指向一条A记录的主机名,后者给出了最终的IP地址。有时候,CNAME也指向PTR记录,而不是A记录。MX是指定有限选择的邮件交换服务器,本身有一个顺序,会从具有最小顺序数字的服务器开始尝试。PTR记录为一个IP地址提供主机名,用在反向查询中。NS记录为一个域名定义DNS服务器。TXT记录存储一个关于主机的专门信息,例如描述。SOA存有起始授权机构信息,它含有一些如何在DNS上保存record的信息。
由操作系统查询只能得到A,AAAA,和CNAME records。方向只能得到PTR和CNAME records。所以,为了获得其他信息,必须使用PyDNS或者其他DNS库。在pydns.sourceforge.net上下载PyDNS库后,打开Python shell。运行DNS.DiscoverNameServers()。如果有显示,则说明可以找到DNS服务器。如果没有反应,则说明找不到DNS服务器,可以手动设置,DNS.defaults[‘servers’] = [‘8.8.8.8′,’…’]你可以设置多个。初始化完成DNS服务器后,下一步需要建立一个请求对象,调用DNS.Request(),这个函数有两个参数,一个是name,一个是qtype,前者指明需要查询的名称,后者指定了前面列表中的某条record类型。
下面是一个利用PyDNS编写的简单的查询程序:

上面的程序查询的是DNS服务器上的缓存,并不能获得完整的DNS信息。需要查询名称完整的DNS信息,需要使用下面的程序:

此外还有反向DNS的程序,如下:

如果使用PyDNS来完成反向查询。必须颠倒IP地址的内容,把IN-ADDR.ARPA家在后面。这是DNS协议使用的基本格式,并在反向查询中必须使用。

总结:
Domain Name System(DNS)用于在文字名称和底层通信的IP地址之间转换,Python通过Socket模块提供了访问操作系统本身DNS的接口。可以通过gethostname()得到程序运行机器上的信息,可以得到机器本身的主机名。

2014.10.11—Mac下ssh翻墙

今天闲来无事,研究了一下mac下的翻墙。VPN,goagent,ssh。亲测之后还是觉得ssh是最方便的。由于mac自带的Unix解释器。因此本身就支持ssh命令。当你有一个免...

阅读全文

2014.7.25—Python网络编程(三):网络服务器

服务器的特点是等待请求,返回应答。对于客户端来说,一般只需要两步。建立Socket对象调用connect()来建立一个和服务器的连接。对于服务器,这个过程需要4步...

阅读全文

2014.7.23—Python网络编程(二)

Socket网络编程,当不涉及底层的东西时十分简单。Python的Socket编程比C语言更加的简单,举例,C语言要建立TCP时需要知道IP地址和端口号,不能直接按照域名和...

阅读全文

欢迎留言

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据