用python实现wireshark的follow tcp stream功能

长话短说,wireshark有一个follow tcp stream功能,这个功能很方便。美中不足的是提取出的stream 数据没有时间戳等其他信息,在分析数据的延时和丢包问题时就有些力不从心了。这里简单用python实现了一个简单follow tcp stream功能,同时保留了tcp信息。

原理很简单,仍然是基于wireshark,里面有一个Export packet dissection as XML ‘pdml’ file。 导出来之后的文件内容是这个样子的:

<proto name="tcp" showname="Transmission Control Protocol, Src Port: 59203 (59203), Dst Port: 80 (80), Seq: 1, Ack: 1, Len: 381" size="20" pos="34">
    <field name="tcp.srcport" showname="Source Port: 59203 (59203)" size="2" pos="34" show="59203" value="e743"/>
    <field name="tcp.dstport" showname="Destination Port: 80 (80)" size="2" pos="36" show="80" value="0050"/>
    <field name="tcp.port" showname="Source or Destination Port: 59203" hide="yes" size="2" pos="34" show="59203" value="e743"/>
    <field name="tcp.port" showname="Source or Destination Port: 80" hide="yes" size="2" pos="36" show="80" value="0050"/>
    <field name="tcp.stream" showname="Stream index: 4" size="0" pos="34" show="4"/>
    <field name="tcp.len" showname="TCP Segment Len: 381" size="1" pos="46" show="381" value="50"/>
    <field name="tcp.seq" showname="Sequence number: 1    (relative sequence number)" size="4" pos="38" show="1" value="3b0ac4bd"/>
    <field name="tcp.nxtseq" showname="Next sequence number: 382    (relative sequence number)" size="0" pos="34" show="382"/>
    <field name="tcp.ack" showname="Acknowledgment number: 1    (relative ack number)" size="4" pos="42" show="1" value="397d7582"/>
    <field name="tcp.hdr_len" showname="Header Length: 20 bytes" size="1" pos="46" show="20" value="50"/>

看到上面的内容,我想什么都不用说了。用python简单的做个xml文件解析,将数据提取出来就可以了。

那么剩下的一个问题就是follow tcp stream 这个算法如何实现?本质就是一个tcp数据如何重组的过程,具体可以参考这篇博文TCP数据包重组实现分析

这里,简单起见,我做了一些约束:

  1. 只能提取A-->B这样的单个方向的数据。如果需要提取B-->A的数据,可以重新过滤一下数据,然后执行一次脚本。
  2. 忽略最开头的syn包和断开连接时的Fin包。

基于上面两个简化,实际算法可以简化为根据tcp帧中的seq,从小到大排序。简单举个例子:有三个tcp包,按seq排序后如下样子

(seq=1, nxtseq=5, data=‘1234‘) , (seq=4, nxt=6, data=‘45‘) , (seq=7,nxt=8, data=‘7‘)

第一个数据包的nxtseq > 第二个数据的seq,说明两个数据包之间有数据重复,事实也是如此,重复了数字‘4’

第二个数据包的nxtseq < 第三个数据包的seq,说明这两个数据包之间有丢帧。事实也是如此,丢失了数字‘6’

好了,原理就介绍到这儿。

剩下稍微介绍一下wireshark过滤规则和这个算法的局限性

  1. 按照ip过滤某个方向的数据,一般可以使先执行wireshark的follow tcp stream功能,一般在filter一栏会有这样一个表达式 tcp.stream eq xxx。在这个表达式的后面可以继续跟上ip过滤的表达式:  tcp.steam eq xxx and ip.src==xxx  and ip.dst==xxx
  2. 按照tcp端口号过滤某个方向的数据。首先同ip过滤,先固定到一条tcp连接上,得到tcp.stream eq xxx。 然后加上端口过滤:tcp.stream eq xxx and tcp.srcport==xxx and tcp.dstport==xxx
  3. 这个工具的局限性,因为是基于python element tree 对xml文件进行解析和数据提取,所以即使是解析100M的pcap文件,首先生成的pdml文件就会暴增到几百兆,然后这几百兆的文件又要被读入内存,(python element tree的特点),总计下来就是生成pdml文件有点慢(几分钟),内存消耗特大,几百兆。

