【问题标题】:Capture TCP-Packets with Python使用 Python 捕获 TCP 数据包
【发布时间】:2011-11-01 13:46:03
【问题描述】:

我尝试使用 dpkt 和 pcap 通过 Python 捕获 HTTP 下载。代码看起来像

...
pc = pcap.pcap(iface)
for ts, pkt in pc:
    handle_packet(pkt)

def handle_packet(pkt):
    eth = dpkt.ethernet.Ethernet(pkt)

    # Ignore non-IP and non-TCP packets
    if eth.type != dpkt.ethernet.ETH_TYPE_IP:
        return
    ip = eth.data
    if ip.p != dpkt.ip.IP_PROTO_TCP:
        return

    tcp = ip.data
    data = tcp.data

    # current connection
    c = (ip.src, ip.dst, tcp.sport, tcp.dport)

    # Handle only new HTTP-responses and TCP-packets
    # of existing connections.
    if c in conn:
        handle_tcp_packet(c, tcp)
    elif data[:4] == 'HTTP':
        handle_http_response(c, tcp)
...

handle_http_response()handle_tcp_packet() 中,我读取tcp 数据包(tcp.data)的数据并将它们写入文件。但是我注意到我经常收到具有相同 TCP 序列号 (tcp.seq) 的数据包(在同一个连接上),但它们似乎包含相同的数据。此外,似乎并非所有数据包都被捕获。例如,如果我总结数据包大小,则结果值低于 http-header (content-length) 中列出的值。但是在 Wireshark 中我可以看到所有的包。

有谁知道我为什么会得到这些重复的数据包以及如何捕获属于 http-response 的每个数据包?

编辑:
在这里你可以找到完整的代码:pastebin.com。 运行时它会在标准输出中打印类似的内容:

Waiting for HTTP-Audio-responses ...
...
New TCP-Packet, len=1440, tcp-payload=5107680, con-len=5197150 , dups=57 , dup-bytes=82080
New TCP-Packet, len=1440, tcp-payload=5109120, con-len=5197150 , dups=57 , dup-bytes=82080
New TCP-Packet, len=1440, tcp-payload=5110560, con-len=5197150 , dups=57 , dup-bytes=82080
----------> FIN <----------
New TCP-Packet, len=1937, tcp-payload=5112497, con-len=5197150 , dups=57 , dup-bytes=82080
New TCP-Packet, len=0, tcp-payload=5112497, con-len=5197150 , dups=57 , dup-bytes=82080

如您所见,TCP 有效负载加上重复的接收字节 (5112497+82080=5194577) 小于下载的文件大小 (5197150)。此外,您可以看到我收到了 57 个重复的包(相同的 SEQ 和相同的 TCP 数据),并且在带有 FIN 标志的数据包之后仍然收到了包。

那么有没有人知道如何捕获属于该连接的所有数据包? Wireshark 可以看到所有数据包,我认为它也使用了 libpcap。

我什至不知道是我做错了什么,还是 pcap 库做错了什么。

EDIT2:
好的,看来我的代码是正确的:在 Wireshark 中,我保存了捕获的数据包并在我的代码中使用了捕获文件(pcap.pcap('/home/path/filename') 而不是pcap.pcap('eth0'))。我的代码完美地读取了所有包(在多个测试中)!由于 Wireshark 也使用 libpcap (afaik),我认为问题在于 lib pypcap 并没有为我提供所有包。

关于如何测试的任何想法?

我已经自己编译了 pypcap(主干),但这并没有改变任何东西 -.-

EDIT3:
好的,我将代码更改为使用 pcapy 而不是 pypcap 并且遇到了同样的问题:
从以前捕获的文件(使用 Wireshark 创建)读取数据包时,一切都很好,但是当我直接从 eth0 捕获数据包时,我错过了一些数据包。

有趣:当同时运行两个程序(一个使用 pypcap 和一个使用 pcapy)时,它们会捕获不同的数据包。例如一个程序多接收一个数据包。

