PCAPNG文件格式详解——这一篇就够了!

【参考文献:文献名:《draft-tuexen-opsawg-pcapng-05》,正文名:《PCAP Next Generation (pcapng) Capture File Format》 】

声明:本文提供极尽准确且高效的中文翻译,本文内容主要参考互联网工作小组于2022年7月29日发布的互联网草案,并且该草案已于2023年1月30日到期,故本文仅供学习了解之用。任何将该格式用于非学习研究以外的任何场合而导致的任何问题,本文一概不负责。

1. 介绍

1.1 PCAPNG是什么?

PCAPNG全名Packet CAPture Next Generation,是一种现阶段广泛使用的网络数据包保存格式,其前身为PCAP(libpcap)。

1.2 为什么要约定PCAPNG制度(格式)?

      随着时代的发展,交换数据包追踪的问题愈发严峻,而且行业内还没有针对于此的标准解决方案。目前(PCAPNG拟订时)比较被广泛接纳的一个格式是libpcap,但这种格式有些老旧,并且尤其缺乏对于现行应用的扩展性。

      IETF提出一种新型的用以记录(数据)包追踪的(文件)格式,并且正在努力实现以下目标:

扩展性:随着时间的推移,基于该文件格式的标准添加应当是可行的,并且第三方应当能通过属性扩展丰富文件的信息,另外,需要注意的是,不清楚新扩展内容的工具当然会忽视这些内容。

可移植性:一份捕获的追踪应当包含所有能够独立于生成该捕获的网络、硬件、操作系统(设备)打开的信息。

合并/追加数据:在指定文件末尾添加数据应当是可行的,并且添加后的文件也必须是可读的。

2. 通用文件结构

2.1 文件逻辑架构

      pcapng文件的最小单位是“块”,一种有着通用格式的基础组成单元,就像细胞一样,在此之上是“节”,由节头块率领的一个较为明显辨识的区段,像是人体的组织。

      “块“之间互相指代构建成了一种逻辑层级。下图以树形图的方式展现了当前所定义块构筑的逻辑层级:

图表 1 pcapng文件的逻辑块层级(原文)

字段头部

接口描述

简单数据包

增强数据包

接口统计

名称解析

图表 2 pcapng文件逻辑块层级等价表格

2.2 通用块结构

一个捕获文件的基本单元是“块”,这些块一个接一个地构成了捕获文件,有块共享一种通用格式,如图所示:

块类型(32bits)

块总长(32bits)

块主体

块总长(32bits)

图表 3 基本块结构

  1. 块类型(32位):一个标识块地唯一无符号数。最高有效位为1地值保留本地使用。这些值可以用来对文件格式进行扩展已保存文件的私有数据。当前已规定的类型列表可以在原文献10.1中找到。
  2. 块总长(32位):一个给出所在块总大小的无符号数,8位一组。例如,一个没有块体的块总大小为12字节:4字节的块类型、4字节的初始块总长以及4字节的重复块总长。块总长一定是4的倍数。
  3. 块体:块的内容。
  4. 块总长度:同上,该字段被复制以支持反向的文件导航。

这种在所有块之间共享的结构使得处理文件和跳过不需要或未知的块变得容易。块可以内嵌另一个块(嵌套块)。另外有些块是强制的,即如果这些强制块不存在捕获文件则无效,另一个块则是可选的。

如果需要,通用文件结构也允许定义其它块。不理解自定义块的解析器可以直接跳过它们。

2.2.1 块类型一览

2.2.1.1 【强制块】

以下块是强制的且必须在每个(pcapng)文件中至少出现一次:

Section Header Block(节头块)

该块定义了捕获文件中最为重要的特性。

2.2.1.2 【可选块】

以下块有可能出现在一个文件中:

Interface Description Block(接口描述块)

它定义了用于捕获流量的接口中最为重要的特征,这种块在特定情况下是必须的,在后面的章节中会提到。

Enhanced Packet Block(增强型数据包块)

它包含单个被捕获数据包或其中的一部分,它由原先使用但现已被废弃的数据包块演变而来,如果该块出现在文件中,那么接口描述块需要出现在该块之前。

Simple Packet Block(简单数据包块)

它包含一个被捕获的数据包,或是其中的一部分(只有最少的一部分数据集)。如果该块出现在文件中,那么接口描述块需要出现在该块之前。

Name Resolution Block(名称解析块)

      它定义了从数据包捕获中存在的数字地址到规范名称的映射。

Interface Statistics Block(接口统计块)

      它定义了存储统计数据的方式(例如丢包等),这些数据对于了解捕获生成时的状况有帮助。如果该块出现在文件中,那么接口描述块需要出现在该块之前。

Custom Block(自定义块)

      它以可移植的方式涵盖了供应商特定的数据。

2.2.1.3【废弃块】

以下废弃块不会出现在新生成的文件中(但记录在附录中作以参考)

Packet Block(数据包块)

      它包含了一个被捕获的数据包,或是其中的一部分。该格式已被废弃,并由增强型数据包替代。

2.2.1.4 【实验块】

      以下块很有潜力但笔者(们)认为它们在真正使用前还需要更深层次的讨论。

可替代数据包块

压缩块

加密块

定长块

目录块

流量统计和监控块

事件/安全块

2.3 物理文件布局

      pcapng格式的文件必须以节头块开始。然而同一个捕获文件中不止有一个节头块出现,每个节头块都覆盖[1]其后的数据,直到下一个节头块开始。两个节头块中间就是一个“节(Section)”(或是一个节头块到文件末尾)

      应用无法读取与自身版本号不一致的节,这种情况下应用将跳过整个节的全部内容到下一个节。注意,为了准确跳过该节到下一个节,所有块都必须在开头存在指示类型于长度的字段,也就是说要符合通用块的结构。这也是未来块格式中必须保留的强制需求。

以下是一种最为简单的pcapng文件结构。

SHB v1.0

Data

