为了弥补pcap文件的缺陷,让抓包文件可以容纳更多的信息,pcapng格式应运而生。关于它的介绍详见《PCAP Next Generation Dump File Format》

当前的wireshark/tshark抓取的包默认都被保存为pcapng格式。

形而上的论述就不多谈了,直接给出一个pcapng数据包文件的例子:

然后我强烈建议,对着《PCAP Next Generation Dump File Format》来把一个实际抓取的pcapng文件里面的每一个字节都对应清除,接下来写一个python脚本,手工构造一个这样的文件,可以用wireshark打开并解析的那种(其实这并不是一件特别难的事情)。这样你就算彻底掌握了这个格式。

还是那个需求,统计一个抓包文件中一个IP地址发出的数据总量,对于pcapng文件,由于其格式已经有了大不同啊大不同,python脚本也就截然不同了,列如下:

#!/usr/bin/python

# Default tcpdump buffer size seems to 2M

import sys

import socket

import struct

filename = sys.argv[0]

filename = sys.argv[1]

#print filename

ipaddr = sys.argv[2]

direction = sys.argv[3]

packed = socket.inet_aton(ipaddr)

ip32 = struct.unpack("!L", packed)[0]

file = open(filename, "rb")

pkthdrlen=16

iphdrlen=20

tcphdrlen=20

stdtcp = 20

total = 0

pos = 0

start_seq = 0

end_seq = 0

# Read file header(type and size)

typedata = file.read(8)

(type, size) = struct.unpack("=LL", typedata)

# Skip header description

skipdata = file.read(size-8)

# Read interface desc block

interfacedata = file.read(8)

(type, size) = struct.unpack("=LL", interfacedata)

# Get linktype from int-desc block

ltdata = file.read(4)

(type, ltsize) = struct.unpack("=HH", ltdata)

if ltsize == 0x71:

pkthdrlen = 16

else:

pkthdrlen = 14

# Skip other of int-desc block

skipdata = file.read(size-8-4)

# Read packet block

pktdata = file.read(8)

(type, size) = struct.unpack("=LL", pktdata)

ipcmp = 0

cnt = 0

while pktdata:

# Skip Interface ID

skipdata = file.read(4)

# Get time and length

# sec:

# microsec:

# iplensave:

# origlen:

data = file.read(16)

(sec, microsec, iplensave, origlen) = struct.unpack("=LLLL", data)

# Read linklayer

linkdata = file.read(pkthdrlen)

# Read IP header

ipdata = file.read(iphdrlen)

(vl, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr) = struct.unpack(">ssHHHssHLL", ipdata)

iphdrlen = ord(vl) & 0x0F

iphdrlen *= 4

# Read TCP standard header

tcpdata = file.read(stdtcp)

(sport, dport, seq, ack_seq, pad1, win, check, urgp) = struct.unpack(">HHLLHHHH", tcpdata)

tcphdrlen = pad1 & 0xF000

tcphdrlen = tcphdrlen >> 12

tcphdrlen = tcphdrlen*4

if direction == 'out':

ipcmp = saddr

else:

ipcmp = daddr

if ipcmp == ip32:

cnt += 1

total += tot_len

total -= iphdrlen + tcphdrlen

if start_seq == 0: # BUG?

start_seq = seq

end_seq = seq

# Skip options and data

skipdata = file.read(size - 8 - 4 - 16 - pkthdrlen - iphdrlen - stdtcp)

# Read next packet

pos += 1

pktdata = file.read(8)

(type, size) = struct.unpack("=LL", pktdata)

if type <> 0x06:

break

# Get interface statistics

if type == 0x05:

skiphdr = file.read(12)

opthdr = file.read(4)

(code, length) = struct.unpack("=HH", opthdr)

while length <> 0:

# 32-bit boundary! BUG?

if code == 5:

opt = file.read(length)

(drops,) = struct.unpack("=Q", opt)

# 不能这么将丢弃的数据包算进去!抓包时就这一个流吗?每个被丢弃的包都是携带数据的吗?...