最后简单贴一些关键代码。完整的脚本可以从这里免费下载 TCPParser -- follow tcp stream by python

这是从pdml文件的某个proto中提取需要的元素信息。

def extract_element(self, proto, elem):
        result = dict()
        for key in elem.keys():
            result[key]=""

        fieldname   = ""
        attribname  = ""
        for field in proto.findall("field"):
            fieldname = field.get('name')
            if fieldname in elem:
                attribname = elem[fieldname]
                result[fieldname] = field.get(attribname, '')

        return result
def regularize_stream(self, frame_list):
        '''
                    正则化tcp stream的数据,主要是根据seq,nxtseq补上缺少的segment,以及删除重复的数据
                    不少缺少的segment时,data为空,frame.number='lost'
                    删除重复的数据时,尽可能保留较早之前收到的数据,也就是前一个包的数据
        '''
        self.reporter.title("TCPParser regularize timestamp")
        timer = Timer("regularize_stream_data").start()
        reg_frame_list = []
        expectseq = -1
        first = True
        for frame in frame_list:
            if first:
                # 第一个数据包
                first = False
                expectseq = frame["tcp.nxtseq"]
                reg_frame_list.append(frame)
                continue

            # 从第二个数据包开始
            seq = frame["tcp.seq"]
            nxtseq = frame["tcp.nxtseq"]
            if seq == expectseq :
                # 数据刚好,完全连续,不多不少
                if nxtseq == 0: continue # 表示ack包,无意义
                expectseq = nxtseq
                reg_frame_list.append(frame)
            elif seq > expectseq:
                # 数据有缺失,说明丢包了
                self.reporter.error("previous tcp segment is lost: " + str(frame[TCPFrame.KEY_FRAMENo]))
#                newpacket = self.new_lost_packet(frame, str(expectseq), str(seq))
#                reg_frame_list.append(newpacket)
                reg_frame_list.append(frame)
                expectseq = nxtseq

            elif seq < expectseq:
                # 数据有重叠,数据重传时补传过多数据了
                self.reporter.warning("tcp segment retransmission: " + str(frame[TCPFrame.KEY_FRAMENo]))
                if expectseq < nxtseq:
                    # 当前数据包需要舍弃一部分内容
                    # pre_packet[-(expectseq-seq):-1] == frame[0:expectseq-seq]
                    frame["tcp.seq"] = expectseq
                    frame["data"] = frame["data"][expectseq-nxtseq:]
                    frame["datalen"] = len(frame["data"])
                    expectseq = nxtseq
                    reg_frame_list.append(frame)
                else:
                    # 当前数据包的内容可以完全舍弃
                    # expectseq 保持不变
                    # pre_packet[-(nxtseq-seq):] = frame[:nextseq-seq]
                    pass
        timer.stop()
        return reg_frame_list

用python实现wireshark的follow tcp stream功能,布布扣,bubuko.com

时间: 2024-10-05 05:58:38

用python实现wireshark的follow tcp stream功能的相关文章

Python网络编程02/基于TCP协议的socket简单的通信

目录 Python网络编程02/基于TCP协议的socket简单的通信 1.昨日内容回顾 2.socket 2.1 socket套接字 2.2 基于TCP协议的socket简单通信 Python网络编程02/基于TCP协议的socket简单的通信 1.昨日内容回顾 1.单播:单独联系某一个人 2.广播:给所有人发送消息(群发) 3.比特流:bit就是0101跟水流一样的源源不断的发送01010101 4.以太网协议:将数据进行分组:一组称之为一帧,数据报 head|data head:18字节:

python实现简单的循环购物车小功能

python实现简单的循环购物车小功能 # -*- coding: utf-8 -*- __author__ = 'hujianli' shopping = [ ("iphone6s", 5000), ("book python", 81), ("iwach", 3200), ("电视机", 2200) ] def zero(name): if len(name) == 0: print("\033[31;1m您的输

