1

当我在 pcap 文件上执行以下 Python 代码时:

if tcp.dport == 80:    
   try:
      http=dpkt.http.Request(tcp.data)
   except (dpkt.dpkt.NeedData):
      continue
   except (dpkt.dpkt.UnpackError):
      continue
if http.method == 'POST':
   print('POST Message')

如下数据包会产生问题: 在此处输入图像描述

这是一个单独的 HTTP Post 消息,被分割成两个 TCP 段,每个段都在不同的数据包中发送。但是,因为第一个段仅是 TCP,而第二个被识别为 HTTP,所以当 dpkt.http.Request 尝试将第一个段读取为 HTTP 时,它似乎失败了。

到目前为止没有问题。失败是可以的,因为它不是真正的完整 HTTP 消息。但是,问题是它似乎根本没有阅读第二段(“ POST Message ”没有打印)!!!第二段完全被忽略,就好像它不存在一样!!!对此唯一可能的解释是 dpkt 会立即自动读取第二段,因为它识别出它们都是同一消息的段。

问题是,尽管同时读取两个 TCP 段(遵循上述假设),但结果 tcp.data 不会被识别为 HTTP 数据包,而是仍然被识别为 TCP,只是因为消息的第一段是仅 TCP 数据包。

那么我应该怎么做才能读取此类 pcap 文件的 HTTP 标头和数据呢?

4

3 回答 3

2

dpkt仅适用于数据包级别。dpkt.http.Request期望完整的 HTTP 请求作为输入,而不仅仅是当前数据包中的部分。这意味着您必须从属于该连接的所有数据包中收集输入,即重新组装 TCP 数据流。

重新组装不仅仅是连接数据包,还要确保没有丢失的数据包,没有重复,并且数据包以正确的顺序重新组装,这可能不是线路上的顺序。本质上,在将提取的有效负载放入套接字缓冲区之前,您需要完成操作系统内核所做的一切。

有关如何完成部分操作的示例,请参阅Follow HTTP Stream (with decompression)。请注意,那里的示例盲目地假设数据包已经有序、完整且没有重复 - 并且假设在现实生活中并不能保证。

于 2018-11-16T20:01:18.080 回答
0

也许有点晚了。@steffen Ullrich提出的观点是正确的。但是,假设您没有这些问题(即没有丢失、重复的 pkts 等),您可以像我为重新组装分布在多个 TLS 数据包上的 TLS 帧所做的那样进行一些基本的重组。您可以将类似的逻辑应用于 HTTP 流量。您可以在我针对与 TLS 帧重组相关的类似问题发布的SO 问题中找到我的解决方案。顺便说一句,在我的解决方案中,我使用的是 scapy。

于 2020-02-18T01:22:04.763 回答
0

或者您可以使用 Scapy 2.4.3+ 中的内置功能 https://scapy.readthedocs.io/en/latest/layers/http.html

sniff(session=TCPSession, [...])
于 2020-02-18T12:59:18.793 回答