# 所以,pcapng仅仅统计被丢弃的数据包的数量,不够!怎么才够?不知道!!

# total += drops*1460

elif code == 7:

opt = file.read(length)

(drops,) = struct.unpack("=Q", opt)

# total += drops*1460

else:

skipopt = file.read(length)

opthdr = file.read(4)

(code, length) = struct.unpack("=HH", opthdr)

print pos, 'Actual:'+str(total), 'ideal:'+str(end_seq-start_seq)

执行方式与《pcap文件的python解析实例》针对pcap文件的解析完全一样。

pcapng文件的内容还有很多,这里不再赘述了。本文并没有谈及关于每一个Block里都可以携带的Options信息,那个东西可以再写一篇的。

也许python高手会笑我,为什么我非要用python去解析这么底层的pcap/pcapng文件,用dpkt库不是更好吗?是的,如果本着我文中所提的需求而言,用dpkt固然更好,但是用dpkt的话,你无法知道pcap/pcapng文件格式的全貌,甚至都不可能见一斑!我用python直接解析pcap/pcapng文件,目的有二,首先我要学python,其次我要趁机了解一下pcap/pcapng的细节!我可不想成为女司机那样的。诚然,最高效的方案解决问题最可取,然而,在我这里没有什么问题是要解决的,仅仅是玩玩!

仅仅是玩玩,这也是我折腾了这么久的原因。不过还是很有收获的。

附录

抓包丢弃的问题:dropped by kernel释义与避免

如果你纵观pcap的文件格式(在《pcap文件的python解析实例》中有),你会发现,整个文件只是记录了数据包本身,而丝毫没有涉及那些”由于系统处理能力所限而不得不丢弃的数据包“,而这就造成了统计上的困难。以下仅举一例以说明。

数据发送端为S,数据接收端为C,用我的pcapng-parser.py分析后,数据显示了令人惊讶的结果:

接收端接收的数据总量大于发送端发送的数据总量!!

我们排除数据包被中间可耻的运营商重放这种可能,因为我是在自己的环境下测试!这显而易见是由于发送端抓包抓漏了或者或两边都抓漏了,只是发送端漏的更多而导致!然而我们无法证实这种情况。非常明确的是,在你结束抓包的时候,会打印出”XXX packets dropped by kernel“这种信息,很显然,内核并没有成功抓取所有的包(抓包由PACKET套接字驱动,后者受限于套接字接收缓存!)这可怎么办?

pcapng帮了大忙!

pcapng可以把抓包过程中被丢弃的数据包的数量统计在一个section里最终导出给用户看,我们注意到pcapng文件格式的section类型中有一个”Interface Statistics Block“的可选字段,其中统计了在整个抓包过程中的以下信息:

但是这些够了吗?

有的时候,我可能会一次性抓取所有的数据包保存为一个超级大的pcapng文件,然后利用wireshark/tshark的析取功能去析出那些感兴趣的数据流,此时被析取的数据流的大小已经很小了,但是”Interface Statistics Block“依然保持不变,因为在抓包这个层次上,系统根本没有办法去区分数据流!这可怎么办?!

没有办法!

即便我知道了”在该数据流中丢弃了几个数据包“,我也没有办法计算出丢弃了多少个字节,因为这涉及到了MSS!诚然,你可以使用肉眼,然而你无敌的肉眼只能在wireshark界面里去看那些”previous segment is not captured.“周边的序列号,然后拿这些缺失的字节数去和pcapng保存的统计值去做四则混合运算!!够了!(以上信息,如欲知详情,请点击wireshark的”统计“菜单的第一项!)

我们怎样可以避免抓包丢失呢?或者说即便不可避免,我们怎样可以最小化抓包丢失(这样可以减小我们的估算难度!)呢?幸运的是,tcpdump/tshark可以指定抓取数据包的长度以及PACKET套接字(使用RING/NetMap会更好)缓存的大小,”-s“选项可以限制抓取数据包的大小:

-s Snarf snaplen bytes of data from each packet rather than the

