抓包

使用 raw socket 进行网络底层抓包,想必大家都清楚(仔细想想tcpdump原理)。这里不赘述,网上许多资料。
注意,网卡需要开启混杂模式、其次程序运行需要root权限。

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>unsigned char buffer[102];
void main()
{int fd, n, i;fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));if (fd < 0 ) {perror("socket fail\n");exit(1);}/*block*/n = recvfrom(fd, buffer, sizeof(buffer), 0, NULL, NULL);if (n < 0) {perror("recvfrom none\n");exit(1);}for (i = 0; i < n ;i++) {printf("%02x ", buffer[i]);}
}

希望能够过滤

法1:抓所有的包,在用户态recvfrom后,自己使用代码逻辑进行过滤。
法2:告诉底层 raw socket, 哪些包是自己想要的,直接在底层被过滤掉。

法1,行得通,但是性能肯定扛不住,所有的包需要从内核拷贝至用户态,这个消耗巨大。
法2,即使用bpf。

首先,获得 过滤规则 对应的的bpf code。比如,我想过滤端口为 9090 的tcp报文,使用tcpdump的-dd参数,就能获得。

$sudo  tcpdump -dd -i eth0 tcp port 9090 -s 0
{ 0x28, 0, 0, 0x0000000c },
{ 0x15, 0, 6, 0x000086dd },
{ 0x30, 0, 0, 0x00000014 },
{ 0x15, 0, 15, 0x00000006 },
{ 0x28, 0, 0, 0x00000036 },
{ 0x15, 12, 0, 0x00002382 },
{ 0x28, 0, 0, 0x00000038 },
{ 0x15, 10, 11, 0x00002382 },
{ 0x15, 0, 10, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 8, 0x00000006 },
{ 0x28, 0, 0, 0x00000014 },
{ 0x45, 6, 0, 0x00001fff },
{ 0xb1, 0, 0, 0x0000000e },
{ 0x48, 0, 0, 0x0000000e },
{ 0x15, 2, 0, 0x00002382 },
{ 0x48, 0, 0, 0x00000010 },
{ 0x15, 0, 1, 0x00002382 },
{ 0x6, 0, 0, 0x00040000 },
{ 0x6, 0, 0, 0x00000000 },

使用bpf code

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>#include <linux/filter.h>unsigned char buffer[102];
void main()
{int fd, n, i;struct sock_fprog filter;struct sock_filter code[] = {{ 0x28, 0, 0, 0x0000000c },{ 0x15, 0, 6, 0x000086dd },{ 0x30, 0, 0, 0x00000014 },{ 0x15, 0, 15, 0x00000006 },{ 0x28, 0, 0, 0x00000036 },{ 0x15, 12, 0, 0x00002382 },{ 0x28, 0, 0, 0x00000038 },{ 0x15, 10, 11, 0x00002382 },{ 0x15, 0, 10, 0x00000800 },{ 0x30, 0, 0, 0x00000017 },{ 0x15, 0, 8, 0x00000006 },{ 0x28, 0, 0, 0x00000014 },{ 0x45, 6, 0, 0x00001fff },{ 0xb1, 0, 0, 0x0000000e },{ 0x48, 0, 0, 0x0000000e },{ 0x15, 2, 0, 0x00002382 },{ 0x48, 0, 0, 0x00000010 },{ 0x15, 0, 1, 0x00002382 },{ 0x6, 0, 0, 0x00040000 },{ 0x6, 0, 0, 0x00000000 },};filter.len = sizeof(code)/sizeof(struct sock_filter); filter.filter = code;fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));if (fd < 0 ) {perror("socket fail\n");exit(1);}//设置 sk_filterif (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) < 0) {perror("setsockopt fail\n"); exit(1);   }/*block*/n = recvfrom(fd, buffer, sizeof(buffer), 0, NULL, NULL);if (n < 0) {perror("recvfrom none\n");exit(1);}for (i = 0; i < n ;i++) {printf("%02x ", buffer[i]);}
}

此时运行程序,只有9090端口的tcp报文到达本机,recvfrom才会返回。

原理

net/packet/af_packet.c

