4

I'd like to run pyshark in the background so while its running I'll still be able to perform some web actions and capture them. One mandatory condition is that I must be able to parse using tshark because I have some proprietary Wireshark dissectors.

Basically what I need to do is this:

  1. Start network capture
  2. Perform some web actions
  3. Stop capture (or wait for a stop condition)
  4. Iterate over capture object and check each packet's properties

I can't use capture.sniff() as-is because it's working in blocking mode, and can't use capture.sniff_continuously() because it's a generator.

Problem: I tried calling sniff() from a thread, then wait for it to end with join(). But when I reach the iterator, tshark.exe relaunch and overwrites the capture file:

print('Background sniffing:')
capture = pyshark.LiveCapture(interface='Ethernet', bpf_filter='host 10.20.30.40', output_file='bg_capture.pcapng')
t = threading.Thread(target=capture.sniff, kwargs={'timeout': 30, 'packet_count': 5000}, daemon=True)
t.start()
print('Do some stuff web action here...')
t.join()
print('Done sniffing')
for p in capture: # At this point, tshark re-launch itself
    print(f'Packet number {p.number}')
someuser
  • 43
  • 4

1 Answers1

0

Solution: start network traffic capture on a background thread, then initiate some network traffic on the main thread and use captured traffic for analysis whatever you need.

import pyshark
import sh
import threading
import time

#we want observe network traffic just to this destination
dst_ip = "172.217.16.14"

#background thread task
def capture_task():
    capture = pyshark.LiveCapture('any')
    capture.sniff(timeout=1)

    for packet in capture:
        if 'ip' in packet:
            protocol = packet.layers
            dst = packet['ip'].dst
            if dst == dst_ip:
                print("got it: proto:{}, dst:{}".format(protocol, dst))


def mainfn():
    #start a background thread
    thread = threading.Thread(target=capture_task)
    thread.start()

    print("start...")
    #some sleep - it is needed for other threads to have possibility to get CPU cycles
    time.sleep(1)

    #initiate some network traffic
    for i in range(5):
        print("doing my ping[{}] traffic...".format(i))
        sh.ping("-q", "-c", "1", dst_ip)
        time.sleep(0.3)

    #handle exit as you like...
    try:
        while True:
            time.sleep(0.1)
            pass
    except KeyboardInterrupt:
        print("exiting...")
        thread.join()


#run main fn
mainfn()
keliramu
  • 36
  • 4