Python django实现简单的邮件系统发送邮件功能

Python django实现简单的邮件系统发送邮件功能 本文实例讲述了Python django实现简单的邮件系统发送邮件功能. django邮件系统 Django发送邮件官方中文文档 总结如下: 1.首先这份文档看三两遍是不行的,很多东西再看一遍就通顺了.2.send_mail().send_mass_mail()都是对EmailMessage类使用方式的一个轻度封装,所以要关注底层的EmailMessage.3.异常处理防止邮件头注入.4.一定要弄懂Email backends 邮件发送后

Python进阶:自定义对象实现切片功能

Python进阶:自定义对象实现切片功能 切片是 Python 中最迷人最强大最 Amazing 的语言特性(几乎没有之一),在<Python进阶:切片的误区与高级用法>中,我介绍了切片的基础用法.高级用法以及一些使用误区.这些内容都是基于原生的序列类型(如字符串.列表.元组......),那么,我们是否可以定义自己的序列类型并让它支持切片语法呢?更进一步,我们是否可以自定义其它对象(如字典)并让它支持切片呢? 1.魔术方法:__getitem__() 想要使自定义对象支持切片语法并不难,只需

Python基于pyCUDA实现GPU加速并行计算功能入门教程

https://www.jb51.net/article/142212.htm 这篇文章主要介绍了Python基于pyCUDA实现GPU加速并行计算功能,结合实例形式分析了Python使用pyCUDA进行GPU加速并行计算的原理与相关实现操作技巧,需要的朋友可以参考下 目录 pyCUDA特点 pyCUDA的工作流程 调用基本例子 具体内容 本文实例讲述了Python基于pyCUDA实现GPU加速并行计算功能.分享给大家供大家参考,具体如下: Nvidia的CUDA 架构为我们提供了一种便捷的方式

用 Wireshark 图解:TCP 三次握手

摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “snow warn throughout the winter” 一.什么是 Wireshark ?简单地说,Wireshark 是抓包工具.官网说,“Wireshark 是一个网络包分析工具. 网络数据包分析仪将尝试捕获网络数据包并试图尽可能详尽显示该数据包.” 推荐一本书<Wireshark 网络分析就这么简单>,Wireshark 工具下载地址 https://www.wiresha

python下基于sokcet的tcp通信——入门篇

环境 python版本:2.7 IDE:pycharm TCP/UDP协议均为传输层的协议,绝大部分应用程序之间的通信都是使用TCP或UDP,故而在网络通信中及其重要,想详细了解他们之间的差异,可参考http://www.cnblogs.com/vathe/p/6815928.html 1.模拟后台程序,实现浏览器访问 Server端代码 # coding=utf-8 import socket def handle_request(client): buf = client.recv(1024

python 使用raw socket进行TCP SYN扫描

1. TCP SYN扫描 端口扫描常用于用于探测服务器或主机开放端口情况,被计算机管理员用于确认安全策略,同时被攻击者用于识别目标主机上的可运作的网络服务.端口扫描是向一定范围的服务器端口发送对应请求,以此确认可使用的端口.虽然其本身并不是恶意的网络活动,但也是网络攻击者探测目标主机服务,以利用该服务的已知漏洞的重要手段. TCP SYN扫描是端口扫描众多方式中的一种,其他方式包括TCP扫描,UDP扫描,ACK扫描,窗口扫描和FIN扫描等. TCP SYN扫描是另一种TCP扫描.端口扫描工具不使

nginx 1.9 tcp stream 4层负载均衡

nginx在1.9版本以前默认没有tcp的4层代理负载均衡,如果要使用的话得添加相应的模块,但是在1.9版本以后居然内置了这样一个功能,那我就得试试了 下载地址暂时省略 编译的时候需要添加如下参数才能放开4层负载均衡 [[email protected] conf]# ../sbin/nginx -v nginx version: nginx/1.9.0 [[email protected] conf]# ../sbin/nginx -V nginx version: nginx/1.9.0 b