BPF自己写过滤包程序

http://blog.csdn.net/maeom/article/details/6092457

BPF自己写过滤包程序

分类: linux知识学习 2256人阅读 评论(4) 收藏 举报

  BPF:Berkeley Packet Filter

  英文高手可以直接看原文:http://www.gsp.com/cgi-bin/man.cgi?section=4&topic=bpf#1

或许有一部分人会看不太懂,那么结合下面第二部分的封包结构,就会容易一些。let's go

 


 

首先,要确保我们从socket中读取的是packet,也就是说是 MAC头+IP头+TCP/UDP头,这个样子的才可以。当然,如果用linux下lpf也可以在IP包上做过滤。一样的道理。

 

BPF(Berkeley Packet Filter)
(1) 需要包含的头文件

  1. #include <sys/types.h>  
  2. #include <sys/time.h>  
  3. #include <sys/ioctl.h>  
  4. #include <net/bpf.h>  

(2) FILTER MACHINE
  1. //这个就是bpf instruction的缩写了  
  2. struct bpf_insn {  
  3.         u_short code;  
  4.         u_char  jt;  
  5.         u_char  jf;  
  6.         u_long k;  
  7. };  
  8. BPF_LD  //将值拷贝进寄存器(accumulator),没学过汇编。我就当做赋给一个变量了  
  9. BPF_LDX //将值拷贝进索引寄存器(index register)  
  10. BPF_LD+BPF_W+BPF_ABS    A <- P[k:4]     //将一个Word 即4 byte赋给寄存器(accumulator)  
  11. BPF_LD+BPF_H+BPF_ABS    A <- P[k:2]     //将一个Half Word 即2 byte赋给寄存器(accumulator)  
  12. BPF_LD+BPF_B+BPF_ABS    A <- P[k:1]     //将一个Byte 赋给寄存器(accumulator)  
  13. BPF_LD+BPF_W+BPF_IND    A <- P[X+k:4]   //偏移X寄存器后,将一个Word 即4 byte赋给寄存器(accumulator)  
  14. BPF_LD+BPF_H+BPF_IND    A <- P[X+k:2]  
  15. BPF_LD+BPF_B+BPF_IND    A <- P[X+k:1]  
  16. BPF_LD+BPF_W+BPF_LEN    A <- len        //the packet length 不知道什么意思 :(  
  17. BPF_LD+BPF_IMM          A <- k          //将常量k赋给寄存器(accumulator)  
  18. BPF_LD+BPF_MEM          A <- M[k]       //将一个Word的地址为k的内存部分赋给寄存器(accumulator)  
  19. //下面的部分是将值load进index register 大家自己理解吧  
  20. BPF_LDX+BPF_W+BPF_IMM   X <- k  
  21. BPF_LDX+BPF_W+BPF_MEM   X <- M[k]  
  22. BPF_LDX+BPF_W+BPF_LEN   X <- len  
  23. BPF_LDX+BPF_B+BPF_MSH   X <- 4*(P[k:1]&0xf)  
  24. //来看看两个宏  
  25. #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }  
  26. #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }  
  27. //关键的判断指令忘贴了  
  28. BPF_JMP+BPF_JA          pc += k  
  29. BPF_JMP+BPF_JGT+BPF_K   pc += (A > k) ? jt : jf  
  30. BPF_JMP+BPF_JGE+BPF_K   pc += (A >= k) ? jt : jf  
  31. /* 
  32.  *这个BPF_JEQ用的比较多,就拿它开刀了。 一看就知道,是用来判断是否相等的东西 
  33.  *这个会判断我们给出的数,和A(也就是accumulator寄存器)的内容是否相等, 
  34.  *结果就不用我说了,三目运算符。 
  35.  */  
  36. BPF_JMP+BPF_JEQ+BPF_K   pc += (A == k) ? jt : jf  
  37. BPF_JMP+BPF_JSET+BPF_K  pc += (A & k) ? jt : jf  
  38. BPF_JMP+BPF_JGT+BPF_X   pc += (A > X) ? jt : jf  
  39. BPF_JMP+BPF_JGE+BPF_X   pc += (A >= X) ? jt : jf  
  40. BPF_JMP+BPF_JEQ+BPF_X   pc += (A == X) ? jt : jf  
  41. BPF_JMP+BPF_JSET+BPF_X  pc += (A & X) ? jt : jf  
  42. //返回指令  
  43. BPF_RET+BPF_A           //接受 A 寄存器中的数量bytes  
  44. BPF_RET+BPF_K           //接受常量 k bytes  
  45. //下面我们就直接看个实例吧  
  46. /* 前提条件,这个filter的前提是我们抓的包是将物理层都抓下来的情况下。 
  47.  * 不懂的 物理头-IP头-TCP/UDP头 的兄弟们结合下面的图吧,方便理解与记忆。 
  48.  * 这是一个过滤TCP源端口不为79,目的端口为79的包(TCP Finger) 
  49.  */  
  50. struct bpf_insn insns[] = {  
  51.     /*物理头,偏移12byte后,指向type*/     
  52.     BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),  
  53.     /*进行比较,是否为IP协议。 true的话 0,  false 10 
  54.      *这里说一下了,由于本人没学过汇编,对这玩意开始时相当困惑。对于学过汇编的兄弟,应该是小菜吧。 
  55.      *true,则跳过0条指令执行。 就是继续执行下面的一条指令 
  56.      *false,则跳过10条指令执行。 数数!结果就数到最后一条。即BPF_STMT(BPF_RET+BPF_K, 0),就返回了 
  57.      *下面的照这个慢慢分析就OK了。 
  58.      */  
  59.     BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_IP, 0, 10),  
  60.     BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 23),  
  61.     BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 8),  
  62.     BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),  
  63.     BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 6, 0),  
  64.     BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 14),  
  65.     BPF_STMT(BPF_LD+BPF_H+BPF_IND, 14),  
  66.     BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 79, 2, 0),  
  67.     BPF_STMT(BPF_LD+BPF_H+BPF_IND, 16),  
  68.     BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 79, 0, 1),  
  69.     BPF_STMT(BPF_RET+BPF_K, (u_int)-1),  
  70.     BPF_STMT(BPF_RET+BPF_K, 0),  
  71. };  

 

下面我们来看下网络包的格式,才能对上面如何编写。温习一下网络结构

Ethernet Header

EthDHost :

Destination address (6 bytes). //目的MAC地址

EthSHost

Source address (6 bytes).

EthType

Encapsulated packet type (2 bytes). It is ETHERTYPE_IP for IP based communication.   //所承载的协议,IP协议则为ETHERTYPE_IP

 

上面为IP头格式,一行为32为,即4 bytes

 

下面来看看TCP头和UDP头

 

TCP的头这么复杂和IP头差不多了。

UDP的包头就简单多了

 

 

更多 1


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值