一旦满足条件,我想在连续嗅探的同时停止数据包捕获

I want to stop packet capture while sniffing continuously once a condition is met

问题

我已经编写了一个从主机嗅探数据包的脚本,但是,我正在以连续模式嗅探数据包,并且想在超时时停止嗅探。我已经写了下面的代码来停止数据包嗅探,但是当时间明显超过超时时,它似乎并没有停止。我在这里做错了什么?

import time
import pyshark

prog_start = time.time()
capture = pyshark.LiveCapture(interface='en0')
capture.sniff(timeout=10)
start_time = capture[0].frame_info.time_epoch
end_time = capture[-1].frame_info.time_epoch
print("Capture lasted:", float(end_time) - float(start_time))
pkt_num = 0
for pkt in capture:
    pkt_num += 1
    print("Time", time.time() - prog_start, "Pkt#", pkt_num)

然后我们得到这个输出,每秒有数千个 额外的 个数据包,超过了捕获应该停止的时间:

Capture lasted: 9.148329019546509
Time 10.346031188964844 Pkt# 1
Time 10.348641157150269 Pkt# 2
Time 10.351708889007568 Pkt# 3
Time 10.353564977645874 Pkt# 4
Time 10.35555100440979 Pkt# 5
...

问题

为什么PyShark超时后继续抓包?

PyShark 问题

您似乎 运行 陷入 known issue 多年未修复的 PyShark 问题。根据线程,作者写道

You can subclass LiveCapture and override the get_parameters() function, adding your own parameters.

你可以修改发送给tshark的参数,但此时为什么不直接使用tshark命令呢?

改用 Tshark

PyShark 只是您系统上 tshark 的包装器。如果要将 subprocess 与 Python 一起使用,等效的 tshark 命令是 tshark -a duration:5。直接使用 tshark 的另一个优点是 subprocess 给你一个 pid,你可以在任意条件下杀死它。

有关详细信息,请参阅 manpage

我遇到了同样的问题,我设法找到了一些解决方案。它并不完美,但它的工作原理是告诉捕获循环在下一个数据包上停止并发送一个空数据包,它将看到它结束。对于我的案例,我在高端口上将它设为一个 udp 数据包,因为我使用了一个过滤器来过滤掉大部分流量,所以这个解决方案对我有用

class PacketCapture(threading.Thread):
    capture = 1

    def __init__(self, interface_name):
        threading.Thread.__init__(self)
        self.interface_name = interface_name

    def stop(self):
        self.capture = 0

    def run(self):
        capture = pyshark.LiveCapture(interface=self.interface_name)
        try:
            for packet in capture.sniff_continuously():
                if not self.capture:
                    capture.close()
        except pyshark.capture.capture.TSharkCrashException:
            self.exited = 1
            print("Capture has crashed")



#start capture
pcap = PacketCapture(interface_name)
pcap.start()

#stop capture
pcap.stop()
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = bytes("", "UTF-8")
sock.sendto(msg, ("external IP", 12345))
sock.close

我自己对 python 比较陌生,但我认为考虑到

这种情况,这应该是一个可以接受的解决方案

您可以在 bash 中甚至在 python 中使用以下行 os.systemos.popen 甚至 subprocess:

while IFS= read -r line; do if [[ $line =~ 'some protocol' ]]; then <SOME_ACTION>; break; fi; done < <(sudo tshark)