python3使用libpcap库进行抓包及数据处理的操作方法

1. 介绍

Packet Capture library (libpcap) 是一个在类Unix/Linux操作系统上用于捕获网络数据包的开源库。 Python包含了Pylibpcap, 是libpcap库的Python版本。Pylibpcap提供了一个几乎与libcap一样的接口,它提供了一个方便的软件开发工具箱,使开发者们能够使用Python脚本进行数据包的捕获,尤其是在操作网络安全和网络性能监测应用程序时。

2. 安装

在Python3中,我们可以通过pip3来安装pylibpcap模块,使用以下命令:

pip3 install pypcap

3. 捕获数据包

使用pylibpcap捕获数据包的第一步,是需要打开一个network interface来进行数据包的捕获。 我们通过libpcap中的pcap.open_live(...)函数来打开一个device。这个函数返回 pcap 对象,并且允许我们绑定一个callback函数以接受并处理捕获到的数据包信息。 所以第二步是注册一个callback函数:

import pcap

def packet_by_packet(packet):

print("Packet:", packet)

pc = pcap.pcap()

pc.setfilter('icmp')

pc.loop(0, packet_by_packet) #0表示持续监控

3.1 打开network interface

我们可以使用pcap库的pcap.lookupdev()函数来查找这个系统上的设备,然后使用pcap.open_live(device, snaplen)函数来打开它。

from pcap import *

import sys

dev = sys.argv[1]

pc = pcapObject()

pc.open_live(dev, 65536, 1, 0)

pcap.lookupdev()函数返回字符串类型的device名称,该device是我们要打开的设备。 通常在Unix系统上,除非对特殊的设备有特殊的需求,否则都是打开默认网络设备: eth0。在Windows系统中,通常使用设备名称,如:rpcap://\\Device\\NPF_{7B4293E6-C9A3-4111-9DBC-6EFA3E8C18A9}。

pcap.open_live() 参数依次为:

device (string):设备名称

montior size (integer): 捕获的数据包的大小

promiscuous (boolean): 是否打开混杂模式

timeout (In milliseconds): 等待数据包的超时时间

3.2 抓包

在打开interface后,我们可以使用pcap.loop(count, callback)函数来开始包的捕获, 可以通过count告诉它只要捕获多少个包就停止。但是如果不需要停止捕获数据包,可以传递一个0给count参数。每捕获一个包,callback参数所绑定的函数就会被调用。

捕获的数据包的类型是一个字符串(string)类型的数据,代表着一个dhcp包或一个tcp包等等。下面是一个可以抓取所有网络流量的callback函数:

def capture_callback(timestamp, pkt_data):

print(repr(pkt_data))

pc = pcap.pcap(name=None, promisc=True, immediate=True)

pc.setnonblock(False)

pc.set_snaplen(65535)

pc.set_promisc(True)

pc.set_timeout(100)

pc.activate()

pc.loop(0, capture_callback) #0表示持续监控

这个callback函数打印了被捕获的数据包的二进制表示方法,这种表示方法通常用来解析数据包。

4. 数据处理

捕获数据包是网络安全分析和监测的常见任务。一旦我们定义了一个callback函数来监视一个网络interface,我们就可以抓取数据包了。然后,我们需要处理这些数据包。处理数据包有很多方式。常见的做法是分析数据包内容中的数据。例如,在tcp包中,我们可以分析payload(负载)中的信息。

我们可以通过pcapfilter或libpcap来捕获选定的流量,它们是非常快速的,不需要读取每个网络数据包,只需捕获与特定过滤器匹配的流量即可。 以下是该过滤器的例子:

import pcap

from dpkt.ethernet import Ethernet

from dpkt.ip import IP

from dpkt.icmp import ICMP

from dpkt.tcp import TCP

from dpkt.udp import UDP

def get_packet_details(p, verbose=0):

eth = Ethernet(p)

if eth.type == 0x0800:

ip = eth.data

src = '%d.%d.%d.%d' % tuple(map(ord, list(ip.src)))

dst = '%d.%d.%d.%d' % tuple(map(ord, list(ip.dst)))

if ip.p == 1:

icmp = icmpprotocol.ICMP(ip.data)

if verbose:

print 'ICMP:%d->%s(%d)' % (icmp.type, dst, len(p))

elif ip.p == 6:

tcp = TCP(ip.data)

if verbose:

print 'TCP:%s:%d->%s:%d(%d)' % (src, tcp.sport, dst, tcp.dport, len(p))

if tcp.dport == 80 and (len(tcp.data) > 4 and len(tcp.data.split('\r\n\r\n')) > 1):

attr_headers = tcp.data.split('\r\n\r\n')[0].split('\r\n')

attr_data = tcp.data.split('\r\n\r\n')[1]

attributes = {}

for attr in attr_headers[1:]:

key, value = attr.split(':')[0], attr.split(':')[1][1:]

attributes.update({key: value})

if attributes['Content-Type'][0:8] == 'multipart':

pass

else:

if attributes['Content-Type'][0:16] == 'application/json':

print attr_data

elif attributes['Content-Type'][0:15] == 'text/plain;charset':

pass

else:

pass

data = dev.recv(1024)

get_packet_details(data)

这是一个简单的Demo,它解析了接收到的数据包中的一些信息,并据此进行处理。 例如,它可以查找所有传输控制协议(TCP)数据包,并输出它们的信息。

5. 总结

本文介绍了如何使用Python3中的Pylibpcap库来抓取数据包,以及如何分析数据包。在计算机网络安全、网络性能监测等领域中,抓取并分析数据包是一个非常重要的技术。本文提供的方法可以帮助我们更好地实现这项技术。

后端开发标签