flowcontainer

repository·master·Indexed 42 days ago

https://github.com/jmhicoding/flowcontainer

A Python 3 library for extracting basic and extended network flow information from PCAP files. It leverages tshark and optional PCAP splitting for high-speed analysis of large traffic datasets. Supports extraction of source/destination IPs, ports, timestamps, and custom Wireshark extension fields such as TLS SNI, SSL ciphersuites, and UDP payloads.

Tokens
3K
Snippets
7
Records
9
Agent score
4%

What's inside flowcontainer

  1. Extract custom Wireshark extension fields

    master

    You can extract specific Wireshark fields by passing them in the extension list to extract(). The resulting value.extension attribute is a dictionary where:

    • Key: The field name you requested.
    • Value: A list of tuples [(value, packet_index), ...].
      • value: The extracted data.
    • packet_index: The index of the IP packet in the stream where this value appeared.

    Common Extension Fields:

    Field NameExtension KeyTshark Requirement
    SNItls.handshake.extensions_server_name$\ge$ 3.0.0
    SSL Ciphersuitestls.handshake.ciphersuite$\ge$ 3.0.0
    X509 Certificatetls.handshake.certificate$\ge$ 3.0.0
    UDP Payloadudp.payload$\ge$ 3.3.0
    TCP Payloadtcp.payloadN/A

    Warning: Do not attempt to re-extract fields that are already provided by default (e.g., ip.src, tcp.port, ip.length), as this will cause parsing errors.

    # Example: Extracting TLS ciphersuites
    result = extract("file.pcap", extension=["tls.handshake.ciphersuite"])
    for key, value in result.items():
        # extension is a dict: {'tls.handshake.ciphersuite': [('value', index), ...]}
        print(value.extension)
  2. Parse HTTP, DNS, and SSL traffic

    master

    flowcontainer provides specialized parsing for common application-layer protocols via the extension mechanism.

    HTTP Parsing

    Extracts metadata such as User-agent, http-url, and host.

    DNS Parsing

    Extracts DNS records, such as A records (NAME, TYPE, ADDRESS).

    SSL/TLS Parsing

    Extracts security-related information including:

    • sni: Server Name Indication.
    • cipher_suites: List of supported cipher suites.
    • certificates: A list of X509 certificates containing issuer, subject, not_valid_before, not_valid_after, seriral_number, and version.

    Note: To use these, ensure you pass the appropriate protocol extensions during the extract call.

    # Example of what an SSL flow dictionary might look like:
    {
      'pcapname': 'tid_ssl.pcap', 
      'src_ip': '119.78.131.162', 
      'sport': 50665, 
      'dst_ip': '23.56.10.10', 
      'dport': 443, 
      'protocol': 'tcp', 
      'ext_proto': 'TLSv1.2', 
      'start': 1597319999.645109, 
      'end': 1597319999.732076, 
      'sni': 'c.go-mpulse.net', 
      'cipher_suites': '49192,49191...', 
      'certificates': [...] 
    }
  3. Configure the flowcontainer environment

    master

    To use flowcontainer, ensure your environment meets the following requirements:

    • Python: version 3.
    • NumPy: version >=18.1.
    • Wireshark/Tshark:
      • Install Wireshark (version 3.0.0 is recommended; avoid version 4.x as it contains breaking changes).
      • Ensure the tshark directory is in your system's PATH.
      • Version Requirements for specific features:
        • Basic info (ports, packet lengths): tshark >= 2.6.0.
        • TLS SNI extraction: tshark >= 3.0.0.
        • UDP payload extraction: tshark >= 3.3.0.
    • splitpcap: A tool for splitting large PCAP files to speed up parsing. Installation guide here.

    Critical: Ensure your shell (including IDE shells like PyCharm or VSCode) can execute tshark and splitpcap commands directly.

  4. Troubleshoot common flowcontainer errors

    master

    File Not Found

    If you receive a file not found error:

    1. Use absolute paths for the PCAP file.
    2. Ensure tshark is installed and available in your system's PATH.
    3. Verify that your tshark version is 2.6.0 or higher.

    ValueError: invalid literal for int() with base 10

    This typically occurs when non-TCP/UDP packets are present in the PCAP, causing port extraction to fail. Solutions:

    1. Specify a stricter filter in the extract call, such as filter='tcp or udp'.
    2. Avoid redundant extraction: Do not attempt to re-extract fields (like IP addresses, ports, or lengths) in the extension list if they are already being extracted by the core engine. tshark does not allow consecutive extractions of the same field.

    Other Issues

    If you encounter unknown issues, please submit a GitHub issue and include the problematic PCAP file and your code snippet.

  5. Use the extract function to parse PCAP files

    master

    Import extract from flowcontainer.extractor to parse a PCAP file. The function returns a dictionary where the key is a tuple (filename, protocol, stream_id) and the value is a Flow object.

    Function Signature: extract(infile, filter='', extension=None, split_flag=False)

    • infile: Path to the PCAP file.
    • filter: Packet filtering rules (uses Wireshark syntax). Can be empty.
    • extension: A list of additional Wireshark fields to extract (e.g., ['tls.handshake.extensions_server_name']). Can be empty.
    • split_flag: If True, the input PCAP is split into smaller PCAPs based on the 5-tuple, and parsed concurrently using a thread pool. This significantly improves speed for large files.
    from flowcontainer.extractor import extract
    
    # Basic extraction with specific TLS extensions
    result = extract(
        r"1592754322_clear.pcap",
        filter='',
        extension=["tls.handshake.extensions_server_name", "tls.handshake.ciphersuite"]
    )
  6. Access attributes of a Flow object

    master

    Once you have obtained a Flow object from the extract function, you can access various network metadata and packet sequences:

    AttributeDescription
    srcSource IP address
    dstDestination IP address
    sportSource port
    dportDestination port
    ext_protocolThe protocol name (e.g., UDP, TLSv1.2|TCP)
    extensionExtension data (e.g., SNI or certificates)
    time_startStart timestamp
    time_endEnd timestamp
    payload_lengthsSequence of payload packet lengths
    payload_timestampsSequence of payload packet timestamps
    ip_lengthsSequence of IP packet lengths (includes headers/zero payload)
    ip_timestampsSequence of IP packet timestamps
    lengthsDefault length sequence (defaults to payload_lengths)
    timestampsDefault timestamp sequence (defaults to payload_timestamps)
    # Example of accessing Flow attributes
    for key, value in result.items():
        print('src ip:', value.src)
        print('dst ip:', value.dst)
        print('sport:', value.sport)
        print('dport:', value.dport)
        print('payload lengths :', value.payload_lengths)
        print('payload timestamps:', value.payload_timestamps)
        print('ip packets lengths:', value.ip_lengths)
        print('ip packets timestamps:', value.ip_timestamps)
        print('default length sequence:', value.lengths)
        print('default timestamp sequence:', value.timestamps)
        print('start timestamp:{0}, end timestamp :{1}'.format(value.time_start, value.time_end))
        print('proto:', value.ext_protocol)
        print('extension:', value.extension)
  7. Access Flow object attributes

    master

    Once you have a Flow object from the extract result, you can access various network attributes.

    Note on Packet Lengths: Length sequences use signed integers to indicate direction:

    • Positive (+): Client to Server (C->S).
    • Negative (-): Server to Client (S->C).
    for key, value in result.items():
        # key is (filename, protocol, stream_id)
        print(f'Flow {key} info:')
        
        # IP and Port info
        print('src ip:', value.src)
        print('dst ip:', value.dst)
        print('sport:', value.sport)
        print('dport:', value.dport)
    
        # Payload sequences (only non-zero TCP/UDP payloads)
        print('payload lengths:', value.payload_lengths)
        print('payload timestamps:', value.payload_timestamps)
    
        # IP packet sequences (includes handshake/zero-payload packets)
        print('ip packets lengths:', value.ip_lengths)
        print('ip packets timestamps:', value.ip_timestamps)
    
        # Default sequences (aliases for payload sequences)
        print('default length sequence:', value.lengths)
        print('default timestamp sequence:', value.timestamps)
    
        # Timing
        print('start timestamp:', value.time_start)
        print('end timestamp:', value.time_end)
    
        # Protocol and Extensions
        print('proto:', value.ext_protocol)
        print('extension:', value.extension)
  8. Extract network flows using extract()

    master

    Use the flowcontainer.extractor.extract function to parse PCAP files into network flows.

    Return Value Structure: The function returns a dictionary where:

    • Key: A tuple containing (filename, protocol, stream_id).
    • Value: A Flow object (accessible via flowcontainer.flows.Flow attributes).

    Arguments:

    • file_path (str): Path to the PCAP file (absolute paths are recommended).
    • filter (str): Protocol filter (e.g., 'ip', 'tcp or udp').
    • extension (list): List of additional protocol extensions to extract.
    • split_flag (bool): Whether to enable flow splitting.
    • verbose (bool): Enable verbose logging.
    from flowcontainer.extractor import extract
    
    result = extract(
        r"1592993485_noise.pcap",
        filter='ip',
        extension=[],
        split_flag=False,
        verbose=True
    )
    
    for key, flow in result.items():
        print(f'Flow {key} info:')
        print(f'src ip: {flow.src}')
        print(f'dst ip: {flow.dst}')
        print(f'sport: {flow.sport}')
        print(f'dport: {flow.dport}')