使用Python捕获TCP数据包

时间:2011-08-23 00:20:39

标签: python pcap

我尝试使用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-packets(tcp.data)的数据并将其写入文件。但是我注意到我经常得到具有相同TCP序列号(tcp.seq)的数据包(在同一连接上),但似乎它们包含相同的数据。此外,似乎并非所有数据包都被捕获。例如,如果我总结数据包大小,则结果值低于http-header(content-length)中列出的值。但在Wireshark中,我可以看到所有包裹。

有没有人知道为什么我会得到那些重复的数据包以及如何捕获属于http响应的每个数据包?

修改
在这里,您可以找到完整的代码:pastebin.com。 在运行时,它会向stdout输出类似的内容:

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-payload加上重复的接收字节数(5112497 + 82080 = 5194577)低于下载的文件大小(5197150)。此外,您可以看到我收到57个重复的包(相同的SEQ和相同的TCP数据),并且在带有FIN标志的数据包之后仍然收到包。

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

我甚至不知道我做错了什么,或者pcap-library是否出错了。

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)。

请帮助:)

2 个答案:

答案 0 :(得分:1)

以下是需要注意的几件事:

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

答案 1 :(得分:0)

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