无法跟踪 python pcapy 包装器中的错误
Cannot trace error in python pcapy wrapper
我在 docker
容器中使用 python pcapy
使用这段代码:
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
当我 运行 它时,我得到以下异常:
Traceback (most recent call last):
File "test_pcap.py", line 12, in
print p.next()
PcapError
我尝试通过更改为不同的最大数据包大小并将混杂设置为 True
。
我试图从异常中获取任何消息,但消息似乎是空的。我还浏览了 pcapy source code: since the exception in the PcapyError object is empty and the other PcapErrors in the next
function are explicit strings, it implies we are falling into the condition in which buf
is empty. It seems pcap_geterr
returns an empty string because pp->pcap
has been closed and the pointer to the pcap exception no longer exists (take a look into the doc).
当我运行使用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
找不到任何错误。这是 strace
输出中错误的 grep:
strace python test_pcap.py 2>&1 1>/dev/null | grep -i error
read(6, "[=33=][=33=][=33=]t[=33=][=33=][=33=]intt\n[=33=][=33=][=33=]ValueErrort[=33=][=33=][=33=]_"..., 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
我也通过自己打电话给 pcap_next
测试了 pcap.h
:
// 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版本:
Docker version 1.5.0, build a8a31ef
- Docker 图片是 Docker 默认值
Ubuntu
- Python2.7
答案很简单:
p.next()
将在 timeout
上 throw
您的超时是 100ms
(open_live
的最后一个参数)
所以你的 except
应该处理超时情况,你可能想增加 timeout
时间或将它设置为 0
for infinite
编辑:
你只是期望 socket.timeout
但 PcapError
被抛出。 socket.timeout
是 python 库中的套接字代码抛出的异常,因此它是 python 特定的。它正在结束(可能只是使用新版本的 pcapy)或者它只是代表一种不同类型的超时(与 TCP 套接字相关)
请参阅示例 pcapy 代码:example
pcapy
不使用 Python socket
模块。如果先前的 socket.settimeout
调用启用了超时,它不会引发 socket.timeout
。 socket.settimeout
用于将socket
设置为阻塞、非阻塞或超时状态。
在 pcapy
中,open_live
的超时参数至少在 Linux 中传递给 poll
系统调用,应该与 OS 不同,其中 poll
不可用。
Reader.next
如果没有数据包到 return,调用会引发 PcapError
,因为它还没有捕获任何数据包。这不是错误,只是像 StopIteration
这样的指示。可以忽略,需要重新调用Reader.next
。
Reader.loop
不会 return 直到它至少有一个数据包到 return 或发生错误。
以下代码捕获 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
我在 docker
容器中使用 python pcapy
使用这段代码:
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
当我 运行 它时,我得到以下异常:
Traceback (most recent call last):
File "test_pcap.py", line 12, in
print p.next()
PcapError
我尝试通过更改为不同的最大数据包大小并将混杂设置为 True
。
我试图从异常中获取任何消息,但消息似乎是空的。我还浏览了 pcapy source code: since the exception in the PcapyError object is empty and the other PcapErrors in the next
function are explicit strings, it implies we are falling into the condition in which buf
is empty. It seems pcap_geterr
returns an empty string because pp->pcap
has been closed and the pointer to the pcap exception no longer exists (take a look into the doc).
当我运行使用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
找不到任何错误。这是 strace
输出中错误的 grep:
strace python test_pcap.py 2>&1 1>/dev/null | grep -i error
read(6, "[=33=][=33=][=33=]t[=33=][=33=][=33=]intt\n[=33=][=33=][=33=]ValueErrort[=33=][=33=][=33=]_"..., 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
我也通过自己打电话给 pcap_next
测试了 pcap.h
:
// 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版本:
Docker version 1.5.0, build a8a31ef
- Docker 图片是 Docker 默认值
Ubuntu
- Python2.7
答案很简单:
p.next()
将在 timeout
上 throw
您的超时是 100ms
(open_live
的最后一个参数)
所以你的 except
应该处理超时情况,你可能想增加 timeout
时间或将它设置为 0
for infinite
编辑:
你只是期望 socket.timeout
但 PcapError
被抛出。 socket.timeout
是 python 库中的套接字代码抛出的异常,因此它是 python 特定的。它正在结束(可能只是使用新版本的 pcapy)或者它只是代表一种不同类型的超时(与 TCP 套接字相关)
请参阅示例 pcapy 代码:example
pcapy
不使用 Python socket
模块。如果先前的 socket.settimeout
调用启用了超时,它不会引发 socket.timeout
。 socket.settimeout
用于将socket
设置为阻塞、非阻塞或超时状态。
在 pcapy
中,open_live
的超时参数至少在 Linux 中传递给 poll
系统调用,应该与 OS 不同,其中 poll
不可用。
Reader.next
如果没有数据包到 return,调用会引发 PcapError
,因为它还没有捕获任何数据包。这不是错误,只是像 StopIteration
这样的指示。可以忽略,需要重新调用Reader.next
。
Reader.loop
不会 return 直到它至少有一个数据包到 return 或发生错误。
以下代码捕获 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