图表 4 文件结构示例:只有一个节头块的典型布局

      下图是一个含有3个版本号不完全相同的节的pcapng文件,这种文件通常是文件串联的结果。仅支持1.0版本文件格式的应用会跳过中间部分,然后再第三个节头块后重新处理数据包。

SHB v1.0

Data

SHB v1.1

Data

SHB v1.0

Data

图表 5 文件结构示例:三个节头块在一个文件中

      以下是一个类似于“经典libpcap”的文件——含有最小可用的组成。它包含一个节头块(SHB),一个接口描述块(IDB)以及若干个增强型数据包块(EPB)。

SHB

IDB

EPB

EPB

……

图表 6 一个类似于libpcap的pcapng文件

      以下是一个较为复杂的示例文件。作为上面所展示的最小文件的扩展,它包含了由3个接口所捕获的数据包,其中第三个接口的捕获在数据包到达其它接口后开始,并且还包含了一些名称解析块(NRB)和一个接口统计块(ISB)。

SHB

IDB

IDB

EPB

NRB

IDB

EPB

ISB

NRB

EPB

图表 7 文件结构示例:复杂pcapng文件

      最后一个例子充分说明了,相比于经典的libpcap文件格式,块结构使得文件格式非常灵活。

[1] 原文为cover,由于节头块实质上相当于一张表的表头信息,所以可以理解为节头块表示的范围“覆盖”一整个块的逻辑层级到下一个逻辑层级为止。

2.4 选项字段

      在介绍具体的块类型之前,我们先来介绍可以插入到所有块的块体当中的“选项字段”。选项字段可以输入一些对数据有用的信息,但这些内容并非对数据包的处理有所裨益。因此,每个工具都可以选择是读取选项字段的内容(如果有的话),还是跳过其中的一部分或一次性跳过所有。

      可能包含选项字段的块必须构建,以便选项字段的前的块体字节数可以由数据部分确定,这样做方便定位选项字段。对于所有支持选项字段的标准块来说都是如此;而对于支持选项字段的用户自定义块来说,自定义数据必须以这种方式构建。这意味着“块长度”字段可以用来决定块中选项字段的字节数,如果有的话。这个数字[2]可以用来判断块中是否含有选项字段(如果这个值是0,则没有选项字段)。

    选项字段是一个 类型—长度—值[3] 的列表代码段,每个部分都包含一个数值。

类型(16bits)

      一个无符号数,包含了当前TLV记录字段类型的代码段[4]。选项字段中值为1的最高位保留本地使用。因此,不能保证所有捕获文件当中该代码段都是唯一的(其它应用生成的),并且该部分一定不具有可移植性对于需要保证跨平台唯一供应商的特定扩展,务必转而使用用户自定义字段。

长度(16bits)

      一个包含紧随其后的“选项值“无填充字节数的实际字节长度的无符号值。

值(变长)

      所在选项的值,4字节对齐。该字段的实际长度由上一个字段指示。

[2] 块总长的值

[3] 原文为TLV,即Typr-Length-Value

[5]给定的选项可能具有固定长度,在这种情况下,所有实例的选项都具有等同于指定长度的长度;给定的选项也可能具有可变长度,在这种情况下,选项具有最小值,并且选项长度长度不得小于指定的最小值。定长选项的长度,可变长度选项的最小长度,都应在选项的描述中指定。如果未指定变长选项的最小值,那么0长度的选项将是合法的读取这些文件的软件应当报告这些具有非法长度的选项;当软件检测到非法长度的选项时,可以停止处理其所在文件。同时,生成这些文件[6]的软件不得生成具有非法长度的文件。

      如果一个选项的值是字符串,那么该值并非一定要有0终止符。读取这些文件的软件不得假定字符串都是0终止符结尾的,并且必须将0值的字节视为一个字符串终止符。

      一些选项可能(在一个块当中)重复多次;例如,一个块可以含有多个(重复的)注解,接口描述块可以在被赋了多个Ipv4或是Ipv6地址的情况下指定多个Ipv4或是Ipv6地址。而另外一些选项在一个块当中则最多出现一次。

      选项列表以一个使用”End of Option”的特殊码终结。生成pcapng文件的代码必须以opt_endofopt选项作为一个选项列表的结束。读取PCAP文件的代码不得假定任何一个选项都以opt_endofopt选项结尾;这些代码务必检查块的末尾,并且应当将那些选项列表中没有opt_endofopt结尾的块视作它们的选项列表有opt_endofopt结尾。

选项字段的格式如下:

选项代码

选项字段总长度

选项的值

其它选项代码

选项代码段

选项字段总长度

图表 8 选项字段格式

以下是可以出现在选项字段中的代码

名称

代码

长度

允许重复

opt_endofopt

0

0

No

opt_comment

1

Variable

Yes

opt_custom

2988/2989/19372/19373

Variable

Yes

图表 9 常用选项

opt_endofopt

      opt_endofopt适用于分隔可选字段的末尾。此选项不得在给定的选项列表中重复。

opt_comment

      opt_comment选项是一个包含了与当前块有关的、人类可读注解文本的、UTF-8格式编码的字符串。行分隔符应当为回车加换行(’\r\n’);任意一种出现则应当被认为是一个换行符“,该字符串并非以0结尾。

例:“该数据包是我们所有问题的开始”,“17-23号包显示了一个伪造的TCP转发(换行)这在bugzilla[7]1486号入口处有报告信息。(换行)这将会在未来修复“

opt_custom

      该选项将在3.2中详细描述。

[4] 这句话就是说,“类型”就是选项字段内指定了“类型的“代码段。以普遍理性而言,这是废话。

[5] 这里开始直到介绍选项字段的格式之前都是标准规范性的论述。

[6] 指PCAPNG文件。

[7] 通用软件缺陷追踪工具

2.5 自定义选项

      自定义选项用于可移植的、与其自身所在块相关的“供应商特定数据“。自定义选项可用于任何一个可以持有选项的块,也可以在一个块中重复任意次,并且可以出现在除结束选项字段外的其它类型选项的任意位置(前面或者后面)。同一pcapng文件中可以使用不同类型代码或不同私人企业编号的不同自定义选项。查询原文章节5以获取更多信息。

