使用netfilter框架处理ARP报文
2018-03-31 19:19
931 查看
利用netfilter的框架实现对arp报文的处理,这里只是打印arp报文信息,更多的处理可以在此基础上实现。
arp 首部封装格式:
内核版本 :
,
不同版本内核头文件可能不一样带来编译出错问题,可以参考这篇博客https://blog.csdn.net/fuyuande/article/details/79429441 更新一下内核。
源码如下:/*
* Description : print arp packet info
* Date : 20180331
* Author : fuyuande
* Note : Kernel version 3.4.39
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_arp.h>
#define LOG(fmt,arg...) printk("[%s %d] "fmt,__FUNCTION__,__LINE__,##arg)
#pragma pack(push,1)
struct arp_info {
unsigned char src[ETH_ALEN];
__be32 srcip;
unsigned char dst[ETH_ALEN];
__be32 dstip;
};
#pragma pack(pop)
#define IP1(addr) ((unsigned char *)&addr)[0]
#define IP2(addr) ((unsigned char *)&addr)[1]
#define IP3(addr) ((unsigned char *)&addr)[2]
#define IP4(addr) ((unsigned char *)&addr)[3]
static unsigned int arp_input_hook(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct ethhdr * ethh = NULL;
ethh = eth_hdr(skb);
if(ethh == NULL)
{
return NF_ACCEPT;
}
LOG(" L3 type :%x \r\n",ethh->h_proto);
return NF_ACCEPT;
}
static unsigned int arp_output_hook(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct arphdr *arph = NULL;
struct arp_info *arpinfo = NULL;
arph = arp_hdr(skb);
if(arph == NULL)
{
LOG("Weird! arp header null \r\n");
return NF_ACCEPT;
}
LOG(" arp info :\r\n"
"-------------\r\n"
"arp hw type :%x \r\n"
"arp pro type :%x \r\n"
"arp hln :%d\r\n"
"arp plen:%d\r\n"
"arp ops :%d\r\n"
"-------------\r\n",
ntohs(arph->ar_hrd),ntohs(arph->ar_pro),arph->ar_hln,arph->ar_pln,ntohs(arph->ar_op));
arpinfo = (unsigned char *)(arph + 1);
LOG("\n-------------\r\n"
"mac : %x:%x:%x:%x:%x:%x \r\n"
"sip : %d:%d:%d:%d \r\n"
"dmac : %x:%x:%x:%x:%x:%x \r\n"
"dip : %d:%d:%d:%d \r\n"
"-------------\r\n",
arpinfo->src[0],arpinfo->src[1],arpinfo->src[2],arpinfo->src[3],arpinfo->src[4],arpinfo->src[5],
IP1(arpinfo->srcip),IP2(arpinfo->srcip),IP3(arpinfo->srcip),IP4(arpinfo->srcip),
arpinfo->dst[0],arpinfo->dst[1],arpinfo->dst[2],arpinfo->dst[3],arpinfo->dst[4],arpinfo->dst[5],
IP1(arpinfo->dstip),IP2(arpinfo->dstip),IP3(arpinfo->dstip),IP4(arpinfo->dstip));
return NF_ACCEPT;
}
struct nf_hook_ops arp_hook_ops[] ={
{
.hook = arp_input_hook,
.pf = NFPROTO_ARP,
.hooknum = NF_ARP_IN,
.priority = 0,
},
{
.hook = arp_output_hook,
.pf = NFPROTO_ARP,
.hooknum = NF_ARP_OUT,
.priority = 0,
},
{}
};
static int __init arp_hook_init(void)
{
nf_register_hooks(arp_hook_ops,ARRAY_SIZE(arp_hook_ops));
return 0;
}
static void __exit arp_hook_exit(void)
{
nf_unregister_hooks(arp_hook_ops,ARRAY_SIZE(arp_hook_ops));
return ;
}
module_init(arp_hook_init)
module_exit(arp_hook_exit)
MODULE_LICENSE("GPL");
Makefile:obj-m := arphook.o
PWD :=$(shell pwd)
KERNEL_DIR :="/usr/src/linux-headers-3.4.39-030439-generic/"
modules:
$(MAKE) -C $(KERNEL_DIR) M=${PWD} modules
clean:
@rm *.ko *.mod.c *.o Modu* modu*
在内核3.4.39版本上可以直接执行如下命令编译、加载#编译模块
sudo make
#加载模块
sudo insmod arphook.ko
#卸载模块
sudo rmmod arphook.ko效果如下:
一开始钩子函数注册在PF_INET上,没有抓到ARP报文,后来查了查,发现协议注册错了,更改成NFPROTO_ARP就可以。
arp 首部封装格式:
内核版本 :
,
不同版本内核头文件可能不一样带来编译出错问题,可以参考这篇博客https://blog.csdn.net/fuyuande/article/details/79429441 更新一下内核。
源码如下:/*
* Description : print arp packet info
* Date : 20180331
* Author : fuyuande
* Note : Kernel version 3.4.39
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_arp.h>
#define LOG(fmt,arg...) printk("[%s %d] "fmt,__FUNCTION__,__LINE__,##arg)
#pragma pack(push,1)
struct arp_info {
unsigned char src[ETH_ALEN];
__be32 srcip;
unsigned char dst[ETH_ALEN];
__be32 dstip;
};
#pragma pack(pop)
#define IP1(addr) ((unsigned char *)&addr)[0]
#define IP2(addr) ((unsigned char *)&addr)[1]
#define IP3(addr) ((unsigned char *)&addr)[2]
#define IP4(addr) ((unsigned char *)&addr)[3]
static unsigned int arp_input_hook(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct ethhdr * ethh = NULL;
ethh = eth_hdr(skb);
if(ethh == NULL)
{
return NF_ACCEPT;
}
LOG(" L3 type :%x \r\n",ethh->h_proto);
return NF_ACCEPT;
}
static unsigned int arp_output_hook(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct arphdr *arph = NULL;
struct arp_info *arpinfo = NULL;
arph = arp_hdr(skb);
if(arph == NULL)
{
LOG("Weird! arp header null \r\n");
return NF_ACCEPT;
}
LOG(" arp info :\r\n"
"-------------\r\n"
"arp hw type :%x \r\n"
"arp pro type :%x \r\n"
"arp hln :%d\r\n"
"arp plen:%d\r\n"
"arp ops :%d\r\n"
"-------------\r\n",
ntohs(arph->ar_hrd),ntohs(arph->ar_pro),arph->ar_hln,arph->ar_pln,ntohs(arph->ar_op));
arpinfo = (unsigned char *)(arph + 1);
LOG("\n-------------\r\n"
"mac : %x:%x:%x:%x:%x:%x \r\n"
"sip : %d:%d:%d:%d \r\n"
"dmac : %x:%x:%x:%x:%x:%x \r\n"
"dip : %d:%d:%d:%d \r\n"
"-------------\r\n",
arpinfo->src[0],arpinfo->src[1],arpinfo->src[2],arpinfo->src[3],arpinfo->src[4],arpinfo->src[5],
IP1(arpinfo->srcip),IP2(arpinfo->srcip),IP3(arpinfo->srcip),IP4(arpinfo->srcip),
arpinfo->dst[0],arpinfo->dst[1],arpinfo->dst[2],arpinfo->dst[3],arpinfo->dst[4],arpinfo->dst[5],
IP1(arpinfo->dstip),IP2(arpinfo->dstip),IP3(arpinfo->dstip),IP4(arpinfo->dstip));
return NF_ACCEPT;
}
struct nf_hook_ops arp_hook_ops[] ={
{
.hook = arp_input_hook,
.pf = NFPROTO_ARP,
.hooknum = NF_ARP_IN,
.priority = 0,
},
{
.hook = arp_output_hook,
.pf = NFPROTO_ARP,
.hooknum = NF_ARP_OUT,
.priority = 0,
},
{}
};
static int __init arp_hook_init(void)
{
nf_register_hooks(arp_hook_ops,ARRAY_SIZE(arp_hook_ops));
return 0;
}
static void __exit arp_hook_exit(void)
{
nf_unregister_hooks(arp_hook_ops,ARRAY_SIZE(arp_hook_ops));
return ;
}
module_init(arp_hook_init)
module_exit(arp_hook_exit)
MODULE_LICENSE("GPL");
Makefile:obj-m := arphook.o
PWD :=$(shell pwd)
KERNEL_DIR :="/usr/src/linux-headers-3.4.39-030439-generic/"
modules:
$(MAKE) -C $(KERNEL_DIR) M=${PWD} modules
clean:
@rm *.ko *.mod.c *.o Modu* modu*
在内核3.4.39版本上可以直接执行如下命令编译、加载#编译模块
sudo make
#加载模块
sudo insmod arphook.ko
#卸载模块
sudo rmmod arphook.ko效果如下:
一开始钩子函数注册在PF_INET上,没有抓到ARP报文,后来查了查,发现协议注册错了,更改成NFPROTO_ARP就可以。
相关文章推荐
- Adhesive框架系列文章--报警处理流程使用实践
- android游戏开发框架libgdx的使用(十四)—TiledMap中视角完善和障碍物处理
- android游戏开发框架libgdx的使用(十四)—TiledMap中视角完善和障碍物处理
- 幸福框架:使用 “离线事件” 处理 “长事务”
- 幸福框架:应当如何使用和处理异常
- 在DirectX10中不使用Effect框架处理Shader与程序间的数据传递
- python的分布式任务并行处理框架Jug简单使用
- Java图片处理开源框架--Thumbnailator使用简介
- windows下使用libxml2处理XML报文
- 使用 PHP 处理HTTP 请求报文
- 幸福框架:使用 “离线事件” 处理 “长事务”
- jQuery前端框架easyui使用Dialog时bug处理
- 使用DXUT框架简单处理鼠标事件
- 使用DXUT框架简单处理鼠标事件
- 使用Hibernate框架,对异常java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()Z的处理