wireshark抓取dns_利用Scapy打造简单的DNS监测脚本

简介

因为最近工作中有个需求是需要记录终端的dns请求,并进行对比和记录,这里研究了一下,使用python写了一个简单的本机dns请求的监控脚本。脚本设置后可以监控本机对特定域名的请求记录,以及记录这些dns请求的响应内容。用到了python一个看起来应用可以很广的(据我搜索的结果,可以使用这个模块进行本机的, 好像并没有什么明显的意义, DNS欺骗)模块——scapy。本文只使用了这个模块的一小部分功能。

Scapy

Scapy是python一个非常强大的应用框架,可以非常方便的实现数据包的发送,嗅探,拆解和伪造(原文是forge,想了好几个词,不太确定要用生成和捏造...orz好像更奇怪了)数据包,可以用于编写对网络探测,扫描和攻击的工具。官方的介绍文档在这里:

https:// scapy.readthedocs.io/en /latest/ --scapy official documentation

我在自己的python 3.7环境下使用pip安装了scapy[basic]

pip install --pre scapy[basic]

这里因为时间比较赶,直接使用了官方的推荐安装方式(这种做法以后还是少一点好),之后就可以愉快的使用命令行中的wireshark了。另外需要注意的是,我使用的是win10系统,并且安装了npcap,所以其他版本的捕包软件不一定能和脚本兼容,所以运行前一定先检查scpay能在当前环境下抓取到什么格式的报文,如果报文格式不对,脚本运行不会出结果或直接报错,请知悉。

开始干活!

开始之前有几点需要注意的,scapy会使用wincap捕捉数据包,所以开始前确保电脑是安装了winpcap或npcap的,不然嗅探是无法正常工作的。另外先了解一下TCP/IP四层模型中的DNS协议报文。 我在下面直接贴了一个:

v2-b1a7c330721615b7359ad2b516a24c9a_b.jpg

这个报文是直接使用sniff(filter='udp and port 53', prn=lambda x:x.summary)模块抓取下来的,我对长报文进行了重新排版(狠狠夸一波VScode,相见恨晚),你可以看出这个报文遵循了TCP/IP的四层模型,对应如下:

Ether部分 -- 对应网络接口层
IP部分 -- 对应网络层
UDP部分 -- 对应传输层
DNS部分 -- 对应应用层

从报文的实际内容也可以看出,上面是query,下面是收到的response,即客户机向1.1.1.1这个dns服务器请求http://bing.com的地址,1.1.1.1则回复了两个可用的IP,204开头的和13开头的。下面是实际nslookup的回复内容:

v2-0f301bde1aa6a52d2e5b207c91c23586_b.jpg

上面的dns报文只是使用过滤器简单过滤了可能的dns报文后进行的简单展示,我们后面会展示代码对DNS请求和DNS应答进行进一步过滤。

代码部分

参考了一些其他脚本后写的,使用VScode 预运行的时候提示有很多import了但未使用的组件,估计还有优化空间。(优化和前面的几篇文章说的一样,是以后的事orz..)

# -*- coding:utf8 -*-
from scapy.all import *
from scapy.layers.dns import DNSRR, DNSQR
import time


def dns_sniff(pkt):
    if DNSQR in pkt and pkt.dport == 53:
        if 'bing.com' in str(pkt[DNSQR].qname):
            print(time.strftime("%H:%M:%S",time.localtime()))
            print("Host is requesting for url: %s from %s" %(
                pkt[DNSQR].qname[:-1], pkt[IP].dst))
    elif DNSRR in pkt and pkt.sport == 53:
            if 'bing.com' in str(pkt[DNSRR].rrname):
                for i in range(pkt[DNS].ancount):
                    dnsrr = pkt[DNS].an[i]
                    print("Server offers: %s is in %s" %(
                        dnsrr.rrname[:-1], dnsrr.rdata))

def main():
    sniff(filter="udp and port 53", prn=dns_sniff)
if __name__ == "__main__":
    main()

这里实现的主要是监控并过滤出对http://bing.com的DNS请求。代码部分请结合sniff得到的较原始的报文内容进行查阅,如果有对报文其他部分内容的摘出需求,可以结合报文去修改脚本以实现更自主化的应用。

运行后,我们再在客户机上访问目标地址或直接使用nslookup发送DNS请求,你就可用看到输出的内容了:

v2-7e5416505c27b65f27de12c919f51331_b.png

实际上脚本可以使用python对字符串的操作把域名附近的b'**'内容去掉,不过这是美观的需求了,这个脚本实际上已经可以满足我的需求了,为了方便记录我还加上了时间戳,为了记录DNS请求发生的时间。

后面可以继续使用探测到的结果进行其他的操作,这里就不一一说明了。另外发现nslookup进行DNS请求的时候实际上会进行两次,一次是ipv4的请求,另一次是ipv6的请求,暂时没有对这个现象进行深入的研究,应该是nslookup会默认针对ipv4和ipv6进行两次请求,因为sniff给出的报文在Ether部分有type字段,估计不能在一个请求中同时包含两种地址的type。

参考链接

https:// stackoverflow.com/quest ions/25092538/scapy-dns-sniff-with-additional-records --参考了帖子中对报文解析的思路 https:// blog.csdn.net/nixawk/ar ticle/details/45933299 --参考了sniff的用法
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值