如何利用libpcap和Python嗅探数据包
一提到Python获取数据包的方式,相信很多Python爱好者会利用Linux的libpcap软件包或利用Windows下的WinPcap可移植版的方式进行抓取数据包,然后再利用dpkt软件包进行协议分析,我们这里想换一个角度去思考:
1. Python版本的pcap存储内存数据过小,也就是说缓存不够,在高并发下容易发生丢包现象,其实C版本的也同样存在这样的问题,只不过Python版本的缓存实在是过低,让人很郁闷。
2. dpkt协议分析并非必须,如果你对RFC 791和RFC 793等协议熟悉的话,完全可以使用struct.unpack的方式进行分析。
如果你平常习惯使用tcpdump抓取数据包的话,完全可以使用它来代替pcap软件包,只不过我们需要利用tcpdump将抓取的数据以pcap格式进行保存,说道这里大家一定会想到Wireshark工具,具体命令如下:
tcpdump dst 10.13.202.116 and tcp dst port 80 -s 0 -i eth1 -w ../pcap/tcpdump.pcap -C 1k -W 5
我们首先需要对pcap文件格式有所了解,具体信息大家可以参考其他资料文档,我这里只说其重要的结构体组成,如下:
sturct pcap_file_header { DWORD magic; WORD version_major; WORD version_minor; DWORD thiszone; DWORD sigfigs; DWORD snaplen; DWORD linktype; } struct pcap_pkthdr { struct timeval ts; DWORD caplen; DWORD len; } struct timeval { DWORD GMTtime; DWORD microTime; }
这里需要说明的一点是,因为在Python的世界里一切都是对象,所以往往Python在处理数据包的时候感觉让人比较麻烦。Python提供了几个libpcapbind,http://monkey.org/~dugsong/pypcap/这里有 一个最简单的。在windows平台上,你需要先安装winpcap,如果你已经安装了Ethereal非常好用。一个规范的抓包过程:
import pcap import dpkt pc=pcap.pcap() #注,参数可为网卡名,如eth0 pc.setfilter('tcp port 80') #设置监听过滤器 for ptime,pdata in pc: #ptime为收到时间,pdata为收到数据 print ptime,pdata #...
对抓到的以太网V2数据包(raw packet)进行解包:
p=dpkt.ethernet.Ethernet(pdata) if p.data.__class__.__name__=='IP': ip='%d.%d.%d.%d'%tuple(map(ord,list(p.data.dst))) if p.data.data.__class__.__name__=='TCP': if data.dport==80: print p.data.data.data
一些显示参数nrecv,ndrop,nifdrop=pc.stats()返回的元组中,第一个参数为接收到的数据包,第二个参数为被核心丢弃的数据包。
至于对于如何监控tcpdump生成的pcap文件数据,大家可以通过pyinotify软件包来实现,如下:
class Packer(pyinotify.ProcessEvent): def __init__(self, product): self.product = product self.process = None def process_IN_CREATE(self, event): logger.debug("create file: %s in queue" % self.process_IF_START_THREAD(event)) def process_IN_MODIFY(self, event): self.process_IF_START_THREAD(event) logger.debug("modify file: %s in queue" % self.process_IF_START_THREAD(event)) def process_IN_DELETE(self, event): filename = os.path.join(event.path, event.name) logger.debug("delete file: %s" % filename) def process_IF_START_THREAD(self, event): filename = os.path.join(event.path, event.name) if filename != self.process: self.process = filename self.product.put(filename) if self.product.qsize() > 1: try: logger.debug("create consumer product.qsize: %s" % self.product.qsize()) consumer = Consumer(self.product) consumer.start() except Exception, errmsg: logger.error("create consumer failed: %s" % errmsg) return filename class Factory(object): def __init__(self, product): self.product = product self.manager = pyinotify.WatchManager() self.mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY def work(self): try: try: notifier = pyinotify.ThreadedNotifier(self.manager, Packer(self.product)) notifier.start() self.manager.add_watch("../pcap", self.mask, rec = True) notifier.join() except Exception, errmsg: logger.error("create notifier failed: %s" % errmsg) except KeyboardInterrupt, errmsg: logger.error("factory has been terminated: %s" % errmsg)
在获得要分析的pcap文件数据之后,就要对其分析了,只要你足够了解pcap文件格式就可以了,对于我们来讲只需要获得TCP数据段的数据即可,如下:
class Writer(threading.Thread): def __init__(self, product, stack): threading.Thread.__init__(self) self.product = product self.stack = stack self.pcap_pkthdr = {} def run(self): while True: filename = self.product.get() try: f = open(filename, "rb") readlines = f.read() f.close() offset = 24 while len(readlines) > offset: self.pcap_pkthdr["len"] = readlines[offset+12:offset+16] try: length = struct.unpack("I", self.pcap_pkthdr["len"])[0] self.stack.put(readlines[offset+16:offset+16+length]) offset += length + 16 except Exception, errmsg: logger.error("unpack pcap_pkthdr failed: %s" % errmsg) except IOError, errmsg: logger.error("open file failed: %s" % errmsg)
在获得TCP数据段的数据包之后,问题就简单多了,根据大家的具体需求就可以进行相应的分析了,我这里是想分析其HTTP协议数据,同样也借助了dpkt软件包进行分析,如下:
def worker(memcache, packet, local_address, remote_address): try: p = dpkt.ethernet.Ethernet(packet) if p.data.__class__.__name__ == "IP": srcip = "%d.%d.%d.%d" % tuple(map(ord, list(p.data.src))) dstip = "%d.%d.%d.%d" % tuple(map(ord, list(p.data.dst))) if p.data.data.__class__.__name__ == "TCP": tcpacket = p.data.data if tcpacket.dport == 80 and dstip == local_address: srcport = tcpacket.sport key = srcip + ":" + str(srcport) if tcpacket.data: if not memcache.has_key(key): memcache[key] = {} if not memcache[key].has_key("response"): memcache[key]["response"] = None if memcache[key].has_key("data"): memcache[key]["data"] += tcpacket.data else: memcache[key]["data"] = tcpacket.data else: if memcache.has_key(key): memcache[key]["response"] = dpkt.http.Request(memcache[key]["data"]) try: stackless.tasklet(connection)(memcache[key]["response"], local_address, remote_address) stackless.run() except Exception, errmsg: logger.error("connect remote remote_address failed: %s", errmsg) logger.debug("old headers(none content-length): %s", memcache[key]["response"]) memcache.pop(key) except Exception, errmsg: logger.error("dpkt.ethernet.Ethernet failed in worker: %s", errmsg)
如果大家只是想单纯的获取IP地址、端口、流量信息,那么问题就更简单了,这里只是抛砖引玉。另外再提供一段代码供参考:
import pcap, dpkt, struct import binascii def main(): a = pcap.pcap() a.setfilter('udp portrange 4000-4050') try: for i,pdata in a: p=dpkt.ethernet.Ethernet(pdata) src=/article/&/index.html % tuple(map(ord,list(p.data.src))) dst='%d.%d.%d.%d' % tuple(map(ord,list(p.data.dst))) sport = p.data.data.sport dport = p.data.data.dport qq = int( binascii.hexlify(p.data.data.data[7:11]) , 16 ) print 'QQ: %d, From: %s:%d , To: %s:%d' % (qq,src,sport,dst,dport) except Exception,e: print '%s' % e n = raw_input() if __name__ == '__main__': main()
linux c下利用srand和rand函数生成随机字符串 请问:Linux下用C编程计算CPU利用率和内存利用率? linux下利用(cat,strings,head,sed)命令生成随机字符串 在2003下利用vmware安装了linux,又利用host-only方式上了网,问题如下多谢指点!!! Web前端开发如何利用css样式来控制Html中的h1/h2/h3标签不换行 大虾 紧急求助!!!!如何求得当前机子的处理器利用率和内存利用率? windows堆栈溢出利用的七种方式 如何利用Bash脚本(利用awksedgrepwc等)来自动修改配置文件 求RADIUS的动态分配IP的问题(利用IPPOOL) iowait和cpu利用率的权衡问题 利用java.net.URLConnection上传文件 Qt中利用槽如何来传递参数 请问如何编程获得CPU利用率?(空) 如何利用Linux安装盘制作启动盘? 谁知道linux/unix下利用Schema读取校验xml的开源代码,给一个链接,谢谢! 怎样实现利用fprintf,输出定长字串,位数不足时在左侧填入指定字符填充。。 CPU、内存、数据库利用率监控 怎样利用u-boot烧写?? 根目录 / 文件利用过高, 啥办法? 浏览器漏洞利用框架 BeEF