基于原始套接字(raw socket)的网络抓包工具

发布时间:2021-07-31 05:56:18

基于raw?socket的网络抓包工具


1.?原始套接字(raw?socket)简介


原始套接字可以接收本机网卡上的数据帧或者数据包,利用raw?socket可以编写基于IP协议的程序。一般的TCP/UDP类型的套接字只能够访问传输层以及传输层以上的数据,而原始套接字却可以访问传输层一下的数据,所以使用raw?socket既可以实现应用层的数据操作,也可以实现链路层的数据操作。


1.1 基本原理


网卡对数据帧进行硬过滤(根据网卡的模式不同采取不同的操作,如果设置了混杂模式,则不做任何过滤直接交给下一层,否则非本机mac或者广播mac的会被直接丢弃)。在进入ip层之前,系统会检查系统中是否有通过socket(AP_PACKET,SOCK_RAW,...)创建的套接字,如果有并且协议相符,系统就给每个这样的socket接收缓冲区发送一个数据帧的拷贝。如果数据的校验和出错的话,内核直接丢弃该数据包,而不会拷贝给sock_raw的套接字。


1.2原始套接字创建方式


发送接收ip数据包


socket(AF_INET,?SOCK_RAW,?IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)?


发送接收以太网数据帧?


socket(PF_PACKET,?SOCK_RAW,?htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL))?


参数说明:


1)AF_INET和PF_PACKET的区别


使用AF_INET可以接收协议类型为(tcp?udp?icmp等)发往本机的ip数据包,而使用PF_PACKET可以监听网卡上的所有数据帧。


2)SOCK_RAW、SOCK_DGRAM和SOCK_PACKET的区别


第一个参数使用PF_PACKET的时候,这三种类型都可以使用,区别在于


a)使用SOCK_RAW发送的数据必须包含链路层的协议头,接收到的数据包,包含链路层协议头。而使用SOCK_DGRAM不含链路层协议头;


b)SOCK_PACKET已经废弃,不建议使用;


c)使用这三者时,在sendto和recvfrom中使用的地址类型不同,钱两个使用sockaddr_ll类型的地址,第三个使用sockaddr类型的地址;


d)如果socket的第一个参数使用PF_INET,第二个参数使用SOCK_RAW,则可以得到原始的IP包。


3) 使用PF_PACKET和SOCK_RAW时,第三个参数说明


ETH_P_IP??0x800??????只接收发往本机mac的ip类型的数据帧


ETH_P_ARP?0x806??????只接受发往本机mac的arp类型的数据帧


ETH_P_ARP?0x8035?????只接受发往本机mac的rarp类型的数据帧


ETH_P_ALL?0x3????????接收发往本机mac的所有类型ip?arp?rarp的数据帧,接收从本机发出的所有类型的数据帧。(混杂模式打开的情况下,会接收到非发往本地mac的数据帧)


2.?raw?socket编程


1)创建套接字


sock?=?socket(PF_PACKET,?SOCK_RAW,?htons(ETH_P_ALL));


使用ETH_P_ALL表示接收所有类型的数据帧(ip,arp,rarp)。


2)设置网卡混杂模式


正常情况下,网卡只响应两种数据帧:一种是与自己mac地址相匹配的数据帧;另一种是发向所有机器的广播数据帧。如果网卡要接收所有通过它的数据,而不管是不是发给它的,就必须把网卡置于混杂模式。


struct?ifreq?ethreq;


strncpy(ethreq.ifr_name,?"eth0",?IFNAMSIZ);


ethreq.ifr_flags?|=?IFF_PROMISC;


ioctl(sock,?SIOCGIFFLAGS,??req);


3)设置BPF过滤器


通过前面的设置,可以收到所有的数据帧,但是因为数据帧太多,数据量太大,cpu可能被严重占用,然而很多数据帧,程序处理的时候根本不关心。如果只是接收到数据帧之后用if等判断的话,那将会很麻烦,而且判断太多也降低了反应效率。另一种方法就是通过内核处理,设置过滤器把不需要的数据过滤掉。


在使用libpcap编写网络抓包工具时,就用到了BPF过滤器,因为libpcap已经封装好了,只用将过滤表达式如“port?80”指定就可以由libpcap传到内核进行相应的BPF解码从而过滤掉不需要的数据。而使用raw?socket就没有这么方便,但是tcpdump提供了一个选项-dd,可以将一段过滤表达式生成为等效的c代码,如#tcpdump?-dd?port?80,生成结果如下