static int packet_rcv(struct sk_buff *skb, struct net_device *dev,struct packet_type *pt, struct net_device *orig_dev)
{........res = run_filter(skb, sk, snaplen);if (!res)goto drop_n_restore;

在包被raw socket处理时,会执行run_filter,而这过滤规则正是 上文 tcpdump输出的code,这些code由bpf解释程序运行。

实际上,可议使用tcpdump -d查看具体code的行为,如下,类似汇编语言,相对而言可读性高一点了(当然前提你需要熟悉二三层协议)。

$sudo  tcpdump -d -i eth0 tcp port 9090 -s 0
(000) ldh      [12]                                                     #加载12字节后的自己,即偏去6字节的smac 和 dmac
(001) jeq      #0x86dd          jt 2    jf 8                            # 如果 网络层类型不是0x86dd(IPV6),则跳转到 8
(002) ldb      [20]
(003) jeq      #0x6             jt 4    jf 19
(004) ldh      [54]
(005) jeq      #0x2382          jt 18   jf 6
(006) ldh      [56]
(007) jeq      #0x2382          jt 18   jf 19
(008) jeq      #0x800           jt 9    jf 19                           #如果 网络层类型不是0x0800(IPV4),则跳转到 19,不处理
(009) ldb      [23]                                                         #ip头中的protocol字段
(010) jeq      #0x6             jt 11   jf 19                           #不是6表示不是tcp,不处理
(011) ldh      [20]
(012) jset     #0x1fff          jt 19   jf 13                           #检测是否是ip分片,是的就不处理
(013) ldxb     4*([14]&0xf)                                             #ip头中的length字段,偏过这个长度,就是tcp头
(014) ldh      [x + 14]
(015) jeq      #0x2382          jt 18   jf 16                           #0x2382  是9090.匹配sport是否是9090
(016) ldh      [x + 16]
(017) jeq      #0x2382          jt 18   jf 19                           #0x2382  是9090.匹配dport是否是9090
(018) ret      #262144
(019) ret      #0

raw socket 使用 BPF 过滤报文相关推荐

  1. BPF高阶 - 使用BPF过滤固定特征报文

    这篇文章主要介绍如何使用BPF过滤固定特征报文 参考文章:https://www.freebsd.org/cgi/man.cgi?query=bpf&sektion=4&manpath ...

  2. Raw Socket编程

    原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGRAM的套接字,它实现于系统核心.然而,原始套接字能做什么呢?首 先来说,普通的套接字无法处理ICMP.IGMP等网络报 ...

  3. linux raw socket 例子,raw socket编程例子

    raw socket编程例子内容安排: 1.原始套接字介绍 1.1 原始套接字工作原理与规则 1.2 简单应用 2 FTP密码窃取器实现(简单的rootkit) 2.1 设计思路 2.2 实现 2.3 ...

  4. Linux小知识--原始套接字(raw socket)之模拟ping

    原始套接字-raw socket 最近在研究高并发下扫描存活主机,基本想法是通过socket来模拟ICMP报文,然后就发现了socket的一片新天地----原始套接字(raw socket). raw ...

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

    基于raw socket的网络抓包工具 1. 原始套接字(raw socket)简介 原始套接字可以接收本机网卡上的数据帧或者数据包,利用raw socket可以编写基于IP协议的程序.一般的TCP/ ...

  6. python实现syn半扫描_python 使用raw socket进行TCP SYN扫描实例

    1. TCP SYN扫描 端口扫描常用于用于探测服务器或主机开放端口情况,被计算机管理员用于确认安全策略,同时被攻击者用于识别目标主机上的可运作的网络服务.端口扫描是向一定范围的服务器端口发送对应请求 ...

  7. RAW SOCKET探索

    在Linux实现抓取以太网络上的数据包主要有libpcap,raw socket以及从内核中获取的方式. 我尝试选择使用raw socket来抓取以太网络上的数据包. 一.socket地址域(协议簇) ...

  8. 关于windows xp sp2/sp3 中tcpip.sys对于Raw socket的限制

    WINDOWS XP SP2修改了TCPIP.SYS,增加了对于RAW SOCKET的发送和伪造源地的限制,详情如下 : 1) 不能通过raw socket发送TCP报文.做此尝试时会得到10004号 ...

  9. linux raw限制端口访出,使用Linux raw socket时需要注意的一些问题

    本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载.但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途. 作者:gfree.win ...

  10. 用C#的Raw Socket实现网络封包监视

    <script language="javascript" src="/ad/js/edu_left_300-300.js" type="tex ...

最新文章

  1. Xilinx zynq的资料获取总结
  2. 用Groovy思考 第一章 用Groovy简化Java代码
  3. 欠阿里云一分钱,会是什么样的后果。。。
  4. Qt之QLineEdit详解(附源码)
  5. spring+redis自主实现分布式session(非spring-session方式)
  6. java 关于JDBC和DAO模式使用
  7. php相册上传和删除吗,php上传与删除图片的简单范例
  8. 2018北理复试机试题
  9. Linux虚拟文件系统(节点路径搜索)
  10. 【聚沙成塔】将Mon Jun 01 2020 00:00:00 GMT+0800 (中国标准时间) 转换为 2020-06
  11. 电脑版我的世界java_我的世界pc JAVA版
  12. matlab谐波分析fft,fft谐波分析_matlab进行fft谐波分析_交流电谐波?
  13. apple script to 1s screen capture snapshot w/ windowsill
  14. git bash批量dos2unix
  15. 机器学习与数据挖掘 编程实现k均值算法
  16. 选择小程序的8大理由,让你拒绝说No
  17. 麋鹿微博工具箱 · 批量删除微博、设置仅自己可见、仅好友可见等
  18. 根据输入的三角形的三条边a、b、c,如果可以构成三角形,计算并输出该三角形的面积和周长,否则输出“Not a Valid Triangle”。
  19. 【游戏设计】3D坦克大战
  20. 替代人工操作,模拟浏览器的“行为”

热门文章

  1. 起来吧!不要做奴隶的ITproject师们!
  2. asp.net gridview添加删除确认对话框
  3. IE8的样式兼容性适应方法【转】
  4. python中avg函数的使用_PostgreSQL avg()函数
  5. CentOS7 网络配置--NAT模式
  6. 流媒体技术笔记(DarwinStreamingServer相关)
  7. struts标签logic:iterate的用法
  8. Postgresql 插入json数据
  9. 虚拟桌面与代理服务器的那些事
  10. 如何设置mysql数据库连接池的大小