default of 65535 bytes. Packets truncated because of a limited snapshot

are indicated in the output with ``[|proto]'', where proto is the name of

the protocol level at which the truncation has occurred. Note that taking

larger snapshots both increases the amount of time it takes to

process packets and, effectively, decreases the amount of packet buffering.

This may cause packets to be lost. You should limit snaplen to the

smallest number that will capture the protocol information you're

interested in. Setting snaplen to 0 sets it to the default of 65535, for

back-wards compatibility with recent older versions of tcpdump.

限定数据包的大小大多数情况下并不影响我们抓包的目的,毕竟我们大多数情况下抓包都是为了分析内核问题,用户态的问题我们可以通过应用程序的日志来获得,因此我们几乎不用抓取应用层的数据,而应用层以下的所有协议头长度加在一起也不是一个很大的数字,一般而言128字节以内就可以满足需求!所以-s 128这个选项可以让同样大小的缓冲区容纳更多的数据包。除此之外,”-B“选项则可以指定抓包套接字接收缓冲区的大小。两者双管齐下,解决抓包丢弃问题自然不在话下了。

总有人质疑,这是人之本性,我是人,我也会这样,这是亚里士多德的理论,是吗?是的!由于抓包丢失我无法统计出精确的数据包发送的数值,谁能精确统计以及怎么统计?请回答,如果不能回答,请沉默。

我不沉默,因为我有办法统计。我可以对照TCP的序列号,就像wireshark发现抓包丢失那样发现抓包丢失,但是我并不认为这是有用的,这毫无意义!

pcapng的统计补遗

pcapng文件格式已经足够我容纳尽可能多的数据了,然而问题在PACKET套接字!看Linux内核的packet_rcv函数,我们可看到,内核除了数据包本身之外并没有提供更多的信息。

比如,如果我想知道发送某一个TCP数据包的时候,其拥塞窗口是多大?我除了借助于tcpprobe而别无他法!但是,我还是有办法的。

我们在packet_rcv函数里将数据包交给PACKET套接字的时候,不是截断了数据包吗?此时我完全可以将与这个数据包相关的socket的统计信息作为替换加到后面,这些信息包括:当前的拥塞窗口,当前的ssthresh...这样,我们就可以用强大的wireshark/tshark工具来解析这些信息了,而且还可以画出图形呢。

pcap与pcapng之间的转换

说了这么多,其实就统计传输字节数这个需求而言,针对pcap文件和pcapng文件而言完全没有必要用两个脚本!因为pcap和pcapng文件可以互相转换。

最简单的方式,用wireshark打开一个文件,然后”另存为“即可,次好的方式,使用editcap命令也可以完成两者间的转换,只需要”-F“选项,就可以完成你需要的,具体操作,请man!

