pythonpython-2.7pcaplibpcapdpkt

Need help outputting the source and destination port number to the user, reading from a pcap file using Python, and dpkt


Hi everyone this is my first time doing PCAP programming using Python for the programming language, this is for a task for University and I have mostly got everything I need to complete the task except for one small detail.

I just need to get an output of the source and destination port numbers (HTTP Port 80 for example) associated with the IP addresses.

I'm happy for the answer to be a pointer to the right direction to help me work it out for myself. Otherwise if it's easier for it to be just answered, I would like a basic explanation on what was used and how it resolves the problem so I can understand it better for when I do more future PCAP programming in my studies and research.

This is being utilized on a Unix system running FreeBSD 10.3

I have tried using dpkt.tcp, dpkt.udp, dpkt.ip libraries as well as tried some socket libraries to see if I can achieve the result I am looking for, but not having much luck. I'll be honest, I'm not sure what I need to use.

EDIT: I did try using tcp.sport and tcp.dport, still had no luck.

The main area of focus is where I have added the comments.

import datetime
import time
import sys
import dpkt
import socket

def printPcap(pcap):
    for (ts,buf) in pcap:
        try:
            eth = dpkt.ethernet.Ethernet(buf)
            if eth.type == dpkt.ethernet.ETH_TYPE_IP:
                ip = eth.data
                ipsrc = socket.inet_ntoa(ip.src)        
                ipdst = socket.inet_ntoa(ip.dst)

                srcport = ??? ###Stuck here for source port
                dstport = ??? ###Stuck here for destination port

                if ip.p == dpkt.ip.IP_PROTO_TCP:        
                    TCP = ip.data
                    iptype = 'tcp'
                elif ip.p == dpkt.ip.IP_PROTO_UDP:   
                    UDP = ip.data
                    iptype = 'udp'
                len = str(ip.len)
                ttl = str(ip.ttl)

                ###My current output
                print '[' +str(datetime.datetime.utcfromtimestamp(ts))+ '] - ' \
                        +ipsrc+ ':' +srcport+ ' -> ' +ipdst+ ':' +dstport+ \
                        ' ('+iptype+', len='+len+', ttl='+ttl+')'

        except:
            pass

SAMPLE EXPECTED OUTPUT:

[2018-08-16 02:48:10.238506] - 172.16.11.2:61016 -> 172.16.10.2:80 (tcp, len=52, ttl=63)

Solution

  • The problem is that your print statement is bogus, but you've hidden that with the "bare except". Using the bare except is considered very poor practice in python for exactly this reason. See also answers to this question: Should I always specify an exception type in `except` statements?

    Specifically, your print statement is attempting to concatenate an integer to a string which isn't valid.

    So, repaired, and with:

                    if ip.p == dpkt.ip.IP_PROTO_TCP:
                        TCP = ip.data
                        iptype = 'tcp'
                        srcport = TCP.sport
                        dstport = TCP.dport
                    elif ip.p == dpkt.ip.IP_PROTO_UDP:
                        UDP = ip.data
                        iptype = 'udp'
                        srcport = UDP.sport
                        dstport = UDP.dport
    

    and this print statement, it works:

                    print("[{}] - {}:{} -> {}:{} ({}, len={}, ttl={})".format(
                          datetime.datetime.utcfromtimestamp(ts), ipsrc, srcport,
                          ipdst, dstport, iptype, len, ttl))
    

    Finally, at the very least, I would change your except clause to something like this to detect such issues in the future:

            except Exception as exc:
                print("Exception: {}".format(exc))
    

    (Note that I've used the python3-compatible print function syntax here, which also works fine with python2's print statement.)

    EDIT:
    One other thing just occurred to me. If the first IP packet encountered is neither TCP or UDP, srcport and dstport will not be defined and that will cause an AttributeError exception. Leaving that for you to clean up.