选项代码

选项字段总长度

私人企业编号(选项值)

自定义数据(变长,4字节对齐)

图表 10 自定义选项格式

(1)选项代码

2988

      该选项代码用于标识一个数据区存放有一个UTF-8格式字符串的自定义选项。该字符串不是以0结尾的。如果存在多个由一个应用生成的pcapng文件,那么该自定义选项可以安全拷贝至另一份新文件当中,否则应当使用19372作为替代。更多内容详见原文5.2。

2989

      该选项代码用于标识一个数据区存放有二进制数的自定义选项如果存在多个由一个应用生成的pcapng文件,那么该自定义选项可以安全拷贝至另一份新文件当中,否则应当使用19372作为替代。更多内容详见原文5.2。

19372

      该选项代码用于标识一个数据区存放有UTF-8格式字符串的自定义选项。该字符串不是以0结尾的。如果存在多个由一个应用生成的pcapng文件,那么该自定义选项不应该拷贝至另一份新文件当中。更多内容详见原文5.2。

19373

      该选项代码用于标识一个数据区存放有二进制数的自定义选项。如果存在多个由一个应用生成的pcapng文件,那么该自定义选项不应该拷贝至另一份新文件当中。更多内容详见原文5.2。

(2)选项总长度

      同通用选项字段的总长度。

(3)私人企业编号

      一个由IANA[8]分配的用于标识所在自定义选项声明组织或机构的PEN[9]。更多内容请查询原文5.1。PEN必须使用与他所在节头块相同的字节序。

[8] 互联网地址编码分配机构(Internet Assigned Numbers Authority)

[9] 私人企业编码(Private Enterprise Number)

2.6 数据格式

2.6.1 字节序

      每个节中的数据将会按照捕获(数据包)设备的字节序存储。这适用于所有以数字保存的字段和超过两个字节的区块。

      将每个节以生成主机的本地格式保存的方法更有效,因为这种方法避免了自身在读写数据时的来回转换,在生成/处理捕获文件时这是最常见的情况。

      另外,字节序在“节头块“中也有提及,因为一个文件可以拥有多个节头块,所以一个文件也可以包含多种字节序。

