netfilter提供了
个抽象、通用化
框架
该框架定义
个子功能
实现就是包过滤子系统框架包含以下 5部分:
1. 为每种网络协议(ipv4、ipv6等)定义
套钩子
(ipv4定义了5个钩子
), 这些钩子
在数据报流过协议栈
几个关键点被
在这几个点中
协议栈将把数据报及钩子
标号作为参数
netfilter框架
2. 内核
任何模块可以对每种协议
个或多个钩子进行注册
实现挂接
这样当某个数据包被传递给netfilter框架时
内核能检测是否有任何模块对该协议和钩子
进行了注册
若注册了
则
该模块
注册时使用
回调
这样这些模块就有机会检查(可能还会修改)该数据包、丢弃该数据包及指示netfilter将该数据包传入用户空间
队列
3 .那些排队
数据包是被传递给用户空间
异步地进行处理
个用户进程能检查数据包
修改数据包
甚至可以重新将该数据包通过离开内核
同
个钩子
中注入到内核中
4. 任何在ip层要被抛弃
ip数据包在真正抛弃的前都要进行检查
例如允许模块检查ip-spoofed包(被路由抛弃)
5.ip层
5个hook点
位置如下所示 :
(1)nf_ip_pre_routing:刚刚进入网络层
数据包通过此点(刚刚进行完版本号
校验 和等检测)
源地址转换在此点进行;ip_input.c中ip_rcv
(2)nf_ip_local_in:经路由查找后
送往本机
通过此检查点,input包过滤在此点进行;ip_local_deliver中
(3)nf_ip_forward:要转发
包通过此检测点,forword包过滤在此点进行;
(4)nf_ip_post_routing:所有马上便要通过网络设备出去
包通过此检测点
内置
目
地址转换功能(包括地址伪装)在此点进行;
(5)nf_ip_local_out:本机进程发出
包通过此检测点
output包过滤在此点进行
这些点是已经在内核中定义好
内核模块能够注册在这些hook点进行
处理
可使用nf_register_hook
指定
在数据报经过这些钩子
时被
从而模块可以修改这些数据报
并向netfilter返回如下值:
nf_accept 继续正常传输数据报
nf_drop 丢弃该数据报
不再传输
nf_stolen 模块接管该数据报
不要继续传输该数据报
nf_queue 对该数据报进行排队(通常用于将数据报给用户空间
进程进行处理)
nf_repeat 再次
该钩子
个基于netfilter框架
、称为iptables
数据报选择系统在linux2.4内核中被应用
其实它就是ipchains
后继工具
但却有更强
可扩展性
内核模块可以注册
个新
规则表(table)
并要求数据报流经指定
规则表
这种数据报选择用于实现数据报过滤(filter表)
网络地址转换(nat表)及数据报处理(mangle表)
linux2.4内核提供
这 3种数据报处理功能都基于netfilter
钩子
和ip表
它们是独立
模块
相互的间是独立
它们都完美
集成到由netfileter提供
框架中
包过滤
filter表格不会对数据报进行修改
而只对数据报进行过滤
iptables优于ipchains
个方面就是它更为小巧和快速
它是通过钩子
nf_ip_local_in, nf_ip_forward及nf_ip_local_out接入netfilter框架
因此对于任何
个数 报只有
个地方对其进行过滤
这相对ipchains来说是
个巨大
改进
在ipchains中
个被转发
数据报会遍历 3条链
nat
nat表格监听 3个netfilter钩子
:nf_ip_pre_routing、nf_ip_post_routing及nf_ip_local_out
nf_ip_pre_routing实现对需要转发
数据报
源地址进行地址转换而nf_ip_post_routing则对需要转发
数据包
目
地址进行地址转换
对于本地数据报
目
地址
转换则由nf_ip_local_out来实现
nat表格区别于filter表格
只有新连接
第
个数据报将遍历表格
而随后
数据报将根据第
个数据报
结果进行同样
转换处理
nat表格被用在源nat,目
nat
伪装(其是源nat
个特例)及透明代理(其是目
nat
个特例)
数据报处理(packet mangling)
mangle表格在nf_ip_pre_routing和nf_ip_local_out钩子中进行注册
使用 mangle表
可以实现对数据报
修改或给数据报附上
些带外数据
当前mangle表支持修改tos位及设置skb
nfmard字段
源码分析
如果我们想加入自己
代码,便要用nf_register_hook
其
原型为:
nf_register_hook(struct nf_hook_ops *reg)
struct nf_hook_ops
{
struct list_head list;
/* user fills in from here down. */
nf_hookfn *hook;
pf;
hooknum;
/* hooks are ordered in ascending priority. */
priority;
};
我们
工作便是生成
个struct nf_hook_ops结构
例子
并用nf_register_hook将其hook上
其中list项我们总要
化为{null,null};由于
般在ip层工作
pf总是pf_inet;hooknum就是我们选择
hook点;
个hook点可能挂多个处理
谁先谁后
便要看优先级
即priority
指定了
netfilter_ipv4.h中用
个枚举类型指定了内置
处理
优先级:
enum nf_ip_hook_priorities {
nf_ip_pri_first = _min,
nf_ip_pri_conntrack = -200,
nf_ip_pri_mangle = -150,
nf_ip_pri_nat_dst = -100,
nf_ip_pri_filter = 0,
nf_ip_pri_nat_src = 100,
nf_ip_pri_last = _max,
};
hook是提供
处理
也就是我们
主要工作
其原型为:
unsigned nf_hookfn(unsigned hooknum,
struct sk_buff **skb,
const struct net_device *in,
const struct net_device *out,
(*okfn)(struct sk_buff *));
它
5个参数将由nfhook宏传进去
nf_register_hook根据reg中注册
协议簇类型和优先级在nf_hooks中找到相应
位置并插入到此表中
_hooks[nproto][nf_max_hooks]在netfilter
化时(netfilter_init/netfilter.c,而它在sock_init时
)已经
为
个空表
例如iptable在
化时(init/iptable_filter.c)
nf_register_hook注册他
hook
struct nf_hook_ops ipt_ops
= { { { null, null }, ipt_hook, pf_inet, nf_ip_local_in, nf_ip_pri_filter },
{ { null, null }, ipt_hook, pf_inet, nf_ip_forward, nf_ip_pri_filter },
{ { null, null }, ipt_local_out_hook, pf_inet, nf_ip_local_out,
nf_ip_pri_filter }
};
mangle在init/iptable_mangle.c中注册它自己hook
struct nf_hook_ops ipt_ops
= { { { null, null }, ipt_hook, pf_inet, nf_ip_pre_routing, nf_ip_pri_mangle },
{ { null, null }, ipt_local_out_hook, pf_inet, nf_ip_local_out,
{nf_ip_pri_mangle }
};
nat在init/ip_nat_standalone.c中注册它自己
hook
/*包过滤前
更改目
地址*/
struct nf_hook_ops ip_nat_in_ops
Tags:
延伸阅读
最新评论