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