Search code examples
pythonscapysniffing

Scapy variable sniff stop


i found a similar problem: (Instance variables not being updated Python when using Multiprocessing), but still do not know the solutionn for my task.

The task is to stop a scapy sniff function after the completness of a testskript. the running duration of single testscripts can vary greatly (from some seconds till hours). My sniff function runs in a separate threat. The testscript calls an init Funktion in the beginning which calls the sniff Function from an other modul.

@classmethod
    def SaveFullTrafficPcap(self, TestCase, Termination):
        try:
            Full_Traffic = []
            PktList = []
            FullPcapName = Settings['GeneralSettings']['ResultsPath']+TestCase.TestCaseName +"Full_Traffic_PCAP.pcap"
            #while Term.Termination < 1:             
            Full_Traffic = sniff(lfilter=None, iface=str(Settings['GeneralSettings']['EthInterface']), store=True, prn = lambda x: Full_Traffic.append(x), count=0, timeout=Term.Termination)
            print(Full_Traffic)   
            wrpcap(FullPcapName, Full_Traffic)
        except(Exception):
            SYS.ABS_print("No full traffic PCAP file wirtten!\n")

At the end of the testscript an exit function is called. In the exit function I set Term.Termination parameter to 1 and wait for 5 sec, but it doesnt work. The sniff function is stoped by the system and i get no file"FullPCAPName" If count or timeout get a value, the code works without problemms and i get my FullPCAPName file with he complet traffic on my Interface.

Have anybody hinds how i can stopt the sniff function regulary after finisching the testscript?


Solution

  • Use of the stop_filter command as specified here worked for me. I've duplicated HenningCash's code below for convenience:

    import time, threading
    from scapy.all import sniff
    e = threading.Event()
    def _sniff(e):
        a = sniff(filter="tcp port 80", stop_filter=lambda p: e.is_set())
        print("Stopped after %i packets" % len(a))
    
    print("Start capturing thread")
    t = threading.Thread(target=_sniff, args=(e,))
    t.start()
    
    time.sleep(3)
    print("Try to shutdown capturing...")
    e.set()
    
    # This will run until you send a HTTP request somewhere
    # There is no way to exit clean if no package is received
    while True:
        t.join(2)
        if t.is_alive():
            print("Thread is still running...")
        else:
            break
    
    print("Shutdown complete!")
    

    However, you still have to wait for a final packet to be sniffed, which might not be ideal in your scenario.