{?0x28,?0,?0,?0x0000000c?},


{?0x15,?0,?12,?0x00000800?},


{?0x30,?0,?0,?0x00000017?},


{?0x15,?2,?0,?0x00000084?},


{?0x15,?1,?0,?0x00000006?},


{?0x15,?0,?8,?0x00000011?},


{?0x28,?0,?0,?0x00000014?},


{?0x45,?6,?0,?0x00001fff?},


{?0xb1,?0,?0,?0x0000000e?},


{?0x48,?0,?0,?0x0000000e?},


{?0x15,?2,?0,?0x00000050?},


{?0x48,?0,?0,?0x00000010?},


{?0x15,?0,?1,?0x00000050?},


{?0x6,?0,?0,?0x00000060?},


{?0x6,?0,?0,?0x00000000?},


这段代码对应的数据结构是struct?sock_filter,定义如下


struct?sock_filter??//?Filter?block


?{


????????__u16?code;?//?Actual?filter?code


????????__u8?jt;????//?Jump?true


????????__u8?jf;????//?Jump?false


????????__u32?k;???//?Generic?multiuse?field


?};


code对应命令代码;jt是jump?if?true后面的操作数,注意这里用的是相对行偏移,如2就表示向前跳转2行,而不像伪代码中使用绝对行号;jf为jump?if?false后面的操作数;k对应伪代码中第3列的操作数。


对应的代码中实现如下


struct?sock_filter?BPF_code[]?=?{


????????{?0x28,?0,?0,?0x0000000c?},


????????{?0x15,?0,?12,?0x00000800?},


????????{?0x30,?0,?0,?0x00000017?},


????????{?0x15,?2,?0,?0x00000084?},


????????{?0x15,?1,?0,?0x00000006?},


????????{?0x15,?0,?8,?0x00000011?},


????????{?0x28,?0,?0,?0x00000014?},


????????{?0x45,?6,?0,?0x00001fff?},


????????{?0xb1,?0,?0,?0x0000000e?},


????????{?0x48,?0,?0,?0x0000000e?},


????????{?0x15,?2,?0,?0x00000050?},


????????{?0x48,?0,?0,?0x00000010?},


????????{?0x15,?0,?1,?0x00000050?},


????????{?0x6,?0,?0,?0x0000ffff?},


????????{?0x6,?0,?0,?0x00000000?},


????????};


struct?sock_fprog?Filter;


Filter.len?=?15;


Filter.filter?=?BPF_code;


setsockopt(sock,?SOL_SOCKET,?SO_ATTACH_FILTER,?&Filter,?sizeof(Filter));


需要注意的是,因为tcpdump默认只返回96字节的数据,所以数据帧里的数据将有大部分被去掉,这样在分析数据包的时候就会因为数据不全导致分析出错,因此在生成BPF代码时,需要用tcpdump?-s指定返回的数据长度。采用“tcpdump?-dd?-s?0?port?80”,其中-s?0表示返回完整的数据包。


4)接收数据进行处理


?while?(1)?{


//最后两个参数置为NULL,表示不绑定地址,来了的数据包都接收


????????????????len?=?recvfrom(sock,?buffer,?BUF_SIZE,?0,?NULL,?NULL);


????????????????analyze_packet(buffer,?len);


????????}


处理数据帧的时候,先要解析出以太网头,IP头,tcp头,然后剩下的就是数据,再对数据作处理。


Ethernet head

?| ?IP?head

?| ?TCP?head

?| ?data


3.?统*峁〉挠呕髡


1)结果会偏小的原因


采用raw?socket,是直接由网卡向socket接收缓冲区发数据副本,如果应用程序从socket缓冲区中取出数据,进行处理的效率不高,将可能会造成socket接收缓冲器来不及接收新到来的数据,从而丢失部分数据。


2)调整socket?接收缓存大小


通过getsockopt可以获得socket的当前接收和发送缓存的大小,我的程序中获取出来的发送和接收缓存都是262144字节(256KB)。采用默认的接收缓存大小的测试结果中可能会出现文件大小偏小。


使用setsockopt设置接收缓存的大小为2*1024*1024字节(2M,已经很大了),然后再多次测试,基本上没有结果偏小的情况,但是有时会出现结果偏大(重传以及选择性重传过滤不完全,内容有交叠导致的)


3)使用内存cache


