无法跟踪python pcapy包装器中的错误

时间:2015-04-13 19:05:59

标签: python networking docker pcap packet-sniffers

我使用这段代码在pcapy容器中使用python docker

from pcapy import open_live, findalldevs
import sys
import traceback

p = open_live("eth0", 1024, False, 100)
dumper = p.dump_open("test.pcap")

devices = findalldevs()
print dumper, devices
while True:
    try:
        print p.next()
    except Exception as e:
        print dir(e), e.message, e.args[0]
        traceback.print_exc(file=sys.stdout)
        break

当我运行它时,我得到以下异常:

  

追踪(最近一次呼叫最后一次):

     

文件" test_pcap.py",第12行,

print p.next()
     

PcapError

我尝试通过更改为不同的最大数据包大小并将混杂设置为True来尝试使用这些参数。

我试图从异常中获取任何消息,但似乎消息是空的。我还浏览了pcapy source code:因为PcapyError对象中的异常是空的而next函数中的其他PcapErrors是显式字符串,这意味着我们正陷入{{1}的状态} 是空的。似乎buf返回一个空字符串,因为pcap_geterr已关闭且指向pcap异常的指针不再存在(请查看doc)。

当我使用pp->pcap方法运行时,一切正常:

loop()

我真的不知道问题的根源或者为调试它做了什么。

修改

我使用# Modified from: http://snipplr.com/view/3579/ import pcapy from impacket.ImpactDecoder import * # list all the network devices pcapy.findalldevs() max_bytes = 1024 promiscuous = False read_timeout = 100 # in milliseconds pc = pcapy.open_live("eth0", max_bytes, promiscuous, read_timeout) # callback for received packets def recv_pkts(hdr, data): packet = EthDecoder().decode(data) print packet packet_limit = -1 # infinite pc.loop(packet_limit, recv_pkts) # capture packets 找不到任何错误。这是strace输出中的错误grep:

strace
  

读取(6," \ 0 \ 0 \ 0t \ 3 \ 0 \ 0 \ 0intt \ n \ 0 \ 0 \ 0ValueErrort \ 23 \ 0 \ 0 \ 0 _" ...,4096) = 995

     

getsockopt(3,SOL_SOCKET,SO_ERROR,[0],[4])= 0

     

getsockopt(5,SOL_SOCKET,SO_ERROR,[0],[4])= 0

     

getsockopt(5,SOL_SOCKET,SO_ERROR,[0],[4])= 0

EDIT2

我也通过自己致电strace python test_pcap.py 2>&1 1>/dev/null | grep -i error 来测试pcap.h

pcap_next

要编译,请将其写入 // Modified from: http://www.tcpdump.org/pcap.html #include <pcap.h> #include <stdio.h> int main(int argc, char *argv[]) { pcap_t *handle; /* Session handle */ char *dev; /* The device to sniff on */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error string */ bpf_u_int32 mask; /* Our netmask */ bpf_u_int32 net; /* Our IP */ struct pcap_pkthdr header; /* The header that pcap gives us */ const u_char *packet; /* The actual packet */ /* Define the device */ dev = pcap_lookupdev(errbuf); if (dev == NULL) { fprintf(stderr, "Couldn't find default device: %s\n", errbuf); return(2); } /* Find the properties for the device */ if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf); net = 0; mask = 0; } /* Open the session in promiscuous mode */ handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); if (handle == NULL) { fprintf(stderr, "Couldn't open device %s: %s\n", "eth0", errbuf); return(2); } while (1) { /* Grab a packet */ packet = pcap_next(handle, &header); /* Print its length */ printf("Jacked a packet with length of [%d]\n", header.len); /* Print contents */ printf("\tPacket: %s\n", packet); /* And close the session */ } pcap_close(handle); return(0); } 并运行:

test_sniff.c

我能够成功捕获数据包。所以我真的不知道问题出在哪里......

重现行为的其他信息

  • Docker版本:gcc test_sniff.c -o test_sniff -lpcap
  • Docker镜像是Docker默认Docker version 1.5.0, build a8a31ef
  • Python2.7

2 个答案:

答案 0 :(得分:1)

答案很简单:
p.next() throwtimeout 100ms 您的超时为open_liveexcept的最后一个参数)

因此,您的timeout应处理超时情况,您可能希望增加0时间或将infinite设为socket.timeout

编辑:
您只是期望PcapError,但会引发socket.timeout。 {{1}}是python lib中套接字代码抛出的异常,因此它是特定于python的。它正在被包裹起来(可能只是新版本的pcapy)或者jsut代表不同类型的超时(TCP套接字相关)
请参阅示例pcapy代码:example

答案 1 :(得分:1)

pcapy不使用Python socket模块。如果前一次socket.timeout调用启用超时,则不会引发socket.settimeoutsocket.settimeout用于将socket设置为阻塞,非阻塞或超时状态。

pcapy中,open_live的超时参数至少在Linux中传递给poll系统调用,应该因操作系统poll不可用而不同。

如果没有要返回的数据包,

Reader.next会调用PcapError,因为它尚未捕获任何数据包。这不是错误,仅仅是StopIteration的指示。可以忽略它,并且必须再次调用Reader.next

Reader.loop在至少返回一个数据包或发生错误之前不会返回。

以下代码捕获10个数据包并退出。

from pcapy import open_live, findalldevs, PcapError

p = open_live("eth0", 1024, False, 100)
dumper = p.dump_open("test.pcap")

devices = findalldevs()
print dumper, devices
count=0
while True:
    try:
        packet = p.next()
    except PcapError:
        continue
    else:
        print packet
        count += 1
        if count == 10:
            break