2.6.2 对齐

      本规范中的所有字段对于16位和32位的数据均采用科学的对齐方式。这使得在使用内存映射文件技术时,可以更快速地读写文件的内容。

      字节对齐均以0填充。

      64位数并不会对齐到64位边界。这是因为文件只会自然对齐到32位边界。在读写文件时务必特别小心。(注意有些64位数在写入文件的设备自身的字节序中表现位64位整型,而其它数则表示为2个32位的数值,一个含有该值的高32位,一个则含有该值的低32位。这两个数也按照生成文件的主机字节序进行对齐。注意,无论哪种文件格式都不能保证64位对齐。

3. 块定义

3.1 节头块

      节头块(SHB)是强制的。它标识了捕获文件中一个节的起始点。节头块不含有数据但它标识了一个逻辑上紧密相连的块列表。下图为节头块的格式:

块类型(0x 0A 0D 0D 0A

块总长

字节序魔法数

主版本号

次版本号

节长度

选项(变长)

块总长

块类型(32bits)

      节头块的块类型是4字符”\n\r\r\n”的整形表示(即0x0A0D0D0A),采用该值有两个原因:

1. 该数字用于检测一个文件在从一台机器发送到另一台机器的过程中是否由于FTP/HTTP产生了不正确的ASCII转换。这种情况下,该字段的值将区别于标准值(0x0A0D0D0A)。且阅读器可由此识别出一个可能损坏的文件。

2. 该值是回文的,因此不论该节的字节序如何,阅读器总能识别出节头块。具体的字节序由字节序魔法数指定,其在块类型后面8个字节的地方。

块总长(32bits)

      同通用块结构。

字节序魔法数(32bits)

      一个值为16进制0x1A2B3C4D的无符号数字。该数字用以区分其所在节存储的设备的大小端,并启发式地标识pcapng文件。

主版本号(16Bits)

      一个指定所在节主版本号的无符号数。当前文件格式的主版本号为1。

次版本号(16bits)

      一个指定所在节次版本号的无符号数。当前文件格式的主版本号为0。

节长度(64bits)

      一个带符号的值,以 字节数指定下一个 节的长度,不包括节头块本身。该字段可用于跳过该节,以便在大文件中更快地导航。如果节长度为-1

 (0 xFFFFFFFFFFFFFFFF),这意味着没有指定该节的大小,跳过该节的唯一方法是解析它所包含的块。请注意,如果这个字段是有效的(即不是负的),它的值总是 4 的倍数,因为所有的块都对齐并填充到 32 位(4字节)的边界。另外,在访问该字段时要特别注意:由于文件中所有块的对齐方式都是4字节对齐,因此该字段不能保证与 64 位边界对齐。这在 64 位处理器上可能是一个问题。

      [10]PCAPNG 文件的编写者禁止编写主要版本不是 1 或次要版本不是0 的节头块。如果他们这样做,他们将写一个文件,许多 pcapng 文件的读取器,如使用 libpcap 读取 pcapng 文件的程序(包括但不限于tcpdump), Wireshark,以及可能的其他程序无法读取他们的文件。

[10] 以下是标准规范的论述。

        一些 pcapng 文件编写器使用了 2 的小版本,但文件格式并没有不兼容地改变(增加了新的块类型);pcapng 文件的读取器 MUST 将次要版本为 2 视为等同于次要版本为 0(并且,如果他们同时根据读取一个或多个 pcapng 文件的结果编写 pcapng 文件,他们绝对不能,按照先前的论述,编写次要版本为 2 的 节头块,即使他们读取次要版本为 2 的节头块)。在写 pcapng 文件的一个章节时,使用 0 以外的次要版本号会产生一个大多数现有软件都无法读取的章节;其中一些软件的未来版本将能够读取 1.2 版本的章节,但未更新到最新版本的该软件的旧副本仍将无法读取它们。

        只有在为文件格式的后期主要版本创建了该规范的新版本时,才会更改主要版本。只有当格式发生变化,读取新格式的代码无法读取旧格式(即读取两种格式的代码必须检查版本号并为两种格式使用不同的代码路径),并且读取旧格式的代码无法读取新格式时,才会创建这样的版本。对现有块或现有选项的格式进行不兼容的更改将是这样的更改; 添加新块或新选项则不属于此类更改。这种不兼容的变化的一个例子是在节报头块中增加一个额外的字段,在次要版本字段之后,在 snapen 字段之前;期望新的节头块格式的软件不能正确读取旧的节头块格式,期望旧的节头块格式的软件不能正确读取新的节头块格式。(请注意,对节头块的更改必须使块类型,块总长度,字节序魔法数,主要版本和次要版本字段与字节序开头的偏移量相同并且具有相同的长度,必须保持块类型的值相同,必须保持字节顺序魔术的两个可能值相同,这取决于块的字节顺序,以便 SHB 的其余部分可以正确解释。只有在为该文件格式的后续次要版本创建了该规范的新版本时,才会更改次要版本。只有当格式发生变化时,读取新格式的代码可以在不检查版本号的情况下读取旧格式,但读取旧格式的代码不能读取新格式的所有文件时,才会创建这样的版本。对现有块或现有选项的格式进行向后兼容的更改将是这样的更改;添加新块或新选项则不会是这样的更改。这种向后兼容但不向前兼容的更改的一个示例是更改接口描述块(见下文),以使用当前保留字段来指示选项之前是否存在其他字段,零值表示不存在此类字段 例如,添加新的块类型或选项不需要更改主要版本或次要版本,因为不清楚块类型或选项的代码应该跳过它;只有当跳过一个块或选项不起作用时,才应该更改次要版本号。

选项

      可选的,选项列表可以出现在该字段。除原文3.5中定义的选项值外,下列选项也可以用于当前块中。

名称

代码

长度

是否允许重复

shb_hardware

2

Variable

No

shb_os

3

Variable

No

shb_userappl

4

Variable

No

图表 11 节头块选项

shb_hardware

该选项是一个含有创建其所在节硬件信息的UTF-8格式的字符串。该字符串不是以0结尾的。

示例:“x86 Personal Computer”, “Sun Sparc Workstation”

shb_os

      该选项是一个含有创建其所在节操作系统信息的UTF-8格式的字符串。该字符串不是以0结尾的。

示例:“Windows XP SP2”, “openSUSE 10.2”

shb_userappl

      该选项是一个含有创建其所在节应用程序信息的UTF-8格式的字符串。该字符串不是以0结尾的。

示例:“dumpcap V0.99.7”

【开放议题:重写捕获文件的程序会(应当)改变原硬件/操作系统/应用程序的信息吗?】

3.2 接口描述块

      接口描述块用于存放捕获了数据包的接口的信息。

      读写捕获文件的工具会为每一个接口描述块附上一个递增的32位无符号数(从0开始),这个数被称作接口ID该数字在单节内是唯一的,它标识接口描述块指代的是哪个接口;又由于这个数在单节内是唯一的,所以不同节内的接口ID可以重复。其它块可以通过该唯一标识符引用(指代)对应接口,例如增强型数据包块(EPB)和接口统计块(ISB)。

      每一个其它块引用到的接口都必须有其对应的接口描述块。增强型数据包块和简单数据包块都包含有一个指向特定接口的接口ID,且简单数据包块隐式引用了一个接口ID为0的接口。如果一个文件没有任何使用了接口ID的块,那么该文件不需要接口描述块。[11]

      接口描述块只有在它所属的节内才有效。

块类型(0x0000 0001)

块总长

连接类型

保留

抓取长度

选项

块总长

图表 12 接口描述块格式

 [11] 即,只有当接口ID被EPB或ISB等其它块使用时,IDB才有必要创建。IDB本身就是用用来解释接口ID所表示接口的块,从这种意义上讲,它类似于变量声明或是函数声明。

      通用内容不再赘述。

连接类型(16bits)

      一个定义该接口链路层类型的无符号数。标准的链路层类型的代码段在该字段中可用。

保留

      目前未使用——pcapng文件编写器必须以0填充该字段,阅读器则必须无视该字段。

抓取长度(32bits)

      一个指示每个数据包最大抓取字节数的无符号数。数据包中超过该值所指示大小的部分将不会存储在文件中。该值取0代表不限制抓取长度。

选项(变长)

除通用选项外,以下选项在该块中也是可用的。

名称

代码

长度

允许重复

if_name

2

Variable

No

if_description

3

Variable

No

if_IPv4addr

4

8

Yes

if_IPv6addr

5

17

Yes

if_MACaddr

6

6

No

if_EUIaddr

7

8

No

if_speed

8

8

No

if_tsresol

9

1

No

if_tzone

10

4

No

if_filter

11

Variable, min 1

No

if_os

12

Variable

No

if_fcslen

13

1

No

if_tsoffset

14

8

No

if_hardware

15

Variable

No

if_txspeed

16

8

No

if_rxspeed

17

8

No

图表 13 接口描述块选项字段

if_name

      该选项是一个含有用来捕获数据的设备名字的UTF-8格式的字符串,该字符串不以0结尾。

例:”eth0”, “\Device\NPF_{AD1CE675-96D0-47C5-ADD0-2504B9126B68}”

if_description

      该选项是一个含有用来捕获数据的设备描述的UTF-8格式的字符串,该字符串不以0结尾。

例:“Wi-Fi”, “Local Area Connection” ,”Wireless Network Connection”

if_IPv4addr

该选项是接口的 IPv4 网络地址和对应的 netmask。前 4 个字节是 IP地址,后4个字节是子网掩码。当为接口分配多个 IPv4 地址时,该选项可以在同一个接口描述块内重复多次。 请注意,IP 地址和netma sk 都被视为四个字节,每个字节对应一个地址或掩码;它们不是 32 位数字,因此 SHB 的字节序序不影响该字段的值。

例:“192 168 1 1 255 255 255 0“

if_IPv6addr:

      该选项为IPv6 网络地址和其对应的接口前缀长度。前16个字节是IP地址,后16个字节是前缀长度。当多个 IPv6 地址被分配给接口时,此选项可以在同 一接口描述块内重复多次。

示例: 2001:0db8:85a3:08d3:1319:8a2e:0370:7344/64,十六进制表示为

'20 01 0db8 85a3 08d3 1319 8a2e 0370 7344 40'

if_MACaddr:

      该选项是接口的硬件MAC地址(48位)。

例:“00 01 02 03 04 05“

if_EUIaddr

      该选项是接口的硬件EUI地址

例:“02 34 56 FF FE 78 9A BC”

if_speed

      该选项是一个表示接口速率的64位无符号数,以秒为单位。

例:用于表示100Mbps的64位十进制数是100000000

if_tsresol

      该选项用于标识时间戳的解析。如果最高位是0,剩余位表示时间戳为10的负几次方(比如,6表示微秒,那么时间戳就是从1970-01-01 00:00:00UTC开始的微秒数);如果最高有效位是1,则剩余的位表示时间戳为 2 的负几次方(例如 10 表示 1/1024 秒)。如果不存在此选项,则时间戳假设为 10^-6 (即时间戳具有与标准'libpcap'时间戳相同的值)。

if_tzone

      if_tzone选项标识支持GMT时区

例:【待做:给出一个很好的示例。】

if_filter

      该选项标识过滤器(例如:“仅捕获 TCP 流量”)用于捕获流量。Option Data 的第一个字节保留了所使用的过滤器的代码(例如,如果这是 libpcap 字符串,或 BPF 字节码,等等)。有关此格式的更多细节将在附录 XXX (TODO)中提 供。TODO:不同的字段使用不同的选项更好吗?例如 if_filter_pcap, if_filter_bpf,…)

示例:'00'"tcp 端口 23 和主机 192.0.2.5"。

if_os

      if_os 选项是一个 UTF-8 字符串,包含安装该接口的机器的操作系统名称。这可能不同于节头块中包含的相同类型的信息[12],因为捕获可以在远程机器上完成。该字符串不是以零结尾的。

示例:"Windows XP SP2", "openS US E 10.2"

[12] 指shb_os选项字段。

if_fcslen

      if_fcslen 选项是一个 8 位无符号整数值,用于指定该接口的帧

检查序列的长度(以位为单位)。对于 FCS 长度可以随时间变化的链路层,增强包块 epb_flags 选项可以在每个增强包块中使用.

例:“4”

if_tsoffset

      if_tsoffset 选项是一个表示添加在每个数据包的时间戳后以得到其绝对时间戳的偏移量(按秒) 64 位带符号整数值。如果缺少该选项,则存储在数据包中的时间戳必须被认为是绝对时间戳。偏移量的时区可以用 if_tzone 选项指定。TODO:分数秒偏移的 if_tsoffset_low 不会对高度同步的捕获系统有用吗?

例:‘1234’.

if_hardware

      if_hardware 选项是一个包含接口硬件的描述的UTF-8 格式的字符串。 该字符串不是以零结尾的。

示例:“Broadcom NetXtrem e”、“Intel(R ) PRO/1000 MT Network Connection”

if_txspeed

      if_txrxspeed 选项是一个表示接口传输速度的64 位无符号值,以比特每秒为单位。

示例:表示 1024Kbps 的 64 位十进制数 1024000

if_rxspeed

      if_rxspee d 选项是一个表示接口接收速度的64 位无符号值,单位为比特每秒。

示例:表示 8192Kbps 的 64 位十进制数 8192000。

如果接口的发送速率和接收速率相同,则必须使用 if_speed 选项,而绝对不能使用 if_txspeed 和 if_rxspeed 选项;

如果传输速度未知,则绝对不能使用 if_speed和 if_txspeed 选项;

如果接收速度未知,则绝对不能使用 if_speed和 if_rxspeed 选项。

3.3 增强型数据包块

      增强型数据包块(EPB)专用于存储网络中的数据包。该块不是必须的,因为数据包除了可以由该块存储,还可以由简单数据包块存储(SPB)。这样做可以提升文件生成的速度;另外也有可能一个文件中根本就没有数据包,那么EPB和SPB则都没有必要。

      EPB是老旧的、已被废弃的Packet Block的升级版,相比于PB:

(1)EPB使用32位整型数存储接口的标识符。当捕获从大量接口中获取数据时这是必须的。

(2)EPB会将数据包传输时的丢包数存储在块自身的选项中,而不是表头中。

EPB的格式如下图所示:

块类型(0x0000 0006)

块总长

接口ID

时间戳(高)

时间戳(低)

数据包捕获长度

数据包原始长度

数据包数据

选项

块总长

图表 14 增强型数据包块格式

接口ID(32bits)

      一个标识接受或发送该数据包的那个接口的符号数;正确的接口是那个由该字段相同值标识的那个接口描述块(所在文件中同一节的)所表示的接口。接口ID必须是合法的,也就是说其对应的解耦描述块(IDB)必须存在。

高位时间戳和低位时间戳(32bits for each)

      这个时间戳是一个表示从1970-01-01 00:00:00 UTC开始所经过时间单元数的64位无符号整型数。该时间单元由该数据包中接口ID指代的接口描述块 中的if_tsresol选项字段表示。请注意,不同于“libpcap”文件格式的时间戳,增强型数据包的时间戳并不是以两个32位的从基准时间经过的秒数和微秒数对应的数值来表示的,而是以一个64位数分割得来的两个32位数表示的。

数据包捕获长度(32bits)

      一个表示从数据包中捕获字节数的无符号数。它是自身、EPB中数据包原始长度、IDB中抓取长度三者中的最小值。该字段的值不包括数据包数据区的填充字节。

数据包原始长度(32bits)

      一个表示网络中传输的数据包实际长度的无符号数。如果数据包已被捕获进程本身截断,那么这个数可以与数据包捕获长度不同。

数据包数据(变长)

      该字段存放的是包含链路层表头在内的网络数据。该字段的大小相当于数据包捕获大小加上填充的字节大小。链路层表头的格式依赖于IDB中指定的连接类型字段,并且由连接类型中格式的条目指定。

选项

      除了通用的选项字段,以下选项在本块中也是合法的。

名称

代码

长度

允许重复

epb_flags

2

4

No

epb_hash

3

Variable[13]

Yes

epb_dropcount

4

8

No

epb_packetid

5

8

No

epb_queue

6

4

No

epb_verdict

7

Variable[14]

Yes

图表 15 增强型数据包块选项

[13] 取决于最小哈希类型

[14] 取决于最小判决类型 

epb_flags

      epb_fla gs 选项是一个包含链路层信息的 32 位有符号数字。允许的标

志的完整规范详见原文第 4.3.1 节。

例: ‘0’

epb_hash

      epb_hash 选项包含数据包的哈希值。第一个字节指定哈希算法,而接下来的字节包含实际哈希值,其大小取决于哈希算法,也就是说取决于第一个字节的值。哈希算法可以是: 2s complement(算法 octet = 0, size=XXX)、XOR(算法 octet = 1, size=XXX)、CRC32(算法 octet = 2, size= 4)、MD-5(算法 octet = 3, size= 16)、SHA-1(算法 octet = 4, size= 20)、Toe plitz(算法 octet = 5, size= 4)。哈希只覆盖数据包,不包括捕获驱动程序添加的报头: 这就提供了在网卡内部计算它的可能性。哈希可以更容易地比较合并不同的捕获文件,并在数据采集系统和捕获库之间进行可靠的数据传输。

例: '02 EC 1D 87 97', '03 45 6E C2 17 7C 10 1E 3C 2E 99 6E C2 9A 3D 50 8E'

epb_dropcount

      epb_dropcount 选项是一个 64 位无符号整数值,指定该包与同一接口的前一个包之间的丢包数(由接口和操作系统), 或者对于接口的第一个包,该包与捕获过程开始之间的丢包数

例: ‘0’

epb_packetid

      epb_packetid 选项是一个唯一标识数据包的64 位无符号整数。如果相同的数据包被多个接口看到,并且捕获应用程序有办法将它们关联起来,则必须使用相同的 epb_packetid 值。一个例子是一个路由器,它在两个方向上捕获所有接口上的数据包。当数据包到达接口 a 时,创建一个 EPB 条目,TTL 值递减, 并且在它到达接口 B 之前,在跟踪文件中创建另一个 EPB 条目。 在这种情况下,捕获文件中有两个数据包,它们不相同,但可以使用 epb_packetid 将它们关联起来。

例: ‘0’

epb_queue

      epb_queue 选项是一个 32 位无符号整数,用于标识在接口的哪个

队列上接收到特定的数据包

例: ‘0’

epb_verdict

      epb_verdict 选项存储数据包的判决。该判决指示在处理数据包之后将对其进行什么处理。例如,防火墙可以丢弃数据包。这个结论可以由不同的组件来决定,比如硬件、Linux 的 eBPF TC 或 XDP 框架等等。第一个字节指定判决类型,而接下来的字节包含实际的判决数据,其大小取决于判决类型,因此取决于第一个字节中的值。判定类型可以是:Hardware (type octet = 0, size = variable), Linux_eBPF_TC (type octet = 1, size = 8(64 位无符号整数),value = TC_ACT_*(在 Linux pc k_cls.hinclude 中定义),Linux_eBPF_XDP (type octet = 2, size = 8(64 位无符号整数), value =在 Linux pbf.hinclude 中定义的 xdp_action) 。

例如: '02 000 000 000 000 000 000 000 000 000 000 000 02'用于 Linux_eBPF_XDP,判决为 XDP_PASS

3.4 简单数据包块

      简单数据包块(SPB)是一个用于装载网络中数据包的轻型容器。它的形式是可变的。

      简单数据包块类似于增强型数据包块(EPB),但它更小、处理起来更简单、且只包含最少的信息集。当优先考虑性能和空间占用时,该块优于标准的增强包块。捕获文件可以同时包含增强型数据包块和简单数据包块:举个例子,当硬件资源吃紧时,捕获工具可以将增强型数据包块转换为简单数据包块。

      简单数据包块并不包含接口ID字段。因此,因此必须假定所有简单数据包块都在先前描述的第一个接口描述块(IDB)所表示的接口中捕获生成。

块类型(0x0000 0003)

块总长

数据包原始长度

数据包数据

块总长

图表 16 简单数据包块格式

数据包原始长度(32bits)

      一个表示网络中传输的数据包实际长度的无符号数。如果数据包已被捕获进程本身截断,那么该值可以和数据包捕获长度不同。这种情况下IDB的抓取长度字段将比该值小,并且抓取长度必须用于限定数据包数据字段的长度。

数据包数据

      该字段存放包括链路层报头在内的网络数据。该字段的长度来源于块报头中的块总长度字段,它是 SnapLen(IDB)和 原始数据包长度(该块中)之间的最小值。链路层表头的数据格式取决于IDB中指定的 LinkType 字段(参见 4.2 节),并且由连接类型中格式的条目指定。

简单包块也不包含时间戳,因为这通常是 PC 上最耗费资源的操作之一。 此外,还有一些应用程序不需要它; 例如,入侵检测系统感兴趣的是数据包,而不是它们的时间戳。

简单包块不能出现在具有多个接口的节中,因为不可能引用正确的接口(它不包含任何接口 ID 字段)

简单包块在磁盘空间方面是非常有效的:一个长度为 100 字节的快照只需要 16 字节的开销,这相当于超过86%的效率。

3.5 名称解析块

      名称解析块(NRB)用于建立数字地址(捕获数据包中的)与其对应标准名称的关系,该块是可选的。将文字名称保存在文件中可以防止以后执行名称解析的需要,因为名称和地址之间的关联可能与捕获时使用的关联不同。此外,NRB 避免了每次打开跟踪捕获时发出大量 DNS 请求的需要,并且还在使用未连接到网络的机器读取捕获时提供名称解析。

名称解析块通常放在文件的开头,但不能假设它的位置。多个 NRB 可以存在于一个 pcapng 文件中,这可能是由于内存限制,也可能是因为文件处理工具(如网络分析器)执行了额外的名称解析。

名称解析块不需要包含任何记录,除了 nrb_record_end 记录必须是最后 一条记录。NRB 记录中的地址和名称可以重复多次;即,相同的 IP 地址可以解析为多个名称,相同的名称可以解析为多个 IP 地址,甚至相同的地址-名称对可以在相同的 NRB 或跨 NRB 中出现多次。

块类型(0x0000 0004)

块总长

记录类型(T)

记录值长度(L)

记录值(V)

其它记录

记录类型=nrb_record_end

记录值长度=0

选项

块总长

图表 17 名称解析块格式

名称解析记录(TLV)

      0个或多个TLV,每一个都包含网络地址和名称之间的关联。最后一个记录后面必须是nrb_record_end,就算是NRB中没有任何记录,nrb_record_end也必须存在。以下是一些可以出现的记录:

名称

代码

大小

nrb_record_end

0x0000

0

nrb_record_ipv4

0x0001

Variable

nrb_record_ipv6

0x0002

Variable

图表 18 名称解析块记录

nrb_record_end

      nrb_record_end 限定了名称解析记录的边界。该记录用于确定

名称解析记录列表何时结束以及某些选项(如果有的话)何时开始。

nrb_record_ipv4

      nrb_record_ipv 4 记录指定一个 IPv4 地址(包含在前 4 个字节中), 后面是一个或多个以零结尾的 UTF-8 字符串,其中包含该地址的DNS 项。因此,此记录类型的最小有效记录长度为6: 4 个字节存放IP,1 个字符,以及一个零值的字节结束符。

请注意,IP 地址被视为四个字节,每个字节对应一个 IP 地址;它不是一个 32 位的字,因此 SHB 的端序不影响该字段的值

例: '127 0 0 1'"localhost"。

【开放式问题:空字符串(即,只是一个零值的字节)有效吗?】

nrb_record_ipv6

      nrb_rec ord_ipv6 记录指定一个 IPv6 地址(包含在前 16 个字节中), 后面是一个或多个以零结尾的字符串,其中包含该地址的 DNS 项。因此,此记录类型的最小有效记录长度为 18: 16 用于 IP 字节组,1 个字符,以及一个零值字节结束符。

示例:'20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 34 56 78'"somehost"

【开放式问题:空字符串(即,只是一个零值的字节)是否有效?】

前面指定的记录类型以外的类型务必被忽略并跳过。将来可能会定义更多的记录类型,并且一定破坏向后兼容性。

每个记录值与 32 位边界对齐并填充。对应的记录值长度反映了记录值的实际长度;它不包括记录类型字段、记录值长度字段、记录值的任何填充或记录值之后的任何内容的长度。对于具有名称字符串的记录类型,记录长度包含结束该字符串的零值字节。记录长度为 0是有效的,除非另有说明。

选项

      以下为该块中的特殊选项。

名称

代码

长度

允许重复

ns_dnsname

2

Variable

No

ns_dnsIP4addr

3

4

No

ns_dnsIP6addr

4

16

No

图表 19 名称解析块的选项

ns_dnsname

      ns_dnsname 选项是一个包含用于执行名称解析的机器(DNS 服务器)的名称的UTF-8 字符串,该字符串不以零结尾。

例: “our_nameserver”。

ns_dnsIP4addr

      “ns_dnsIP4a ddr”选项指定 DNS 服务器的 IPv4 地址。请注意,IP 地址被视为四个字节,每个字节对应一个 IP 地址; 它不是一个 32 位的字,因此 SHB 的端序不影响该字段的值。

例:  '192 168 0 1'

ns_dnsIP6addr:

ns_dnsIP6addr 选项指定 DNS 服务器的 IPv6 地址

例: '20 01 0d b8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12

34 56 78'

3.6 接口统计块

接口统计块(ISB)包含指定接口的捕获统计信息,它是可选的。统计信息通过接口ID指代当前所在节中的那个接口。接口统计块通常位于文件的末尾,但不应假定它在固定的位置。一个接口可以有多个接口统计块。

块类型(0x0000 0005)

块总长

接口ID

高位时间戳

低位时间戳

选项

块总长

图表 20 接口统计块格式

时间戳

此统计信息的时间。时间戳的格式与EPB中定义的格式相同;时间单元则由IDB中”if_tsresol”选项指定。

选项

      所有统计字段均定义为“选项“,以适配没有完整统计集的系统。

名称

代码

长度

允许重复

isb_starttime

2

8

No

isb_endtime

3

8

No

isb_ifrecv

4

8

No

isb_ifdrop

5

8

No

isb_filteraccept

6

8

No

isb_osdrop

7

8

No

isb_userdeliv

8

8

No

图表 21 接口统计块选项

isb_starttime

      isb_starttime 选项指定捕获开始的时间;时间将存储在两个大小均为4字节的块中。时间戳的格式与增强包块(章节 4.3)中定义的格式相同;单位时间的长度由该数据包引用的接口描述块的' if_tsressol '选项(见图 10)指定 。

例如: '96 c3 04 00 73 89 6a 65',小端解码为 2012-06-29 06:17:00.834163 UTC

isb_endtime

      isb_endtime 选项指定捕获结束的时间;时间将存储在两个块中, 每个块四个八位字节。时间戳的格式与增强包块(章节 4.3)中定义的格式相同;单位时间的长度由该数据包引用的接口描述块的' if_tsressol '选项(见图 10)指定。

例如: '97 c3 04 00 aa 47 ca 64',小端解码为 2012-06-29 07:28:25.298858 UTC

isb_ifrecv

      isb_ifrecv 选项是一个指定了从捕获开始从物理接口接收到的数据包数的 64 位无符号整数

例: 十进制数 100。

isb_ifdrop

      isb_ifdrop 选项指定从捕获开始由于资源问题而被接口丢弃的64 位无符号整数。

例子: ’0’

isb_filteraccept

      isb_filteraccept 选项指定过滤器从捕获开始接受的 64 位无符号整数。

例:十进制’100’

isb_osdrop

      isb_osdrop 选项指定操作系统从捕获开始开始丢弃的 64 位无符号整数。

例子: ’0’

isb_userdeliv

      isb_u srdeliv 选项指定从捕获开始开始交付给用户的 64 位无符号整数。此字段中包含的值可以与值'isb_ filteraccep t - isb_o sdrop'不同,因为当捕获结束时,某些数据包可能仍在操作系统缓冲区中。

所有引用包计数器的字段都是64位,用当前部分的字节序表示。在访问这些字段时必须特别小心:因为所有的块都是按 32 位边界对齐的,所以这些字段不能保证按 64 位边界对齐。

3.7 解密块

解密块(DSB)存储解密捕获文件中数据包的机密信息。这些机密的格式由机密类型字段规定。

      同一个pcapng文件当中可以出现多个解密块,但它们应该在需要用到这些机密得到数据包块之前。工具可以将解密行为限制为仅数据包之前出现的机密。

块类型(0x0000 000A)

块总长

机密类型

机密长度

机密数据

选项

块总长

图表 22 解密块的格式

机密类型(32bits)

      一个用于描述后续机密字段格式的无符号标识符。以下是机密类型的列表:

0x544c534b:

TLS 密钥日志。该格式在 NSS 密钥日志格式[15]中进行了描述。每行必须以回车和换行('\r\n')或换行('\n')适当结束。工具必须能够处理两种行结尾方式。

0x57474b4c

      WireGuard 密钥日志。每行由密钥类型、等号('=')和 base64 编码的 32 字节密钥组成,密钥前后有可选的空格。密钥类型是其中之一LOCAL_STATIC_PRIVATE_KEY, REMOTE_STATIC_PUBLIC_KEY, LOCAL_EPHEMERAL_PRIVATE_KEY 或PRESHARED_KEY。这与WireGuard工程文件之一extract-handshakes.sh的输出相匹配,它是 WireGuard 项目的一部分。 PRESHARED_KEY 行链接到与前面的 LOCAL_EPHEMERAL_PRIVATE_KEY 行匹配的会话。每行 MUST以 回车和换行('\r\n')或换行('\n')适当结束。工具必须能够处理两种行结尾方式。

警告: LOCAL_STATIC_PRIVATE_KEY 和潜在的 PRESHARED_KEY 是长期机密,用户应该只存储非生产密钥,或者确保 pcapng 文件的适当保护。

机密长度(32bits)

      一个用于描述后续机密字段长度的无符号标识符,不包括填充。

机密数据

      包含机密信息的二进制数据,4字节对齐。

[15] “NSS Key Log Format”

3.8 自定义块

      自定义块用于存储不属于另一个块的用户自定义数据;要将自定义数据存储为另一个块的一部分,详见原文3.5.1。该块是可选的,且可以在一个pcapng 文件中于任何位置重复任意次(除了第一个节头块前)。不同类型节点/不同PEN编号的不同自定义块,可能出现在同一个pcapng文件中。

块类型(0x0000 0BAD/0x4000 0BAD)

块总长

私人企业编号(PEN)

自定义数据

选项(变长)

块总长

图表 23 自定义块格式

      对于 pcapng 重写器可以复制到新文件中的自定义块,其类型代码为

0x00000BAD(十进制为 2989),对于不应被复制的块,其类型代码为

0x40000BAD(十进制为 1073744813)。

自定义块有以下字段:

块类型(32 位)

自定义块的块类型为 0x00000BAD 或 0x40000BAD,如前所述。

块总长度(32 位)

该块的总大小,如第 3.1 节所述。

私有企业号码(32 位)

IANA分配的私有企业号码,用于标识定义自 定义块的组织。详见 5.1 节。PEN 必须使用所在节内的节头块的相同字节序 。

自定义数据

自定义数据,4字节对齐。

选项

可选的,一个选项列表(根据章节 3.5 中定义的规则格式 化)可以出现。请注意,自定义块的自定义选项仍然使用自定义选项格式和类型代码,如第 3.5.1 节所述。

 

[1] 原文为cover,由于节头块实质上相当于一张表的表头信息,所以可以理解为节头块表示的范围“覆盖”一整个块的逻辑层级到下一个逻辑层级为止。

[2] 块总长的值

[3] 原文为TLV,即Typr-Length-Value

[4] 这句话就是说,“类型”就是选项字段内指定了“类型的“代码段。以普遍理性而言,这是废话。

[5] 这里开始直到介绍选项字段的格式之前都是标准规范性的论述。

[6] 指PCAPNG文件。

[7] 通用软件缺陷追踪工具

[8] 互联网地址编码分配机构(Internet Assigned Numbers Authority)

[9] 私人企业编码(Private Enterprise Number)

[10] 以下是标准规范的论述。

[11] 即,只有当接口ID被EPB或ISB等其它块使用时,IDB才有必要创建。IDB本身就是用用来解释接口ID所表示接口的块,从这种意义上讲,它类似于变量声明或是函数声明。

[12] 指shb_os选项字段。

[13] 取决于最小哈希类型

[14] 取决于最小判决类型

[15] “NSS Key Log Format”

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值