但我仍然不知道为什么-.-
我认为 Wireshark 使用相同的 base-lib (libpcap)。

请帮忙:)

【问题讨论】:

  • 您是否丢失了整个数据包,或者将数据包缩短了? pcap 有(曾经有?)默认情况下有一个小缓冲区,所以你不会(不是吗?)总是获取每个数据包的所有数据。
  • 这是一个有趣的问题 :) 在 Wireshark 中,每个 TCP 数据包都有 1440 字节的数据。来自 pcap 的数据包也有 1440 字节的数据。下载的content-length是5197150。TCP-packet-length的总和是5152510(除了与之前的数据包具有相同的SEQ并且没有HTTP-header-information的重复数据包)。差异(5197150-5152510=44640)是(总是)1440的倍数。所以我想我错过了整个数据包,对吧?

标签: python pcap


【解决方案1】:

以下几点需要注意:

  • 确保你有一个大的 snaplen - 对于 pcapy,你可以在 open_live 上设置它(第二个参数)
  • 确保您处理碎片数据包 - 这不会自动完成 - 您需要检查详细信息
  • 检查统计信息 - 不幸的是,我认为这不会暴露给 pcapy 接口,但您可能没有处理所有数据包;如果你太晚了,你不会知道你错过了什么(尽管你可以通过跟踪 tcp 流的长度/位置来获得相同的信息)libpcap 本身确实公开了这些统计信息,所以你可以为它添加函数

【讨论】:

  • 感谢您的回复。 1) 使用 pcapy 时,我使用了 2097100 的最大 snaplen,但没有任何改变。 (2097101 导致缓冲区溢出) to 2) 我想你的意思是IP数据包分片?!我更改了代码以分析 IP 数据包。但是没有数据包将 MORE_FRAGMENTS 标志设置为 1。只有少数数据包将“不分片”标志设置为 0,但这些数据包太小而不能成为丢失的数据包;)
  • @Biggie 实际上,请将 snaplen 限制为 1500(或任何您的实际 mtu)。捕获缓冲区被分成 snaplen 大小的块。这意味着如果您将 snaplen 设置得太大,您将无法缓冲很多数据包 - 因为捕获缓冲区的大小是固定的。
  • 我的路由器使用 1492 的 MTU。当我使用 1492 作为 snaplen 时,我注意到每个 tcp 数据包的数据长度仅为 1416(与 snaplen 为 1500 相同)。所以我增加了 snaplen,直到我得到 1440 的数据长度(和以前一样)。我目前的 snaplen 是 1517,实际上我有时会收到所有的数据包......但并非总是如此-.- 使用 1700 的 snaplen,我会更频繁地收到所有数据包,但并非总是如此。有没有办法找出应该使用哪个 snaplen 来始终获取所有数据包?
  • 应该是 >= mtu (实际上应该是 == mtu,但我注意到在这种情况下没有捕获到一些数据包......据我所知,这不应该发生,但在测试)151x 应该是最佳的 - 任何更高的值都会导致缓冲区比必要的更快地填充 - 你真的希望它保持空。如果你捕获的东西速度非常快,这篇论文可能会让你感兴趣:改进被动数据包捕获:超越设备轮询 (luca.ntop.org/Ring.pdf) 并检查 PF_RING。
  • 使用“151 * MTU”的 snaplen,我只能得到 ca。每次下载 95% 的数据包。现在我将 snaplen 设置为“2 * MTU”(2*1492=2984),在 30 多个测试用例中,只有一个下载未被完全捕获。即使 2984 的 snaplen 对我有用,但我如何确保它也适用于其他计算机/网络? Wireshark 使用的是哪个 snaplen?由于 Wireshark 总是获取所有数据包。
【解决方案2】:

将 snaplen 设置为 65535。显然这是 Wireshark 的默认值: http://www.wireshark.org/docs/wsug_html_chunked/ChCustCommandLine.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    相关资源
    最近更新 更多