dnspython是python 实现的一个dns场景的工具包。

        dnspython(http://www.dnspython.org/)是Python实现的一个DNS工具包,它支持几乎所有的记录类型,可以用于查询、传输并动态更新ZONE信息,同时支持TSIG(事务签名)验证消息和EDNS0(扩展DNS)。在系统管理方面,我们可以利用其查询功能来实现DNS服务监控以及解析结果的校验,可以代替nslookup及dig等工具

安装:

pip install dnspython

python修改DNS服务器 python dns_dns

dns.resolve源码解析:

def resolve(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
            tcp=False, source=None, raise_on_no_answer=True,
            source_port=0, lifetime=None, search=None):
    """Query nameservers to find the answer to the question.

    This is a convenience function that uses the default resolver
    object to make the query.

    See ``dns.resolver.Resolver.resolve`` for more information on the
    parameters.
    """

    return get_default_resolver().resolve(qname, rdtype, rdclass, tcp, source,
                                          raise_on_no_answer, source_port,
                                          lifetime, search)

参数解析:

  • qname 指定查询的名称
  • rdtype 指定查询的类型 默认是A记录
  1. A记录,将主机名转换为IP地址;
  2. MX记录,邮件交换记录,定义邮件服务器的域名;
  3. CNAME记录,指别名记录,实现域名间的映射;
  4. NS记录,标记区域的域名服务器及授权子域;
  5. PTR记录,反向解析,与A记录相反,将IP转换为主机名;
  6. SOA记录,SOA标记,一个起始授权区的定义。
  • rdclass 指定查询的网络类型 ,可选的值有IN、CH与HS,默认是 IN
  • tcp 是否启用tcp查询模式
  • source 和source_port 指定 查询用的源地址和端口
  • raise_on_no_answer 查询无结果的时候,是否需要抛出异常
  • lifetime 声明周期配置参数,采用默认值

1、A记录  实现A记录查询方法源码

示例代码: 

# 导包
import dns.resolver

domain = 'www.baidu.com'

# 获取解析对象
query_object = dns.resolver.resolve(qname=domain, rdtype='A')  # 指定查询记录为A
print('查询对象:{}'.format(query_object))

print('*' * 100)

# 查看response对象
response_object = query_object.response
print('应答对象:{}'.format(response_object))

print('*' * 100)

# 查询answer对象
answer_object = response_object.answer
print('解析对象:{}'.format(answer_object))

print('*' * 100)

# 查看解析条目对象
answer_object = response_object.answer
for query_item in answer_object:
    print('查询条目:{}'.format(query_item))

print('*' * 100)

# 解析后的记录条目
query_item = response_object.answer[0]
# print(query_item)
for item in query_item:
    print('解析记录:{}'.format(item))

print('*' * 100)

运行结果:

python修改DNS服务器 python dns_pythondns模块_02

示例代码: 

# 导包
import dns.resolver

domain = 'www.baidu.com'

query_object = dns.resolver.resolve(qname=domain, rdtype='A')
for query_item in query_object.response.answer:
    for item in query_item.items:
        print("{}的A记录解析地址有:{}".format(domain, item))

运行结果:

python修改DNS服务器 python dns_dns_03

示例代码:

import dns.resolver

domain = 'www.baidu.com'
# 指定查询类型为A记录
A = dns.resolver.query(domain, 'A')
# 通过response.answer方法获取查询信息
for i in A.response.answer:
    print('+' * 100)
    print(i)
    # 遍历回应信息
    for j in i.items:
        print(j)
    print("*" * 100)

运行结果:

python修改DNS服务器 python dns_dns_04

2、MX记录 实现MX记录查询方法源码

 示例代码:

# 必须这样导入
import dns.resolver

ret = dns.resolver.query('dnspython.org', 'MX')
print(ret)

for data in ret:
    print(data)

print('*' * 100)

for data in ret:
    print(data.exchange, data.preference)

print('*' * 100)

ret2 = dns.resolver.resolve('dnspython.org', 'MX')
print(ret2)
for data in ret2:
    print(data.exchange, data.preference)

运行结果:

python修改DNS服务器 python dns_DNS_05

示例代码:

import dns.resolver

domain = '126.com'

# 获取解析对象
query_object = dns.resolver.resolve(domain, 'MX')  # MX记录
print('MX记录的结果:{}'.format(query_object))

print('*' * 100)

# 从应答的response中获取查询记录
resp_object = query_object.response
print('MX记录的结果:{}'.format(resp_object))

print('*' * 100)

# 从应答的answer中获取查询目录
answer_object = resp_object.answer
print('MX记录的结果:{}'.format(answer_object))

print('*' * 100)

# 查看解析条目对象
answer_object = resp_object.answer
for query_item in answer_object:
    print('查询条目:{}'.format(query_item))

print('*' * 100)

# 查看解析后的记录条目
query_item = resp_object.answer[0]
for item in query_item.items:
    print('查询条目:{}'.format(item))

print('*' * 100)

# 查看解析后的记录条目-详细
query_item = resp_object.answer[0]
for item in query_item.items:
    print('邮件服务器权重:{},邮件服务器地址:{}'.format(item.preference, item.exchange))

运行结果:

python修改DNS服务器 python dns_pythondns模块_06

示例代码: 

# 导包
import dns.resolver

domain = '126.com'

query_object = dns.resolver.resolve(domain, 'MX')
for query_item in query_object.response.answer:
    for item in query_item.items:
        print('邮件服务器权重:{},邮件服务器地址:{}'.format(item.preference, item.exchange))

运行结果:

python修改DNS服务器 python dns_dns_07

示例代码:

import dns.resolver

# 输入域名地址
domain = 'baidu.com'

# 指定查询类型为MX
MX = dns.resolver.query(domain, 'MX')

# 遍历回应结果,输出MX记录的preference及exchanger信息
for i in MX:
    print('MX preference=', i.preference, 'mail exchange=', i.exchange)

运行结果:

python修改DNS服务器 python dns_dns_08

3、NS记录 实现NS记录查询方法源码

        NS(Name Server)域名服务器记录。用来表明由哪台服务器对该域名进行解析。在注册域名时,总有默认的DNS服务器,每个注册的域名都是由一个DNS域名服务器来进行解析的。但是需要注意的是只能输入一级域名,如:baidu.com;对于二级以及多级域名,如www.baidu.com、wenku.baidu.com则是错误的。

示例代码:

# 导包
import dns.resolver

domain = '126.com'

NS = dns.resolver.resolve(domain, 'NS')
for i in NS.response.answer:
    for j in i.items:
        print(j.to_text())

运行结果:

python修改DNS服务器 python dns_pythondns模块_09

4、CNAME记录 实现CNAME记录查询方法源码

示例代码:

# 导包
import dns.resolver

domain = 'www.baidu.com'

CNAME = dns.resolver.resolve(domain, 'CNAME')
for i in CNAME.response.answer:
    for j in i.items:
        print(j.to_text())

运行结果:

python修改DNS服务器 python dns_dns_10

5、案例分析:DNS域名轮询业务监控

        大部分的DNS解析都是一个域名对应一个IP地址,但是通过DNS轮询技术可以做到一个域名对应多个IP,从而实现最简单高效的负载均衡,不过此方案最大的弊端是目标主机不可用时无法被自动剔除,因此做好业务主机的服务可用监控至关重要。

实现步骤:

  1. 实现域名的解析,获取域名所有的A记录解析IP列表
  2. 对IP列表进行HTTP级别的探测

具体实现方式:

第一步通过dns.resolver.query()方法获取业务域名A记录信息,查询出所有IP地址列表;

第二步使用httplib模块的request()方法以GET请求监控页面,监控业务所有服务的IP是否正常。

示例代码:

import dns.resolver
import http.client

# 定义域名ip列表变量
ip_list = []
# 定义业务域名
app_domain = "www.baidu.com"
# app_domain = "www.blog.csdn.net"


# 域名解析函数,解析成功IP将被追加到ip_list
def get_ip_list(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:
            # 追加到ip_list列表
            ip_list.append(j)
    return True


def check_ip(ip):
    check_url = str(ip) + ": 80"
    get_content = ""
    # 定义http连接5秒超时(5)秒
    http.client.socket.setdefaulttimeout(5)
    # 创建http连接对象
    conn = http.client.HTTPConnection(check_url)
    try:
        # 发起url请求,添加host主机头
        conn.request("GET", "/", headers={"Host": app_domain})
        r = conn.getresponse()
        # 获取URL页面前15个字符用来可用性效验
        get_content = r.read(15)
    finally:
        # 监控URL页的内容一般是事先定义好的比如http 200等
        # 判断是否为字节
        if isinstance(get_content, bytes):
            get_content = get_content.decode('utf-8')
        if get_content == "<!DOCTYPE html>":
            print(str(ip) + "\033[32;1m [ok]\033[0m")
        else:
            print(str(ip) + "\033[31;1m [Error]\033[0m")
        # 获取response的状态码
        print(r.reason)
        # 获取response的状态 ok或error
        print(r.status)


if __name__ == "__main__":
    # 域名解析正确且至少返回一个IP
    if get_ip_list(app_domain) and len(ip_list) > 0:
        for ip in ip_list:
            check_ip(ip)
    else:
        print("dns resolver error.")

运行结果:

python修改DNS服务器 python dns_dns_11