pcapng文件的python解析实例以及抓包补遗的更多相关文章

  1. 【bb平台刷课记】wireshark结合实例学抓包

    [bb平台刷课记]wireshark结合实例学抓包 背景:本校形势与政策课程课需要在网上观看视频的方式来修得学分,视频网页自带"播放器不可快进+离开窗口自动暂停+看完一集解锁下一集(即不能同 ...

  2. 基于TcpDump和pcap文件分析的Android平台网络抓包程序设计与实现【随便】

    一.考虑使用Tcpdump,将抓到的包保存到cap文件中,然后手动分析.参考资料:1. http://www.cnblogs.com/tt-0411/archive/2012/09/23/269936 ...

  3. Android网络开发实例(基于抓包实现的网络模拟登录,登出和强制登出)

    学习Android有几个月了,最近喜欢上了网络编程,于是想通过Android写一些一个小程序用于连接外网.在这里非常感谢雪夜圣诞的支持,非常感谢,给我打开新的一扇门. 1.声明,本程序只能用于西南大学 ...

  4. 使用jdom进行xml解析,网络抓包

    最近再做一个项目,使用到了jdom进行xml解析,为了方便记忆,现在保存在这里 package bboss; import java.io.FileInputStream; import java.i ...

  5. Android抓包方法(二)之Tcpdump命令+Wireshark

    Android抓包方法(二) 之Tcpdump命令+Wireshark 前言 做前端测试,基本要求会抓包,会分析请求数据包,查看接口是否调用正确,数据返回是否正确,问题产生是定位根本原因等.学会抓包分 ...

  6. nodejs简单抓包工具

    就是简简单单写程序的我为什么需要抓包? 其实在平时写demo的时候需要用到一些图片和文本的资源的,但是需求量比较大,这个时候就想去网站上面直接复制啊,然后图片另存为啊,什么的一系列繁琐的操作. 但是现 ...

  7. Android抓包方法(一)之Fiddler代理

    Android抓包方法(一) 之Fiddler代理 前言: 做前端测试,基本要求会抓包,会分析请求数据包,查看接口是否调用正确,数据返回是否正确,问题产生是定位根本原因等. 不管是之前做HTML5手机 ...

  8. Wireshark和TcpDump抓包分析心得

    Wireshark和 TcpDump抓包分析心得  1. Wireshark与tcpdump介绍 Wireshark是一个网络协议检测工具,支持Windows平台和Unix平台,我一般只在Window ...

  9. Wireshark网络抓包(四)——工具

    一.基本信息统计工具 1)捕获文件属性(Summary) 1. File:了解抓包文件的各种属性,例如抓包文件的名称.路径.文件所含数据包的规模等信息 2. Time:获悉抓包的开始.结束和持续时间 ...

随机推荐

  1. POJ2155【二维树状数组,区间修改,点查询?】【又被输入输出坑】

    这题反反复复,到现在才过. 这道题就是树状数组的逆用,用于修改区间内容,查询点的值. 如果单纯就这个奇偶数来判的话,似乎这个思路比较好理解. 看了一下国家集训队论文(囧),<关于0与1在信息学奥 ...

  2. SPOJ 375. Query on a tree (动态树)

    375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...

  3. Linux- systemd

    systemd被设计用来改进sysvinit的缺点,它和ubuntu的upstart是竞争对手,预计会取代它们.systemd的很多概念来源于苹果的launchd.创始人Lennart是redhat员 ...

  4. linux shell if语句使用方法

    原文地址:http://blog.chinaunix.net/uid-24607609-id-2118151.html 最精简的 if 命令的语法是: if TEST-COMMANDS; then C ...

  5. iPhone应用提交流程:如何将App程序发布到App Store-转

    对于刚加入iOS应用开发行列的开发者来说,终于经过艰苦的Coding后完成了第一个应用后最重要的历史时刻就是将应用程序提交到iTunes App Store.Xcode 4.2开发工具已经把App提交 ...

  6. 《Head First 设计模式》学习笔记——策略模型

    我们全都使用别人设计好的库与框架.我们讨论库与框架.利用他们的API编译成我们的程序.享受运用别人的代码所带来的长处.看看java api它所带来的功能:网络.GUI.IO等.库与框架长久以来,一直扮 ...

  7. spoj Goblin Wars(简单bfs)

    J - Goblin Wars Time Limit:432MS    Memory Limit:1572864KB    64bit IO Format:%lld & %llu Submit ...

  8. 全局安装 Vue cli3 和 继续使用 Vue-cli2.x

    官方链接:https://cli.vuejs.org/zh/guide/installation.html 1.安装Vue cli3 关于旧版本 Vue CLI 的包名称由 vue-cli 改成了 @ ...

  9. QT QCharts QScatterSeries 空心点阵图,鼠标移动到上面显示数值,鼠标移开数值消失

    在最近接到的需求是这样的,画一个折线图,关键点使用空心的圆点标识出来,鼠标移动到关键点上,显示出当前数值:鼠标移走数值消失. 我们遇到这个需求的时候,第一时间就会想到使用 QLineSeries 画折 ...

  10. DotNetBar中dotNetBarManager设置窗口 实现单文档视图界面

    本人想设计一个但文档视图的界面: |--------------------------------------------------------------- |   Ribbon Bar |-- ...