dnspython是python实现的一个DNS工具包,它支持记录类型、查询、传输并动态更新ZONE信息等等。据说dnspython可以代替dig、nslookup等工具。下面我们就来介绍dnspython模块的使用。
dnspython源码安装
这里介绍一下dnspython模块的安装,采用源码的安装方式,目前使用的版本是1.16.0
如下安装:
wget https://www.dnspython.org/kits/1.16.0/dnspython-1.16.0.tar.gz
tar -zxvf dnspython-1.16.0.tar.gz
cd dnspython-1.16.0
python setup.py install
看到红框的信息说明安装完成了。
python模块域名解析方法讲解
平常测试DNS的时候,有些操作手动处理不方便,需要写个脚本来实现,这是就会想到使用dnspython模块,它提供了大量的DNS处理方法,我们知道最常用的方法就是域名查询,dnspyhton库提供一个解析器类(resolver),我们可以使用它query方法实现域名查询功能。这里要说一下query:
query(self, qname, rdtype = 1, rdclass = 1, tcp = False, source = None, raise_on_no_answer = True, source_port = 0)
qname:查询的域名。
rdtype :指定RR资源的类型
A记录:将主机名转换成IP地址
MX记录:邮件交换记录,定义邮件服务器的域名
CNAME记录:别名记录,实现域名间的映射
NS记录:标记区域的域名服务器及授权子域
PTR记录:反向解析,与A记录相反,将IP地址转换为主机名
SOA记录:SOA标记,一个起始授权区的定义
rdclass: 指定网络类型,可选的值为CH、IN。其中IN为默认的,使用最广泛。
tcp :指定查询是否启动TCP协议,默认不启动。
source与source_port:指定的查询源地址与端口。
raise_on_no_answer :指定查询无应答时是否触发异常,默认为True。
下面我们开始对常见解析类型进行说明。
解析类型说明
A记录
#!/usr/local/bin/python38
# -*- coding: utf-8 -*-
import dns.resolver
domain = input('Please input an domain: ') #输入域名地址
A = dns.resolver.query(domain, 'A') #查询记录为A记录
for i in A.response.answer:
for j in i.items:
if j.rdtype == 1: #加判断,不然会出现AttributeError: 'CNAME' object has no attribute 'address'
print(j.address)
运行代码查看结果,这里以www.baidu.com域名为例:
这样子我们就将www.baidu.com的域名解析出来了。 来看看效果:
MZ记录
#!/usr/local/bin/python38
# -*- coding: utf-8 -*-
import dns.resolver
domain = input('Input an domain : ')
MX = dns.resolver.query(domain, 'MX') # 指定解析类型为MX记录
for i in MX: # 遍历回应结果
print('MX preference =', i.preference, 'mail exchanger =', i.exchange)
运行代码查看结果,这里以qq.com域名为例:
其中我们可以看到preference值(优先级)和exchange值(交换地址),其中优先级默认为10,MX记录可以通过设置优先级实现主辅服务器设置,”优先级”中的数字越小表示级别越高,“优先级”仅对MX记录有效。
NS记录
NS(Name Server)域名服务器记录。用来表明由哪台服务器对该域名进行解析。在注册域名时,总有默认的DNS服务器,每个注册的域名都是由一个DNS域名服务器来进行解析的。
下面实现NS记录查询方法:
#!/usr/local/bin/python38
import dns.resolver
domain = input('Input an domain : ')
NS = dns.resolver.query(domain, 'NS')
for i in NS.response.answer:
for j in i.items:
print(j.to_text())
运行结果如下:
只限输入一级域名,如baidu.com。如果输入二级或多级域名,如:www.baidu.com,则是错误的,我们可以试一下,验证问题:
使用CNAME时,CNAME的目标主机地址只能使用主机名,不能使用IP地址。主机名前不能有任何其他前缀,如:http://等是不被允许的。
来看看下面代码实现CNAME记录方法:
#!/usr/local/bin/python38
import dns.resolver
domain = input('Input an domain: ')
CNAME = dns.resolver.query(domain,'CNAME')
for i in CNAME.response.answer:
for j in i.items:
print(j.to_text())
运行结果出现www.a.shifen.com域名,这个域名就是www.baidu.com的别名指向。相当于用子域名来代替ip地址,优点是如果ip地址变化,只需要改动子域名的解析,而不需要逐一改变ip地址解析。
DNS域名轮询业务监控
大部分的DNS解析器都是一个域名对应一个IP地址,但是通过DNS轮询技术可以做到一个域名对应多个IP,从而实现最简单高效的负载平衡,不过此方最大的弊端是目标主机不可用时无法被自动剔除,因此做好业务主机的服务可用监控至关重要。
下面我们来实现域名的解析,获取域名的所有A记录解析IP列表。
#!/usr/local/bin/python38
import dns.resolver
import httplib2
iplist = []
appdomain = "www.baidu.com"
def get_iplist(domain=""):
try:
A = dns.resolver.query(domain,"A")
except Exception as e:
print("dns resolver error:" + str(e))
return
for i in A.response.answer:
for j in i.items:
if j.rdtype == 1:
iplist.append(j.address)
return True
def checkip(ip):
checkurl = 'http://' + ip + ":80"
getcontent = ""
httplib2.socket.setdefaulttimeout(5)
conn = httplib2.Http()
try:
resp,getcontent=conn.request(checkurl)
finally:
if resp['status']== "200":
print(ip+"[OK]")
else:
print(ip+"[Error]")
if __name__ == "__main__":
if get_iplist(appdomain) and len(iplist) > 0:
for ip in iplist:
checkip(ip)
运行结果如下:
从结果可以看出,域名www.baidu.com解析出3个IP地址,并且服务都是正常的。上面的代码,第一步通过dns.resolver.query()方法获取业务域名A记录信息,查询出所有IP地址列表,再使用httplib模块的request()方法以GET方式请求监控页面,监控业务所有服务的IP是否服务正常。
总结
我们知道将IP地址转换为可读格式或单词后,便称为域名。在python中,域名到IP地址的转换由python模块dnspython管理。它支持记录类型、查询、传输并动态更新ZONE信息的方法。感兴趣的朋友,可以去看看dnspython源码。
欢迎关注微信公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下: