背景:
经过流量劫持后,我们的本机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