Search code examples
pythonpython-3.xtcp

How can I extract TCP SYN flag from pcap file and detect SYN Flood attack using Python (Scapy)?


I'm parsing a PCAP file and I need to extract only TCP flags (SYN) for detect a SYN Flood attack. I use Python and scapy.

The main goal is a way of detecting a SYN flood attack! I need to count a number of TCP flags (SYN) for each IP address and print a list with : {IP: number of SYN flag} sorted by number of SYN flag. Could somebody help me?

# -*- coding: utf-8 -*-
from scapy.all import *
pkts = PcapReader("test.pcap")
dict_ips = dict() 

Solution

  • The best object for what you are trying to do is a Counter (from collections).

    The "not-so-Pythonic" (but easier to read if you're not used to Python) way of writing this would be:

    from scapy.all import PcapReader, TCP
    from collections import Counter
    count = Counter()
    for pkt in PcapReader("test.pcap"):
        if TCP in pkt and pkt[TCP].flags & 2:  # TCP SYN packet
            src = pkt.sprintf('{IP:%IP.src%}{IPv6:%IPv6.src%}')
            count[src] += 1
    

    It's easy to write this as a comprehension:

    from scapy.all import PcapReader, TCP
    from collections import Counter
    count = Counter(
        pkt.sprintf('{IP:%IP.src%}{IPv6:%IPv6.src%}')
        for pkt in PcapReader('test.pcap')
        if TCP in pkt and pkt[TCP].flags & 2
    )
    

    Then, a Counter behaves like a dict object:

    >>> count["1.2.3.4"]
    12
    

    But a Counter has a handy .most_common() method:

    >>> count.most_common(1)
    [('1.2.3.4', 12)]
    >>> count.most_common()
    [('1.2.3.4', 12), [...]]
    

    As a conclusion I have to mention that Scapy has poor performances when it comes to parsing a lot of packets (and if we are talking about flood, that might be the case). If I were you, I would still use a Counter, but I would generate the sources by using a subprocess.Popen() call to tcpdump or tshark instead of Scapy's PcapReader.