最近一个项目需要检查TCP/IP包,于是就有了它
- HOOK代码编写
下面展示一些内联代码片
。
// 钩子回调函数
unsigned int myHookCallBack(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{
···············
}
struct nf_hook_ops g_stMyNfHook =
{
.hook = myHookCallBack, //回调函数
.pf = PF_INET, //协议类型
.hooknum = NF_BR_LOCAL_OUT, //hook注册点
.priority = NF_IP_PRI_FIRST, //优先级
};
static void hello_NfHook_Init(void)
{
int iRet;
printk(KERN_ALERT "hello ini success!\n");
iRet = nf_register_hook(&g_stMyNfHook); // 注册
if (0 != iRet)
{
printk(KERN_WARNING "nf_register_hook failed\n");
return;
}
return;
}
static void hello_NfHook_Fini(void)
{
printk(KERN_ALERT "hello_NfHook_Fini\n");
nf_unregister_hook(&g_stMyNfHook); //卸载
return;
}
module_init(hello_NfHook_Init);//注册
module_exit(hello_NfHook_Fini);//卸载
MODULE_LICENSE("GPL");//模块的license,有GPL、BSD等,即模块遵循的开源协议;
MODULE_AUTHOR("Stone");//模块作者
//MODULE_DESCRIPTION--模块描述
obj-m += test.o
#generate the path
CURRENT_PATH:=$(shell pwd)
#the current kernel version number
LINUX_KERNEL:=$(shell uname -r)
#the absolute path
LINUX_KERNEL_PATH:=/usr/src/kernels/linux-headers-$(LINUX_KERNEL)
#complie object
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
#clean
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
通过上面的命令就可以生产一个test.ko模块
- 模块的操作命令
装载模块 insmod test.ko
卸载模块 rmmod test.ko
查看打印日志 dmesg(查看内核日志,因为prink是打印到内核的)
列出系统所有内核模块 lsmod - struct nf_hook_ops
struct nf_hook_ops {
struct list_head list;
/* User fills in from here down. */
nf_hookfn *hook; //hook处理函数
struct net_device *dev;
void *priv;
u_int8_t pf; //协议类型
unsigned int hooknum; //hook点
/* Hooks are ordered in ascending priority. */
int priority; //优先级
};
struct nf_hook_ops g_stMyNfHook =
{
.hook = myHookCallBack, //回调函数
.pf = PF_INET, //协议类型
.hooknum = NF_BR_LOCAL_OUT, //hook注册点
.priority = NF_IP_PRI_FIRST, //优先级
};
协议类型一般分为:
enum {
NFPROTO_UNSPEC = 0,
NFPROTO_INET = 1,
NFPROTO_IPV4 = 2,
NFPROTO_ARP = 3,
NFPROTO_NETDEV = 5,
NFPROTO_BRIDGE = 7,
NFPROTO_IPV6 = 10,
NFPROTO_DECNET = 12,
NFPROTO_NUMPROTO,
};
hook注册点
/* Bridge Hooks */
/* After promisc drops, checksum checks. */------网卡混杂丢包和校验和检查之后(所有进入协议栈的数据包都会经过PRE_ROUTING)
#define NF_BR_PRE_ROUTING 0
/* If the packet is destined for this box. */------经过路由判决,确定发往本机
#define NF_BR_LOCAL_IN 1
/* If the packet is destined for another interface. */--------经过路由判决,不是发往本机,需要从其他接口转发出去
#define NF_BR_FORWARD 2
/* Packets coming from a local process. */--------由本机外发出去的报文路径
#define NF_BR_LOCAL_OUT 3
/* Packets about to hit the wire. */--------所有数据包离开本机前的路径
#define NF_BR_POST_ROUTING 4
/* Not really a hook, but used for the ebtables broute table */-------非hook点,用于其他目的
#define NF_BR_BROUTING 5
#define NF_BR_NUMHOOKS 6
priority 钩子优先级
NF_IP_PRI_FIRST = INT_MIN,
NF_IP_PRI_CONNTRACK_DEFRAG = -400,
NF_IP_PRI_RAW = -300,
NF_IP_PRI_SELINUX_FIRST = -225,
NF_IP_PRI_CONNTRACK = -200,
NF_IP_PRI_MANGLE = -150,
NF_IP_PRI_NAT_DST = -100,
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_SECURITY = 50,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_SELINUX_LAST = 225,
NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
NF_IP_PRI_LAST = INT_MAX,
回调函数的返回值
/* Responses from hook functions. */
#define NF_DROP 0 ----丢弃,释放sk_buff结构
#define NF_ACCEPT 1 ----继续正常传输数据报(按照5个钩子点正常传输)
#define NF_STOLEN 2 ----模块接管该数据报,告诉Netfilter“忘掉”该数据报。该回调函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。但是,这并不意味着该数据包的资源已经被释放。这个数据包以及它独自的sk_buff数据结构仍然有效,只是回调函数从Netfilter获取了该数据包的所有权。
#define NF_QUEUE 3 ----对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)
#define NF_REPEAT 4 ----再次调用该回调函数,应当谨慎使用这个值,以免造成死循环
#define NF_STOP 5 ----终止hook链处理,不会释放sk_buff数据
借鉴了网上很多文章,这里就不一一说了,谢谢大家,有不对的地方请指出