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 ...
随机推荐
- keystore
p12转keystorekeytool -v -importkeystore -srckeystore temp.p12 -srcstoretype PKCS12 -destkeystore temp ...
- SkylineGlobe 如何实现绘制圆形Polygon和对图层的圆形范围选择查询
//结束绘制圆形之前,得到Polygon var pos = gPolyObj.Position; var bufferR = gPolyObj.Radius; var cVerticesArray ...
- AIS系统(转)
船舶自动识别系统(Automatic Identification System, 简称AIS系统)由岸基(基站)设施和船载设备共同组成,是一种新型的集网络技术.现代通讯技术.计算机技术.电子信息显示 ...
- linux系统原子操作
一.概念 原子操作提供了指令原子执行,中间没有中断.就像原子被认为是不可分割颗粒一样,原子操作(atomic operation)是不可分割的操作. c语言中一个变量的自加1操作,看起来很简 ...
- 阿里云ubuntu 16.04搭建odoo11服务器
ubuntu 16.04 具体如何搭建odoo11网站的具体步骤可以参考这一篇文章 按上面的文章配置环境后,自己网站的启动具体步骤如下: 1.登录阿里云 [远程连接],进入命令行界面1 2.cd到目录 ...
- Bootstrap Search Suggest 下拉框模糊查询
源码地址:https://github.com/lzwme/bootstrap-suggest-plugin 有时间会完善!暂时有点忙!
- gist.github.com 被墙无法访问解决办法
windows下 打开C:\Windows\System32\drivers\etc\hosts文件 编辑器打开,在最后行添加192.30.253.118 gist.github.com 保存.
- OpenTK教程-1绘制一个三角形
OpenTK的官方文档是真心的少,他们把怎么去安装OpenTK说的很清楚,但是也就仅限于此,这有一篇learn opentk in 15的教程(链接已经失效,译者注),但是并不完美.你可以在15分钟内 ...
- Docker 小记 — Docker Engine
前言 用了 Docker 方才觉得生产环境终于有了他该有的样子,就像集装箱普及之后大型货轮的价值才逐渐体现出来,Docker 详细说明可查阅"官方文档".本篇为 Docker En ...
- Nagios监控系统部署(源码)
1. 概述2. 部署Nagios2.1 创建Nagios用户组2.2 下载Nagios和Nagios-plugin源码2.3 编译安装3. 部署Nagios-plugin3.1 编译安装nagios- ...