Reputation: 118
I have written a script that sniffs packet from a host, however, I am sniffing the packets in continuous mode and would like to stop sniffing on a timeout. I have written the following code to stop packet sniffing, but it doesn't seem to stop when the time has clearly exceeded the timeout. What could I be doing wrong in here?
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)
We then get this output, with thousands of additional packets a second, past when the capture should have stopped:
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
...
Why does PyShark continue to capture packets after the timeout?
Upvotes: 2
Views: 4935
Reputation: 735
You can use the following line in bash or even in python within os.system
, os.popen
or even subprocess
:
while IFS= read -r line; do if [[ $line =~ 'some protocol' ]]; then <SOME_ACTION>; break; fi; done < <(sudo tshark)
Upvotes: 1
Reputation: 153
I was having this same issue, I managed to find a bit of a solution for it. It isn't perfect but it works by telling the capture loop to stop on the next packet and sends an empty packet it will see to make it end. I made it a udp packet on a high port for my case because I use a filter that filters out most traffic so this solution worked for me
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
I'm relatively new to python myself but I think this should be a somewhat acceptable solution given the scenario
Upvotes: 2
Reputation: 3186
It looks like you're running into a known issue with PyShark that hasn't been fixed in years. Per the thread, the author wrote
You can subclass LiveCapture and override the get_parameters() function, adding your own parameters.
You could modify the parameters sent to tshark, but at this point, why not just use a tshark command directly?
PyShark is just a wrapper for tshark on your system. If you want to use subprocess with Python, the equivalent tshark command is tshark -a duration:5
. The other advantage of using tshark directly is that subprocess gives you a pid that you can kill on an arbitrary condition.
See the manpage for more details.
Upvotes: 1