python拦截数据包_如何利用Python嗅探数据包

展开全部

一提到Python获取数据包的方式,相信很多Python爱好者会利用Linux的libpcap软件32313133353236313431303231363533e59b9ee7ad9431333361313235包或利用Windows下的WinPcap可移植版的方式进行抓取数据包,然后再利用dpkt软件包进行协议分析,我们这里想换一个角度去思考:

1. Python版本的pcap存储内存数据过小,也就是说缓存不够,在高并发下容易发生丢包现象,其实C版本的也同样存在这样的问题,只不过Python版本的缓存实在是过低,让人很郁闷。

2. dpkt协议分析并非必须,如果你对RFC 791和RFC 793等协议熟悉的话,完全可以使用struct.unpack的方式进行分析。

如果你平常习惯使用tcpdump抓取数据包的话,完全可以使用它来代替pcap软件包,只不过我们需要利用tcpdump将抓取的数据以pcap格式进行保存,说道这里大家一定会想到Wireshark工具,具体命令如下:

1. tcpdump dst 10.13.202.116 and tcp dst port 80 -s 0 -i eth1 -w ../pcap/tcpdump.pcap -C 1k -W 5

我们首先需要对pcap文件格式有所了解,具体信息大家可以参考其他资料文档,我这里只说其重要的结构体组成,如下:

1. sturct pcap_file_header

2. {

3. DWORD magic;

4. WORD version_major;

5. WORD version_minor;

6. DWORD thiszone;

7. DWORD sigfigs;

8. DWORD snaplen;

9. DWORD linktype;

10. }

11.

12. struct pcap_pkthdr

13. {

14. struct timeval ts;

15. DWORD caplen;

16. DWORD len;

17. }

18.

19. struct timeval

20. {

21. DWORD GMTtime;

22. DWORD microTime;

23. }

这里需要说明的一点是,因为在Python的世界里一切都是对象,所以往往Python在处理数据包的时候感觉让人比较麻烦。

至于对于如何监控tcpdump生成的pcap文件数据,大家可以通过pyinotify软件包来实现(相信大家一定对于rsync+inotify的组合比较熟悉),如下:

1. class Packer(pyinotify.ProcessEvent):

2. def __init__(self, product):

3. self.product = product

4. self.process = None

5.

6. def process_IN_CREATE(self, event):

7. logger.debug("create file: %s in queue" % self.process_IF_START_THREAD(event))

8.

9. def process_IN_MODIFY(self, event):

10. self.process_IF_START_THREAD(event)

11. logger.debug("modify file: %s in queue" % self.process_IF_START_THREAD(event))

12.

13. def process_IN_DELETE(self, event):

14. filename = os.path.join(event.path, event.name)

15. logger.debug("delete file: %s" % filename)

16.

17. def process_IF_START_THREAD(self, event):

18. filename = os.path.join(event.path, event.name)

19.

20. if filename != self.process:

21. self.process = filename

22. self.product.put(filename)

23.

24. if self.product.qsize() > 1:

25. try:

26. logger.debug("create consumer product.qsize: %s" % self.product.qsize())

27. consumer = Consumer(self.product)

28. consumer.start()

29. except Exception, errmsg:

30. logger.error("create consumer failed: %s" % errmsg)

31.

32. return filename

33.

34. class Factory(object):

35. def __init__(self, product):

36. self.product = product

37. self.manager = pyinotify.WatchManager()

38. self.mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY

39.

40. def work(self):

41. try:

42. try:

43. notifier = pyinotify.ThreadedNotifier(self.manager, Packer(self.product))

44. notifier.start()

45. self.manager.add_watch("../pcap", self.mask, rec = True)

46. notifier.join()

47. except Exception, errmsg:

48. logger.error("create notifier failed: %s" % errmsg)

49. except KeyboardInterrupt, errmsg:

50. logger.error("factory has been terminated: %s" % errmsg)

在获得要分析的pcap文件数据之后,就要对其分析了,只要你足够了解pcap文件格式就可以了,对于我们来讲只需要获得TCP数据段的数据即可,如下:

1. class Writer(threading.Thread):

2. def __init__(self, product, stack):

3. threading.Thread.__init__(self)

4. self.product = product

5. self.stack = stack

6.

7. self.pcap_pkthdr = {}

8.

9. def run(self):

10. while True:

11. filename = self.product.get()

12. try:

13. f = open(filename, "rb")

14. readlines = f.read()

15. f.close()

16. offset = 24

17. while len(readlines) > offset:

18. self.pcap_pkthdr["len"] = readlines[offset+12:offset+16]

19. try:

20. length = struct.unpack("I", self.pcap_pkthdr["len"])[0]

21. self.stack.put(readlines[offset+16:offset+16+length])

22. offset += length + 16

23. except Exception, errmsg:

24. logger.error("unpack pcap_pkthdr failed: %s" % errmsg)

25. except IOError, errmsg:

26. logger.error("open file failed: %s" % errmsg)

在获得TCP数据段的数据包之后,问题就简单多了,根据大家的具体需求就可以进行相应的分析了,我这里是想分析其HTTP协议数据,同样也借助了dpkt软件包进行分析,如下:

1. def worker(memcache, packet, local_address, remote_address):

2. try:

3. p = dpkt.ethernet.Ethernet(packet)

4. if p.data.__class__.__name__ == "IP":

5. srcip = "%d.%d.%d.%d" % tuple(map(ord, list(p.data.src)))

6. dstip = "%d.%d.%d.%d" % tuple(map(ord, list(p.data.dst)))

7. if p.data.data.__class__.__name__ == "TCP":

8. tcpacket = p.data.data

9. if tcpacket.dport == 80 and dstip == local_address:

10. srcport = tcpacket.sport

11. key = srcip + ":" + str(srcport)

12. if tcpacket.data:

13. if not memcache.has_key(key):

14. memcache[key] = {}

15.

16. if not memcache[key].has_key("response"):

17. memcache[key]["response"] = None

18.

19. if memcache[key].has_key("data"):

20. memcache[key]["data"] += tcpacket.data

21. else:

22. memcache[key]["data"] = tcpacket.data

23. else:

24. if memcache.has_key(key):

25. memcache[key]["response"] = dpkt.http.Request(memcache[key]["data"])

26. try:

27. stackless.tasklet(connection)(memcache[key]["response"], local_address, remote_address)

28. stackless.run()

29. except Exception, errmsg:

30. logger.error("connect remote remote_address failed: %s", errmsg)

31. logger.debug("old headers(none content-length): %s", memcache[key]["response"])

32. memcache.pop(key)

33. except Exception, errmsg:

34. logger.error("dpkt.ethernet.Ethernet failed in worker: %s", errmsg)

如果大家只是想单纯的获取IP地址、端口、流量信息,那么问题就更简单了,这里只是抛砖引玉。

本回答由提问者推荐

已赞过

已踩过<

你对这个回答的评价是?

评论

收起

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值