预先申请一块内存,作为内存池,然后每次到来的数据包先存放到内存池中,创建一个线程,负责从内存池中取包数据,进行数据包分析,仍采用默认的接收缓存大小,测试结果可以看出使用了cache,丢失的数据比没有使用cache的少了,但是仍然存在丢失,效果没有增大socket接收缓存好,说明了该程序中的缓存带来的效果不及系统的socket缓存效果。


相关文档

  • 戴尔笔记本哪些程序可以关掉
  • 2020年吉林提前批艺术类第三轮征集志愿计划
  • Nginx + fail2ban 提高安全性
  • 2020年春季卫生保健工作计划
  • 【JDk源码解析之一】ArrayList源码解析
  • 2017年交通违章处罚标准大全
  • C语言实现哈希表查找算法
  • 诸葛亮六出祁山的原因是什么
  • 苹果手机正规批发渠道
  • 四年级数学下册期末试卷浙教版
  • 商务日语完美进行演讲的重点
  • 一年级数学上册期末考试复习练习题
  • 老虎的画法步骤儿童画绘画教程
  • 结婚绣球怎么绑
  • 汗牛充栋的反义词
  • 小学生心理健康手抄报资料图片
  • 在java接口中可以定义抽象方法_Java 接口中定义抽象方法有什么意义
  • 我最喜欢的音乐摇滚乐
  • 人间处处有真情高一作文
  • 虚拟主机服务合同模板通用版
  • 深信服面试之 活下去
  • 两个人一个望东一个望西打一成语
  • 开学第一课节目之信念篇素材
  • 广州机场托运常识
  • 大学生组织部工作总结_个人工作总结
  • 冒泡排序法 插入排序法 选择排序法 归并排序法 堆排序法(javascript实现)
  • vivonex黑屏开不了机
  • 王昌龄从军行其三
  • 手机屏翘起来了危险吗
  • 浅谈影响百度快照每天更新的几个原因
  • 猜你喜欢

  • 熬夜整理Alibaba10万字详细Java面试笔记(带完整目录) 良心分享
  • 之江学院学生不参加大学生医保承诺书
  • 小学三年级上学期数学《商末尾有0的除法》优质课PPT课件
  • 届男女混合排球竞赛规程
  • 2019-2020年湘版美术二年级上册全套表格式教案教学设计
  • 初中校园安全提示语
  • 新版2019-2020年幼儿园小班(下册)期末测试试卷附答案
  • 观佛陀身相,修寂止
  • 做一名智慧的幼儿教师(课堂PPT)
  • 2014年中国家用清洁卫生电器具制造行业福建省南*市TOP10企业排名
  • 第7章实验数据处理
  • 学前比较教育自考辅导
  • 2020年高考数学模拟试卷(文科17
  • 结婚户口本身份证地址不一样怎么办
  • 2020版高考数学大二轮专题突破文科通用版 课件:7.4.3 圆锥曲线中的定点、定值与存在性问题
  • 2018-2019年岢岚县西街实验小学一年级上册数学模拟月考无答案
  • 历史趣谈大禹传位启的背后因素 私有制形成有继承的价值
  • 保安队长工作小结
  • 花开了,就感谢读后感
  • 新学期主题手抄报资料
  • 绍兴市上虞佳舜制冷配件有限公司企业信息报告-天眼查
  • 六一儿童节乡镇领导讲话
  • 高企申报资料清单
  • 泡绿豆连续观察日记范文
  • 克什克腾旗旱地优质春小麦高产栽培技术探讨
  • 无声的爱_400字
  • 中冶天工集团有限公司青岛分公司企业信用报告-天眼查
  • 李白七言诗有哪些
  • 关于医院麻醉药品管理现状的研究
  • 公司5月团队建设活动方案
  • 浅析在建筑结构设计中如何提高建筑安全性
  • 保险公司士气展示口号
  • 声色动人!《遗迹守望者》原声音乐抢鲜听
  • Synthesis Crystal Structure and Antitumor Activity of (E)-1-(7-Methoxy-22-dimethyl-2
  • 关于友谊与爱情的经典名人名言-名人名言
  • 2012年北京市中级职称考试《电气专业基础与实务》考试题
  • 2020年春人教版通用九年级语文下册作业课件18.天下第一楼(节选)
  • 教育随笔:如何使幼儿适应幼儿园生活
  • 网格化管理模式在高校学生管理工作中的应用探究
  • 重阳节登山作文600字
  • 《机械原理》课件第1章绪论-精选文档
  • 公司组织架构图(最新)
  • 电脑版