一、什么是hook函数
netfilter架构其实就是在一个packet流经系统时的多个关键点处设置了钩子,程序员可以为每一个钩子点注册一个监听器(即钩子函数,就是在packet流经这个钩子点时的一段处理代码),钩子函数将决定packet的下一个动作是什么!在钩子函数的代码最后需要决定netfiler框架接下来需要怎么处理packet,可以返回以下5种值:
NF_ACCEPT: continue traversal as normal.
NF_DROP: drop the packet; don't continue traversal.
NF_STOLEN: I've taken over the packet; don't continue traversal.
NF_QUEUE: queue the packet (usually for userspace handling).
NF_REPEAT: call this hook again.
netfilter架构其实就是在一个packet流经系统时的多个关键点处设置了钩子,程序员可以为每一个钩子点注册一个监听器(即钩子函数,就是在packet流经这个钩子点时的一段处理代码),钩子函数将决定packet的下一个动作是什么!在钩子函数的代码最后需要决定netfiler框架接下来需要怎么处理packet,可以返回以下5种值:
NF_ACCEPT: continue traversal as normal.
NF_DROP: drop the packet; don't continue traversal.
NF_STOLEN: I've taken over the packet; don't continue traversal.
NF_QUEUE: queue the packet (usually for userspace handling).
NF_REPEAT: call this hook again.
二、如何注册hook函数
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/atomic.h>
#include <linux/ip.h>
#include <linux/version.h>
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4.h>
#include <linux/moduleparam.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], ((unsigned char *)&addr)[1], ((unsigned char *)&addr)[2], ((unsigned char *)&addr)[3]
/* IP Hooks */
/* After promisc drops, checksum checks. */
#define NF_IP_PRE_ROUTING 0
/* If the packet is destined for this box. */
#define NF_IP_LOCAL_IN 1
/* If the packet is destined for another interface. */
#define NF_IP_FORWARD 2
/* Packets coming from a local process. */
#define NF_IP_LOCAL_OUT 3
/* Packets about to hit the wire. */
#define NF_IP_POST_ROUTING 4
#define NF_IP_NUMHOOKS 5
static atomic_t pktcnt =
{
.counter = 0,
};
//我们自己定义的hook回调函数,每隔4个丢弃1个icmp报文
static unsigned int myhook_func(const struct nf_hook_ops *ops, struct sk_buff* skb, const struct net_device* in, const struct net_device* out, int(*okfn)(struct sk_buff*))
{
const struct iphdr* iph = ip_hdr(skb);
if(iph->protocol == 1)
{
atomic_inc(&pktcnt);
if(atomic_read(&pktcnt) % 5 == 0)
{
printk(KERN_INFO "%d:drop an ICMP to %u.%u.%u.%u!\n", atomic_read(&pktcnt), NIPQUAD(iph->daddr));
return NF_DROP;
}
}
return NF_ACCEPT;
}
//<linux/netfilter.h>
static struct nf_hook_ops nfho =
{
.hook = myhook_func, //回调函数
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT, //挂载在本地出口处
.priority = NF_IP_PRI_FIRST, //优先级最高
};
static int __init myhook_init(void)
{
return nf_register_hook(&nfho);
}
static void __exit myhook_fini(void)
{
nf_unregister_hook(&nfho);
}
module_init(myhook_init);
module_exit(myhook_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sekai");
MODULE_DESCRIPTION("Myhook");