需要帮助将源端口号和目标端口号输出给用户,使用 Python 和 dpkt 从 pcap 文件读取



大家好,这是我第一次使用Python进行PCAP编程,这是大学的任务,除了一个小细节外,我基本上得到了完成任务所需的一切。

我只需要获取与 IP 地址关联的源端口号和目标端口号(例如 HTTP 端口 80)的输出。

我很高兴答案是指向正确方向的指针,以帮助我自己解决问题。否则,如果更容易回答它,我想对使用的内容以及它如何解决问题进行基本解释,以便当我在学习和研究中进行更多未来的PCAP编程时,我可以更好地理解它。

这在运行FreeBSD 10.3的Unix系统上使用

。 我尝试使用dpkt.tcp,dpkt.udp,dpkt.ip库,并尝试了一些套接字库,看看我是否可以达到我想要的结果,但没有太多运气。老实说,我不确定我需要使用什么。

编辑:我确实尝试使用tcp.sport和tcp.dport,仍然没有运气。

主要关注领域是我添加评论的地方。

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

示例预期输出:

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

问题是你的打印语句是假的,但你用"裸露的除外"隐藏了它。正是由于这个原因,在 python 中使用裸露的除外被认为是非常糟糕的做法。另请参阅此问题的答案:我是否应始终在"例外"语句中指定异常类型?

具体来说,您的 print 语句正在尝试将整数连接到无效的字符串。

所以,修复,并带有:

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

而这个打印语句,它有效:

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

最后,至少,我会将您的 except 子句更改为类似的东西,以便将来检测此类问题:

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

(请注意,我在这里使用了与python3兼容的打印函数语法,该语法也适用于python2的print语句

编辑:
我刚刚想到的另一件事。如果遇到的第一个 IP 数据包既不是 TCP 也不是 UDP,则不会定义srcportdstport,这将导致AttributeError异常。留给你清理。

也许使用ip.data来获取 TCP 数据包以及sport和/或dport

ip = eth.data
if ip.p == dpkt.ip.IP_PROTO_TCP:
tcp = ip.data
print('source port: {}, dest port: {}'.format(tcp.sport, tcp.dport))

最新更新