inux 内核中有一套hook函数机制,可在不同hook点位置监控网络数据包,并执行丢弃、修改等操作。网络防火墙就是通过此机制实现的。
注册注销hook函数:
linux/netfilter.h
注册钩子函数:
int nf_register_hook(struct nf_hook_ops *reg);
注销:
void nf_unregister_hook(struct nf_hook_ops *reg);
struct nf_hook_ops数据结构:
list:链表结构,被注册的nf_hook_ops实际是以链表节点的形式存储在nf_hooks中的,nf_hooks是一个二维数组,后面详细介绍;
hook:hook处理函数,当接收到一个数据包后,调用此函数进行处理;
pf:协议类型,ipv4就选PF_INET;
hooknum:hook点,linux 网络协议栈中包含5个hook,在不同的情况下对数据包进行监控,后面详细介绍;
priority:优先级(越小优先级越高)
HOOK点:
linux网络协议栈中有5个hook点:
之间的关系如下图:
PRE_ROUTING: 所有进入协议栈的数据包都会经过PRE_ROUTING;
LOCAL_IN:经过路由判决,确认是发给本机的数据包会经过LOCAL_IN;
FORWARD:若经路由判决不是发送本机,而且经本机转发的报文会经过FORWARD;
LOCAL_OUT:由本机进程发送出去数据包经过LOCAL_OUT;
POST_ROUTING:所有数据包在离开本机前会经过POST_ROUTING;
linux/netfilter_bridge.h中定义了相关hook点:
nf_hooks结构:
struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
这是一个二维数组,NFPROTO_NUMPROTO表示相关协议,NF_MAX_HOOKS表示hook点位置。被注册的hook操作节点按照优先级接在在这个二位数据后面,如下图:
linux/netfilter_ipv4.h中定义了优先级信息(越小优先级越高):
回调函数:
回调函数结构如下:
每监控到一条数据包,就会调用一次次函数,数据包信息存储在sk_buff结构中,参考sk_buff相关介绍。这个函数的返回值决定了函数结束后此数据包的走向,有如下几种返回值:
1. NF_ACCEPT继续正常传输数据报。这个返回值告诉Netfilter:到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络协议栈的下一个阶段。
2. NF_DROP丢弃该数据报,不再传输。
3. NF_STOLEN模块接管该数据报,告诉Netfilter“忘掉”该数据报。该回调函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。但是,这并不意味着该数据包的资源已经被释放。这个数据包以及它独自的sk_buff数据结构仍然有效,只是回调函数从Netfilter获取了该数据包的所有权。
4. NF_QUEUE对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)
5. NF_REPEAT 再次调用该回调函数,应当谨慎使用这个值,以免造成死循环。
例:
此例程用于捕捉来自192.168.31.4的ping包:
注册注销hook函数:
linux/netfilter.h
注册钩子函数:
int nf_register_hook(struct nf_hook_ops *reg);
注销:
void nf_unregister_hook(struct nf_hook_ops *reg);
struct nf_hook_ops数据结构:
list:链表结构,被注册的nf_hook_ops实际是以链表节点的形式存储在nf_hooks中的,nf_hooks是一个二维数组,后面详细介绍;
hook:hook处理函数,当接收到一个数据包后,调用此函数进行处理;
pf:协议类型,ipv4就选PF_INET;
hooknum:hook点,linux 网络协议栈中包含5个hook,在不同的情况下对数据包进行监控,后面详细介绍;
priority:优先级(越小优先级越高)
HOOK点:
linux网络协议栈中有5个hook点:
之间的关系如下图:
PRE_ROUTING: 所有进入协议栈的数据包都会经过PRE_ROUTING;
LOCAL_IN:经过路由判决,确认是发给本机的数据包会经过LOCAL_IN;
FORWARD:若经路由判决不是发送本机,而且经本机转发的报文会经过FORWARD;
LOCAL_OUT:由本机进程发送出去数据包经过LOCAL_OUT;
POST_ROUTING:所有数据包在离开本机前会经过POST_ROUTING;
linux/netfilter_bridge.h中定义了相关hook点:
nf_hooks结构:
struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
这是一个二维数组,NFPROTO_NUMPROTO表示相关协议,NF_MAX_HOOKS表示hook点位置。被注册的hook操作节点按照优先级接在在这个二位数据后面,如下图:
linux/netfilter_ipv4.h中定义了优先级信息(越小优先级越高):
回调函数:
回调函数结构如下:
每监控到一条数据包,就会调用一次次函数,数据包信息存储在sk_buff结构中,参考sk_buff相关介绍。这个函数的返回值决定了函数结束后此数据包的走向,有如下几种返回值:
1. NF_ACCEPT继续正常传输数据报。这个返回值告诉Netfilter:到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络协议栈的下一个阶段。
2. NF_DROP丢弃该数据报,不再传输。
3. NF_STOLEN模块接管该数据报,告诉Netfilter“忘掉”该数据报。该回调函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。但是,这并不意味着该数据包的资源已经被释放。这个数据包以及它独自的sk_buff数据结构仍然有效,只是回调函数从Netfilter获取了该数据包的所有权。
4. NF_QUEUE对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)
5. NF_REPEAT 再次调用该回调函数,应当谨慎使用这个值,以免造成死循环。
例:
此例程用于捕捉来自192.168.31.4的ping包: