python使用原始套接字 解析原始ip头数据
使用底层套接字解码底层流量,是这次做的重点工作。
首先来捕获第一个包
# coding:utf-8import socket # 监听的主机IP
host = "192.168.1.100" socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) raw_buffer = sniffer.recvfrom(65535)
print raw_buffer
下面一行一行解释上面代码的意思。
1. 导入socket包
2. 需要监听的本机ip地址
3. 给socket_protocol变量赋值icmp变量
4. 为sniffer变量创建一个soket对象,该对象为ipv4 原始套接字并指定其协议为icmp
5. 绑定到指定地址和端口进行监听
6. 为sniffer套接字设置选项参数,使其携带ip头
7. 将监听端口的套接字收到的原始数据赋值给raw_buffer
8. 打印raw_buffer的值
这个时候,我们使用root权限运行这个脚本,并且开启另外一个terminal对任意一个地址发送icmp包,我们监听的接口的recvfrom 会收到回监听回包到指定地址。recvfrom与recv不同的是 recvfrom会同时接收回包地址。(string, address)的格式
这个时候我们可以看到打印出来的值,是一堆完全看不懂的东西,因为是没有解码的状态,下面我们将对ip头进行解码。
使用python的struct和ctypes两个库实现这一点。
# coding:utf-8import socket
import struct
from ctypes import * # 监听的主机IPhost = "192.168.1.100" # IP头定义
class IP(Structure):
_fields_ = [
("ihl", c_ubyte, 4),
("version", c_ubyte, 4),
("tos", c_ubyte),
("len", c_ushort),
("id", c_ushort),
("offset", c_ushort),
("ttl", c_ubyte),
("protocol_num", c_ubyte),
("sum", c_ushort),
("src", c_uint),
("dst", c_uint),
] def __new__(self, socket_buffer=None):
return self.from_buffer_copy(socket_buffer) def __init__(self, socket_buffer=None):
self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"} # readable ip address
self.src_address = socket.inet_ntoa(struct.pack("<I", self.src))
self.dst_address = socket.inet_ntoa(struct.pack("<I", self.dst)) # type of protocol
try:
self.protocol = self.protocol_map[self.protocol_num]
except:
self.protocol = str(self.protocol_num) socket_protocol = socket.IPPROTO_ICMP sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) try:
while True:
raw_buffer = sniffer.recvfrom(65535)[0] ip_header = IP(raw_buffer[:20]) print "Protocol: %s %s -> %s " % (ip_header.protocol, ip_header.src_address, ip_header.dst_address) except KeyboardInterrupt:
pass
1. 导入各模块
2. 监听的本机ip地址
3. 使用ctypes 构造一个解析ip头的结构体(structure) IP
4. 使用from_buffer_copy方法在__new__方法将收到的数据生成一个IP class的实例
5. __init__方法初始化一部分数据保存到对应的实例属性值中。
6. 特别说明下面代码, 使用了python struct库的pack方法 用指定的格式化参数将src 和dst的long型数值转换为字符串,然后使用socket.inet_ntoa方法将字符串的一串数字转换为对应的ip格式。最后赋值给对应的src或者dst变量
# readable ip address
self.src_address = socket.inet_ntoa(struct.pack("<I", self.src))
self.dst_address = socket.inet_ntoa(struct.pack("<I", self.dst))
7. 一个接收icmp包的服务器,没什么说的。
8. 无限循环监听指定端口,将recvfrom收到的数据的第一部分 也就是不要ip地址的部分传递给raw_buffer
9. ip头raw_buffer的前20个字节传递给结构体进行解码。
10. 然后打印。
可以看到大致思路就是,将原型socket数据拿过来,然后通过模拟c语言的结构体,使用python的库对这个格式的包进行一一对应的解码,将解码之后的数据打印出来。
到此为止可以看到,在ip层已经可以解析出数据包从哪儿去哪儿的信息。
python使用原始套接字 解析原始ip头数据的更多相关文章
- C++ Win 32 使用原始套接字获取所有ip数据包并分析(包括ping包)
/*页面编码:GBK 开发环境 VS2019 */ #define _WINSOCK_DEPRECATED_NO_WARNINGS#include <iostream>#include&l ...
- Linux原始套接字实现分析---转
http://blog.chinaunix.net/uid-27074062-id-3388166.html 本文从IPV4协议栈原始套接字的分类入手,详细介绍了链路层和网络层原始套接字的特点及其内核 ...
- Linux基础(11)原始套接字
一边接收函数返回一边判断返回值时一定要把接收的优先级加()提高再去判断 例 if((sockfd = socket()) < 0) 问题: 如何实现SYN扫描器扫描端口 , 比如AB两个设备要进 ...
- Linux Socket 原始套接字编程
对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...
- Linux系统编程(37)—— socket编程之原始套接字
原始套接字的特点 原始套接字(SOCK_RAW)可以用来自行组装IP数据包,然后将数据包发送到其他终端.也就是说原始套接字是基于IP数据包的编程(SOCK_PACKET是基于数据链路层的编程).另外, ...
- 关于linux 原始套接字编程
关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...
- 浅谈原始套接字 SOCK_RAW 的内幕及其应用(port scan, packet sniffer, syn flood, icmp flood)
一.SOCK_RAW 内幕 首先在讲SOCK_RAW 之前,先来看创建socket 的函数: int socket(int domain, int type, int protocol); domai ...
- Linux网络编程——原始套接字编程
原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据.区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有 ...
- Linux网络编程——原始套接字能干什么?
通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...
随机推荐
- VsCode插件开发之插件初步通信
参考了Egret Wing,想像Egret Wing那样在上方titlebar最右边上面增加一个menu(这个menu相对于一个按钮,当点击这个按钮时会出现一个window弹框,这个window弹框里 ...
- vue v-for 遍历循环时的key值的报错
问题如下: [Vue warn] Avoid using non-primitive value as key, use string/number value instead. non-primit ...
- 1002-过河卒-洛谷-luogu-动态规划dp
题目描述 棋盘上AA点有一个过河卒,需要走到目标BB点.卒行走的规则:可以向下.或者向右.同时在棋盘上CC点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒 ...
- Ubuntu最新的主要操作系统放弃32位支持?
导读 现在是2018年,2019年即将到来——64位处理器已经成为主流很长一段时间了.如果你仍然使用32位的电脑,那么是时候把它扔进垃圾箱了. 我为所有基于Linux的操作系统维护者感到自豪,他们有勇 ...
- Git使用—第一讲:初识版本控制工具
几乎所有出色的项目都不是一个人完成的,而是由一个团队共同合作开发完成的,这个时候多人之间的代码同步问题就显得异常重要了,因此版本控制工具也就应运而生了.常见的版本控制工具主要有SVN和Git,接下来要 ...
- Android学习之基础知识五—RecyclerView(滚动控件)
RecyclerView可以说是增强版的ListView,不仅具有ListVIew的效果,还弥补许多ListView的不足. 一.RecyclerView的基本用法 与百分比布局类似,Recycler ...
- 『转』统计一个日志文件里,单词出现频率的shell脚本
原文地址:http://blog.csdn.net/taiyang1987912/article/details/39995175 #查找文本中n个出现频率最高的单词 #!/bin/bash coun ...
- LOJ540 游戏 构造
传送门 题意:给出$N$,试构造一个点数小于$500$的图,使得其中三元环的个数恰好为$N$.$N \leq 2 \times 10^6$ 首先构造一个尽可能大的完全图,然后在这个完全图旁边加点.尽可 ...
- ionic Cannot find module 'internal/fs'问题
最近升级了node.js到7.3.0之后,在用cordoval add plugin XXX 命令安装插件的时候报"Cannot find module 'internal/fs'" ...
- Linux下部署SSH登录时的二次身份验证环境记录(利用Google Authenticator)
一般来说,使用ssh远程登录服务器,只需要输入账号和密码,显然这种方式不是很安全.为了安全着想,可以使用GoogleAuthenticator(谷歌身份验证器),以便在账号和密码之间再增加一个验证码, ...