我使用这段代码在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
我能够成功捕获数据包。所以我真的不知道问题出在哪里......
重现行为的其他信息
gcc test_sniff.c -o test_sniff -lpcap
Docker version 1.5.0, build a8a31ef
答案 0 :(得分:1)
答案很简单:
p.next()
throw
将timeout
100ms
您的超时为open_live
(except
的最后一个参数)
因此,您的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.settimeout
。 socket.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