背景:
經過流量劫持后,我們的本機IP就成為了其他設備的網關地址。想查看別人發了什么信息、從哪里來、到哪去,勢必要進行流量分析。
又或者我實在是閑的蛋疼無聊,想看下我網卡都經過了什么流量
第一步:
獲取本機IP地址:
1 # 監聽主機(獲取本機ip) 2 host = socket.gethostbyname(socket.getfqdn(socket.gethostname()))
第二步:
創建原始套接字, 然后綁定在公開接口上。
os.name=="nt"代表windows系統,==“posix”代表linux系統
1 # 創建原始套接字, 然后綁定在公開接口上 2 if os.name == "nt": 3 socket_protocol = socket.IPPROTO_IP 4 else: 5 socket_protocol = socket.IPPROTO_ICMP 6 7 sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 8 sniffer.bind((host, 0))
第三步:
捕獲數據並設置混雜模式
1 # 設置在捕獲的數據包中包含的IP頭 2 sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 3 4 # 在windows平台上, 我們需要設置IOCTL以啟用混雜模式 5 if os.name == "nt": 6 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
第四步:
使用ip解析報文
1 class IP(Structure): 2 _fields_ = [ 3 ("ihl", c_ubyte, 4), 4 ("version", c_ubyte, 4), 5 ("tos", c_ubyte), 6 ("len", c_ushort), 7 ("id", c_ushort), 8 ("offset", c_ushort), 9 ("ttl", c_ubyte), 10 ("protocol_num", c_ubyte), 11 ("sum", c_ushort), 12 ("src", c_ulong), 13 ("dst", c_ulong) 14 ] 15 16 def __new__(self, socket_buffer=None): 17 return self.from_buffer_copy(socket_buffer) 18 19 20 def __init__(self, socket_buff=None): 21 # 協議字段與協議名稱對應 22 self.protocol_map = {1:'ICMP', 2:'IGMP', 3:'GGP', 4:'IP', 6:'TCP', 17:'UDP', 41:'IPV6'} 23 24 # 可讀性更強的ip地址 25 self.src_address = socket.inet_ntoa(struct.pack("<L", self.src)) 26 self.dst_address = socket.inet_ntoa(struct.pack("<L", self.dst)) 27 28 # 協議類型 29 try: 30 self.protocol = self.protocol_map[self.protocol_num] 31 except: 32 self.protocol = str(self.protocol_num)
完整代碼:
1 #-*- encoding:utf-8 -*- 2 ''' 3 Created on 2018年12月8日 4 5 @author: perilong 6 ''' 7 8 from ctypes import * 9 import os 10 import socket 11 import struct 12 from scapy.sendrecv import sniff 13 14 15 # IP頭定義 16 class IP(Structure): 17 _fields_ = [ 18 ("ihl", c_ubyte, 4), 19 ("version", c_ubyte, 4), 20 ("tos", c_ubyte), 21 ("len", c_ushort), 22 ("id", c_ushort), 23 ("offset", c_ushort), 24 ("ttl", c_ubyte), 25 ("protocol_num", c_ubyte), 26 ("sum", c_ushort), 27 ("src", c_ulong), 28 ("dst", c_ulong) 29 ] 30 31 def __new__(self, socket_buffer=None): 32 return self.from_buffer_copy(socket_buffer) 33 34 35 def __init__(self, socket_buff=None): 36 # 協議字段與協議名稱對應 37 self.protocol_map = {1:'ICMP', 2:'IGMP', 3:'GGP', 4:'IP', 6:'TCP', 17:'UDP', 41:'IPV6'} 38 39 # 可讀性更強的ip地址 40 self.src_address = socket.inet_ntoa(struct.pack("<L", self.src)) 41 self.dst_address = socket.inet_ntoa(struct.pack("<L", self.dst)) 42 43 # 協議類型 44 try: 45 self.protocol = self.protocol_map[self.protocol_num] 46 except: 47 self.protocol = str(self.protocol_num) 48 49 if __name__ == "__main__": 50 # 監聽主機(獲取本機ip) 51 host = socket.gethostbyname(socket.getfqdn(socket.gethostname())) 52 53 # 創建原始套接字, 然后綁定在公開接口上 54 if os.name == "nt": 55 socket_protocol = socket.IPPROTO_IP 56 else: 57 socket_protocol = socket.IPPROTO_ICMP 58 59 sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 60 sniffer.bind((host, 0)) 61 62 # 設置在捕獲的數據包中包含的IP頭 63 sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 64 65 # 在windows平台上, 我們需要設置IOCTL以啟用混雜模式 66 if os.name == "nt": 67 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 68 69 try: 70 while True: 71 # 讀取數據包 72 raw_buffer = sniffer.recvfrom(65565)[0] 73 74 # 將緩沖區前的20個字段按IP頭進行解析 75 ip_header = IP(raw_buffer[0:20]) 76 77 # 輸出協議和通信雙方ip地址 78 print "Protocol: %s %s -> %s" % (ip_header.protocol, ip_header.src_address, ip_header.dst_address) 79 80 # 出來CTRL-C 81 except KeyboardInterrupt: 82 # 如果運行在windows上,關閉混雜模式 83 if os.name == "nt": 84 sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
輸出結果:
注:家用電腦包比較單一。如果是公共場合或者公司電腦,你會發現各種各樣的協議和IP地址
參考資料: python黑帽子
協議字段---https://blog.csdn.net/zhou1021jian/article/details/80337308