netfilter深入数据规则存储分析_第1页
netfilter深入数据规则存储分析_第2页
netfilter深入数据规则存储分析_第3页
netfilter深入数据规则存储分析_第4页
netfilter深入数据规则存储分析_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Netfilter分析:这是完整的Netfilter源码分析

一、概述

1.Netfi1ter/TPTables框架简介

2.直要源代码文献

二、Netfilter/IPTables-IPv4总体架构

1.NetfilterHOOK机制

2.IPTables基础模块

3.详细功能模块

三、HOOK的实现

1.Netfilter-IPv4中的HOOK

2.HOOKH勺调用

3.HOOK点的实现

4.HOOKH勺注册和注销

四、IPTables系统

1.表一规则系统

2.表的实现

3.规则的实现

4.规则的使用

5.规则的扩展

五、数据报过滤模块一一filter表

1.概述

2.filter表的定义和初始化

3filter表的实现

六、连接跟踪模块(Conntrack)

1.概述

2.连接状态的管理

3.连接跟踪时实现

4.协议的扩展

七、网络地址转换模块(NetworkAddressTranslation)

1.概述

2.基于连接跟踪的有关数据构造

3.nat表口勺实现

4.协议的扩展

八、数据报修改模块---mangle表

L概述

2.mangle表的实现

3.数据报的修改

九、其他高级功能模块

一、概述

1.Netfilter/IPTables框架简介

Netfilter/IPTables是继2.0.x的IPfwadm.2.2.x的IPchains之后,新一代日勺Linux防火墙机制。

Netfilter采用模块化设计,具有贪好H勺可扩充性。其重要工具模块IPTables连接到Netfilter的架构

中,并容许使用者对数据报进行过滤、地址转换、处理等操作。

Netfilter提供了一种框架,将对网络代码日勺直接干涉降到最低,并容许用规定的接口将其他包处

理代码以模块的形式添加到内核中,具有极强的灵活性。

2.重要源代码文献

Netfilter主文献:net/core/netfiIter,c

Netfilter主头文献:includc/linux/nctfilter.h

IPv4有关:c文献:net/ipv4/netfilter/*.c

头文献:include/linux/netfiltcr_ipv4.h

include/linux/netfilter_ipv4/*.h

IPv4协议栈主体的部分c文献,尤其是与数据报传送过程有关的部分:

ipinput.c,ip_forward.c,ip_output.c,ip_fragment.c等

二、Nctfiltcr/IPTablcs-IPv4总体架构

Netfilter重要通过表、链实现规则,可以这样说,Netfilter是表的容器,表是链口勺容器,链

是规则日勺容器,最终形成对数据报处理规则日勺实现。

详细地说,Netfilter/IPTables的体系构造可以分为三个大部分:

1.NetfilterHOOK机制

Netfilter的J通用框架不依赖于详细的J协议,而是为每种网络协议定义一套HOOK函数。这些

HOOK函数在数据报通过协议栈的几种要点时被调用,在这几种点中,协议栈将数据报及HOOK函数标号

作为参数,传递给Netfilter框架。

对于它在网络堆栈中增长的这些HOOK,内核的任何模块可以对每种协议日勺一种或多种HOOK进

行注册,实现挂接。这样当某个数据报被传递给Netfilter框架时,内核能检测到与否有任何模块对该

协议和HOOK函数进行了注册。若注册了,则调用该模块日勺注册时使用的回调函数,这样这些模块就有机

会检查、修改、丢弃该数据报及指示Netfilter将该数据报传入顾客空间的队列。

这样,HOOK提供了一种以便的机制:在数据报通过Linux内核的不一样位置上截获和操作处理数据

报。

2.IPTables基础模块

IPTables基础模块实现了三个表来筛选多种数据报,详细地讲,Linux2.4内核提供日勺这三种数

据报的处理功能是互相间独立的模块,都基于Netfilter的HOOK函数和多种表、链实现。这三个表包括:

filter表,nat表以及mangle表。

3.详细功能模块

数据报过滤模块

连接跟踪模块(Conntrack)

网络地址转换模块(NAT)

数据报修改模块(mangle)

其他高级功能模块

于是,于是ilter/IPTables总体架构如图所示

Netfilter/IPTables

三、HOOK时实现

1.Netfilter-IPv4中的HOOK

Netfilter模块需要使用HOOK来启用函数的动态钩接,它在IPv4中定义了五个HOOK(位于文

include/linux/netfilter_ipv4.h,Line39),分别对应0-4日勺hooknum

简朴地说,数据报通过各个HOOK的流程如下:

数据报从进入系统,进行IP校验后来,首先通过第一种HOOK函数NF」P_PRE_RO【ITING进行处理:

然后就进入路由代码,其决定该数据报是需要转发还是发给本机的;若该薪据报是发被本机口勺,则该数

据通过HOOK函数NF_IP_LOCAL_IN处理后来然后传递给上层协议;若该数据报应当被转发则它被

NF_TP_FORWARD处理;施后转发而数据报通过最终一种HOOK函数NF」P_POST_ROUTING处理后来,再传

播到网络上。当地产生日勺数据通过HOOK函数NF」P_LOCAL_OUT处理后,进行路由选择处理,然后通过

NF」P_POST_ROUTING处理后发送出去。

总之,这五个HOOK所构成的Netfilter-IPv4数据报筛选体系如图(注:下面所说

Netfilter/IPTables均基于IPv4,不再赘述)

图2.Netfilter-IPv4的数据报筛选体系

详细地说,各个HOOK及其在IP数据报传递中口勺详细位置如图

NF」P_PRE_ROUTING(0)

数据报在进入路由代码被处理之前,数据报在IP数据报接受函数ii-rcvO(位于

net/ipv4/ip_input.c,Line379)的最终,也就是在传入日勺数据报被处理之前通过这个HDOK。在ip_rcv()

中挂接这个HOOK之前,进行日勺是其些与类型、长度、版本有关的检查。

通过这个HOOK处理之后,数据报进入ip_rcv_finish()(位于net/ipv4/ip_input.c,Line306),进

行查路曰表的工作,并判断该数据报是发给当地加器还是进行转发。

在这个HOOK上重要是对数据报作报头检测处理,以捕捉异常状况。

波及功能(优先级次序):Conntrack(-200),mangle(-150),DNAT(-IOO)

NF」P_LOCAL_IN(1)

目的地为当地主机的数据报在IP数据报当地投递函数ip_local_deliver()(位于

net/ipv4/ipinput.c,Line290)H勺最终通过这个HOOK。

通过这个HOOK处理之后,数据报进入ip_local_deliver_finish()(位于net/ipv4/ip_input.c,

Line219)

这样,IPTables模块就可以运用这个HOOK对应H勺INPUT规则链表来对数据报进行规则匹配的筛

选了。防火墙一般建立在这个HOOK上。

波及功能:mangle(-150)>filter(O).SNAT(IOO),Conntrack(INTJIAX-1)

NF」P_FORWARD(2)

目口勺地非当地主机口勺数据报,包括被NAT修改正地址的数据报,都要在TP数据报转发函数

ip_forward()(位于net/ipv4/ip_forward.c,Line73)区|最终通过这个HOOK。

通过这个HOOK处理之后,数据报进入ip_forward_finish()(位于net/ipv4/ip_forward.c,

Line44)

此外,在net/ipv4/ipmr.c中日勺ipmr_queue_xmit()函数(LinellI9)最终也会通过这个HOOK°(ipmr

为多播有关,估计是在需要通过路由转发少播数属时的处理)

这样,IPTables模块就可以运用这个HOOK对应的FORWARD规则链表来对数据报进行规则匹配的筛

选了。

波及功能:mangle(-150)>filter(O)

NF_IP_LOCAL_OUT(3)

当地主机发出日勺数据报在IP数据报构建/发送函数ip_queue_xmit()(位于net/ipv4/ip_output.c,

Line339)>以及ip_build_and_send_pkt()(位于net/ipv4/ip_output.c,Linel22)日勺最终通过这个

HOOKo(在数据报处理中,前者最为常用,后者用于那些不传播有效数据的SYN/ACK包)

通过这个HOOK处理后,数据报进入ipqucue_xmit2()(位于net/ipv4/ipoutput,c,Line281)

此外,在ipbuildxmit_slow()(位于net/ipv4/ipoutput,c,Line429)和ipbuildxmit()(位

于net/ipv4/ip_output.c,Line638)中用于进行错误检测;在igmp_send_report()(位于

net/ipv4/igmp.c,Linel95)的最终也通过了这个HOOK,进行多播时有关的处理。

这样,IPTables模块就可以运用这个HOOK对应的OUTPUT规则链表来对数据报进行规则匹配H勺筛选

了。

波及功能:Conntrack(-200)mangle(-150)>DNAT功能0)、filter(0)

NF_IP_POST_ROUTING(4)

所有数据报,包括源地址为当地主机和非当地主机的I,在通过网络设备离开当地主机之前,在IP

数据报发送函数ip_finish_output()(位于net/ipv4/ip_output.c,Linel84)聆|最终通过这个HOOK。

通过这个HOOK处理后,数据报进入ipfinish_output2:)(位于net/ipv4/ip_output.c,Linel60)

此外,在函数ip_mc_output()(位于net/ipv4/ip_output.c,Linel95)中在克隆新的I网络缓存skb时,

也通过"这个HOOKil行处理。

波及功能:mangle(-150)>SNAT(lOO),Conntrack(INT_MAX)

其中,入口为net_rx_action:)(位于net/core/dev.c,Linel602),作用是将数据报-一种个地从

CPU的输入队列中拿出,然后传递给协议处理例程。

出口为dev_queue_xmit()(位于net/core/dev.c,Linel035),这个函数被高层协议日勺实例使用,以

数据构造structsk_buff*skb的形式在网络设备上发送数据报。

2.HOOK的调用

HOOK的调用是通过宏NF_HOOK实现H勺,其定义位于include/linux/Netfilter.h,Linel22:

SdefineNFJ100K(pf,hook,skb,indev,outdev,okfn)\

(list_empty(&nf_hooks[(pf)][(hook)])\

?(okfn)(skb)\

:nf_hook_slow((pf),(hook),(skb),(indev),(outdev),(okfn)))

这旦先调用list_empty函数检查HOOK点存储数组nf_hooks与否为空,为空则表达没有HOOK注册,

则直接调用。kfn继续处理。假如人为空,则转入nf_hook_s:ow()函数。

nf_hook_slow()函数(位于net/core/netfilter.c,Line449)日勺工作重要是读nf_hook数组遍历所有

的Jnf_hook_ops构造,并调用nf_hookfn()处理各个数据报。

即HOOK口勺调用过程如图示

图4.HOOK的调用过程

下面阐明一下NFJ00K的各个参数:

pf:协议族标识,有关H勺有效协议族列表位于include/linux/socket.h,Line178。对于IPv4,应当使

用协议族PFINET;

hook:HOOK标识,即前面所说5个HOOK对应的Jhooknum;

skb:是具有需要被处理包的skbuuff数据构造Rj指针。skbuff是Linux网络缓存,指那些linux内

核处理IP分组报文的缓存,即套接字缓冲区。

网卡收到IP分组报文后,将它们放入sk,buff,然后再传送给网络堆栈,网络堆栈几乎一直要用到

skbuffo其定义在include/linux/skbuff.h,Line129,下面列出我认为对分析故意义的)部提组员:

structsock*sk;':韦向创立分组报文/、Jsocket;

structtimcvalstamp;':分组报文抵达系统的时间;

下面是三个union,寄存的是各层中多种协议的I报文头指针:

h对应传播层的报头

nh对应网络层的报头

mac对应MAC层的报头

'unsignedintlen;':套接字缓存所代表的I报文长度,即从unsignedchar*data;'的)位置算起H勺目前

有效报文长度。

unsignedcharpkttype,:表达报文的类型,详细类型定义在include/1imix/ifpacket,h,

Line24:

^definePACKETJ1OST0//发送到本机的报文

#definePACKET_BROADCAST1//广播报文

#definePACKETJ1ULTICAST2//多播报文

#definePACKET_OTHER11OST3//表达目的地非本机但被本机接受时报文

#definePACKET_OUTGOING4//离开本机日勺报文

/*Theseonesareinvisiblebyuserlevel*/

#definePACKET_LOOPBACK5//本机发给自己日勺报文

^defineEACKEIJASTKOUTE6//迅速路由报文

indev:输入设备,收到数据报口勺网络设备的net.device数据构造指针,即数

据报抵达的接口。

用于NF_IPPREROUTING和NF」P_LOCAL」N两个HOOK

outdev:输出设备,数据报离开当地所要使用日勺网络设备日勺net_device数据构

造指针。

用于NF_IP_LOCAL_OUT和NF_IP_POST_ROUTING两个HOOK

注意:在一般状况下,在一次HOOK调用中,indev和outdev中只有一种参数会被使用

okfn:下一步要处理的函数。即假如有HOOK函数,则处理完所有的HOOK函数,且所有向该HOOK注

册过的筛选函数都返回调用这个函数继续处理;假如没有注册任何HOOK,则直接调

用此函数。其5个参数将由宏NF」IOOK传入。

3.HOOK点的实现

对应于各个不一样协议的不一样HOOK点是由一种二维数组nf_hooks存储日勺(位于

net/core/netfilter.c,Line47),详细日勺HOOK点则由数据构造nf_hook_ops(位于

include/linux/netfilter.h,Line44)实现。如图所示:

图5.HOOK点的实现

其中,nf_hook_ops组员中:

intpriority;priority值越小,优先级越高,有关优先级在include/linux/netfilter_ipv4.h,

Line52中枚举定义:

enumNF_IP_hook_priorities{

NF_IP_PRI_F1RST=INTJHN,

NF_IP_PRI_CONNTRACK=-200,

NF_IP_PRI_MANGLE=-150,

NF」P_PRI_NAT_DST=-100,

NF_ZP_PRI_FILTER=0,

NFIPPRINATSRC=100,

NF_:P_PRI_LAST=INT_MAX,

};

nf_hookfn*hook;为处理函数的指针,其函数指针类型定

义位于include/linux/netfilter.h,Line38,为:

typedefunsignedintnfhookfn(unsignedinthooknum,

structskbuff**skb,

conststructnet^device*in,

conststructnetdevice*out,

int(*okfn)(structskbuff*));

这是nf_hook_ops中最关键的组员,其五个参数分别对应前面所解释的NFJ100K中第2到6个参数

调用HOOK的包筛选函数必须返回特定时值,这些值以宏的形式定义于头文献

include/linux/netfilter.h41(Linel5),分别为:

NF_DROP(O):丢弃此数据报,严禁包继续传递,不进入此后的处理流程;

NF_ACCEPT(1):接受此数据报,容许包继续传递,直至传递到链表最终,而进入okfn函数;

以上两个返回值最为常见

NF_STOLEN(2):数据报被筛选函数截获,严禁包继续传递,但并不释放数据报的资源,这个数据报

及其占有的sk_buff仍然有效(c.g.将分片的数据报一一截获,然后将其装配起来再进行其他处理);

NF_QUEQUE(3):将数据报加入顾客空间队列,使顾客空间的程序可以直接进行处理;

在nf_hook_slow()以及nf_reinject()函数(位于net/core/netfilter.c,Line449,Line505)中,当

由调用nf_iterate()函数(位于net/core/netfilter.c,Line339,作用为遍历所有注册的HOOK函数,

并返回对应的NF_XX值)而返回的verdict值为NF_QUEUE时(即目前正在执行lf、J这个HOOK筛选函数规

定将数据报加入顾客空间队列),会调用nf_queue()困数(位于net/core/netfliter,c,Line407),

nfqueue。函数将这个数据报加入顾客空间队列nfinfo(位于include/linux/netfilter.h,Line77),

并保留其设备信息以备用

NF_REPEAT(4):再次调用目前这个HOOK日勺筛选函数,进行反兔处理。

4.HOOK的注册和注销

HOOK注册和注销分别是通过nfregisterhook()函数和nfunregisterhook()函数(分别

位于net/core/netfilter.c,Line60,76)实现『、J,其参数均为一种nf_hookops构造,两者『、J实现也

非常简朴。

nf_register_hook()的工作是首先遍历nf_hools[][],由HOOK的优先级确定在HOOK链表中的

位置,然后坂据优先级将该HOOK日勺nf_hook_ops加入链表;

nfunregisterhook()[fj工作愈加简朴,其实就是将该HOOK/、Jnfhookops从链表中删除。

四、IPTables系统

1.表一规则系统

IPTables是基于Netfilter基本架构实现的一种可于展H勺数据报高级管理系统,运用table,

chain、rule二级来存储数据报的J多种规则。系统预定义了二个table;

filter:数据报过滤表(文献net/ipv4/netfilter/iptable_filter.c)

监听NF」P_LOCAL」N、NF_1P_FORWARD和NF」P_LOCAL_OUT三个HOOK,作用是在所有数据报传递日勺要点

上对其虚行过滤。

nat:网络地址转换表

监听NF」P_PRE_ROUTING、NF_IP_POST_ROUTING和NF_IP_LOCAL_OUT三个HOOK,作用是当新连接日勺第一

种数据报通过时,在nat表6决定对其H勺转换操作;相酉面的其他数据报都将根据第一种数据报H勺成果

进行相似的转换处理。

mangle:数据报修改表(位于net/ipv4/netfilter/iptablemangle,c)

监听NF_IP_PRE_ROUTING和NF」P_LOCAL_OUT两个HOOK,作用是修改数据报报头中的某些值。

2.表的实现

表日勺基石数据构造是ipttable(位于include/linux/netfilter_ipv4/ip_tables.h,Line413):

structipttable

structlist_headlist;//一种双向链表

charname[IPTTABLEMAXNAMELEN];//被顾客空间使用的表函数的名字

structipt_replacestable;//表初始化欧I模板,定义了一种初始化用的该表口勺所默认

的HOOK所包括的规则等信息,顾客通过系统调用进行表的替代时也要用

unsignedintvalid_hooks;//表所监听/、JHOOK,实质是一种位图

rwlock_tlock;//整个表口勺读/写自旋锁

structipt_table_info*private;//表所存储的数据信息,也就是实际住)数据区,仅在处

理ipt_table口勺代码内部使用

structmodule*me;//假如是模块,那么取THISMODULE,否则取NULL

};

其中:

unsignedintvalid_hooks;这个位图有两个作用:一是检查NetfiIter中哪些HOOK对应着合法日勺

entries;二是用来为iptmatch以及ipttarget数据构造中的checkentry()函数核算也许的IHOOK。

structmodule*n】e;当取值为THIS_MODULE时,可以制止顾客rmmod一种仍然被某个规则指向的)模块的

尝试。

structipt.replacestable;的数据构造是被顾客空间用来替代一种表的,其定义位于

include/linux/netfilter_ipv4/ip_tables.h,Line230:

structipt_replace

(

charname[IPT_TABLE_MAXNAMELEN];

unsignedintvalid_hooks;

unsignedintnumcntrics;//规则表入口的数量

unsignedintsize;//新的规则表的J总大小

/.Hoo.entr.points.*/

unsignedinthookentry[NF_IP_NUMHOOKS];//表所监听HOOK的J规则入口,是对于cntriesE]

M扁移

unsignedintunderflow[NF_ZP_NUMHOOKS];//规则表/、J最大卜界

unsignedintnumcounters;//IH肤J计数器数目,即目前欧I旧entries隹J数目

structipt_countcrs"counters;//旧口勺计数器

structipt_entryentries[0];//规则表入口

);

上文所提到的filter,nat和mangle表分别是ipt_table这个数据构造的三个实例:

packet_filter(位于net/ipv4/netfilter/iptable_filter.c,Line84)、

nattable(位于net/ipv4/netfi:ter/ipnatrule,c,Linel04)

packet_mangler(位于net/ipv4/netfilter/iptable_mangle.c,Linel17)

ipttableinfo(位于net/ipv4/netfilter/iptables,c,IJne86)是实际描述规则表的I数据构造:

structipt_table_info

(

unsignedintsize;

unsignedintnumber;//表项的数目

unsignedintinitial_entries;//初始表项数目

unsignedinthook_entry[NF_IP_NUMHOOKS];//所监听HOOK的规则入口

unsignedintunderflow[NF_ZP_NUMHOOKS];//规则表的J最大下界

charentries[0];//规则表入口,即真正日勺规则存储构造ipt_entry

构成块日勺起始地址,对多CPU,每个CPU对应一种

};

3.规则的实现

IPTables中日勺规则表可以在顾客空间中使用,但它所采用的数据构造与内核空间中日勺是同样的,

只不过有些组员不会在顾客空间中使用。

一种完整H勺规则由三个数据构造共同实现,分别是:

1个ipjentry构造,存储规则的整体信息;

0或多种ipt_entry_match构造,寄存多种match,每个构造都可以寄存任意日勺数据,这样也就拥有了良

好日勺可扩展性;

1个ipt_ent门「target构造,寄存规则日勺target,类似的,每个构造也可以寄存任意日勺数据。

下面将依次对这三个数据构造进行分析:

存储规则整体日勺构造ipt_entry,其形式是一种链表(位于

include/1inux/netfi1ter_ipv4/iptables.h,Linel22):

structipt_entry

structipt_ipip;

unsignedintnfcache;

uint!6ttargetoffset;

uintl6tnextoffset;

unsignedintcomefrom;

structipt_counterscounters;

unsignedcharelems[0];

};

其组员如下:

structipt_ipip;:这是对其将要进行匹配动作日勺TP数据报报头日勺描述,其定义于

include/linux/netfilter_ipv4/ip_tables.h,Linel22,其组员包括源/目的IIP及其掩码,出入端口及

其掩码,协议族、标志/取反flag•信息。

unsignedintnfcache;:HOOK函数返回cache标识,用以阐明通过这个规则后数据报『、J状态,其也

许值有三个,定义于include/linux/netfilter.h,Line23:

#defineNFC_ALTERED0x8000〃已变化

#defineNFC_UNKNOWN0x4000〃万确定

另一种乜许值是0,即没有变化.

u_intl6_ttargetoffset;:指出了target日勺数据构造ipt_cntry_targct%J起始位置,即从ipt_cntry

的起始地址到match存储结束的位置

u_intl6_tncxt_offsct;:指出了整条规则的大小,也就是下一条规则H勺起始地址,即ipt_cntry的)起

始地址到match偏移再到target存储结束的位置

unsignedintcomefrom;:所谓『、J"backpointer”,据引用此变量『、J代码(重要是

net/ipv4/netfilter/ip_tables.c中)来看,它应当是指向数据报所经历『、J上一种规则地址,由此实现

对数据报行为的跟踪

structipt_counterscounters;:阐明了匹配这个规则日勺数据报日勺计数以及字节计数(定义于

ine1ndp/linnx/nntfi1t.pripv4/ip_tah1PS.h,I.inpl00)

unsignedcharelems[0];:表达扩展的malch开始口勺详细位置(由于它是大小不确定的),当然,假如

不存在扩展的Imatch那么就是target日勺开始位置

扩展match日勺存储构造ipt_entry_match,位于include/linux/netfilter_ipv4/ip_tables.h,Line48:

structiptentrymatch

(

union{

struct{

uintl6tmatchsize;

charname[IPT_FUNCT:ON^MAXNAMELEN];

}user;

struct{

u_intl6_tmatch_size;

structipt_match*match;

}kernel;

u_intl6_tmatch_size;//总长度

}u:

unsignedchardata[0];

);

其中描述match大小的match_size;',从波及这个变量日勺源码看来,在使用H勺时候需要

注意使月一种宏IPT_ALIGN(位于includc/linux/netfiltcr_ipv4/ip_tables.h,Linc445)来进行4

的对齐处理(0x3&Oxfffffffc),这应当是由于match、target扩展后大小的不确定性决定的J。

在构造中,顾客空间与内核空间为不一样的J实现,内核空间中的描述拥有更多欧J信息。在顾客空间

中寄存的仅仅是match日勺名称,而在内核空间中寄存的则是一种指向iptjnatch构造的指针

构造ipt_match位于include/linux/netfilter_ipv4/ip_tables.h,Line342:

structiptjnatch

structlistheadlist;

constcharname[IPTFUNCTION_MAXNAMELEN];

int(*match)(conststructskbuff*skb,

conststructnetdevice*in,

conststructnetdevice*out,

constvoid*matchinfo,//指向规则中match数据的指针,详细是什么数据构造依状

况而定

intoffset,//TP数据报的偏移

constvoid*hdr,//指向协议头口勺指针

u_intl6_tdatalen,//实际数据长度,即数据报长度TP头长度

int*hotdrop);

int(*checkentry)(constchar*tablename,//可用口勺表

conststructipt_ip*ip,

void*matchinfo,

unsignedintmatchinfosize,

unsignedinthookmask);//对应HOOKH勺位图

void("destroy)(void*matchinfo,unsignedintmatchinfosize);

structmodule

);

其中几种重要组员:

int(*match)(....);:指向用该natch进行匹配时『、J匹配函数的指针,match有关的J关键实现。返回0

时hotdrop置1,立即丢弃数据报;返回非0表达匹配成功。

int(*checkentry)(....);:当试图插入新的Imatch表项时调用这个指针所指向的|函数,对新的Jmatch

表项进行有效性检查,即检查参数与否合法;假如返回false,规则就不会被接受(譬如,一种TCP的

match只会TCP包,而不会接受其他)。

void("destroy)(....);:当试图删除一种使用这个match日勺表项时,即模块释放时,调用这个指针所

指向的函数。我们可以在checkentry中动态地分派资源,并在destroy中将其释放。

扩展target的J存储构造ipt_entry_target,位于include/linux/netfilter_ipv4/ip_tables.h,

Line71,这个构造与ipt_entrymatch构造类似。

同步其中描述内核空间target时构造ipt_target(位于include/linux/netfilter_ipv4/ip_tables.h,

Line375)也与ipt_match类似,只不过其中口勺target()函数返回值不是0/1,而是verdict。

而target的实际使用中,是用一种构造ipt_standard_target专门来描述,这才是实际的target

描述数据构造(位于include/1inux/netfilter_ipv4/ip_tables.h,Line94),它实际上就是一种

ipt_entry_target力口——种verdict。

其中组员verdict这个变量是一种很巧妙的设计,也是一种非常重要的东东,其值日勺正负有着不一样的

意义.我没有找到这个变量H勺中文名称,在内核开发者日勺新闻组中称这个变量为“amagicnumberL它

时也许值包括IPT_C0NTINUE>IPT_RETURN以及前文所述的INF_DR0P等值,那么它日勺作月是什么呢?

由于IPTablcs是在顾客空间中执行的,也就是说Nctfiltcr/IPTablcs这个框架需要顾客态与内核态之

间日勺数据互换以及识别。而在详细日勺程序中,verdict作为'structipt_standard_target'及J一种组员,

也是对于struclipt_entrytarget'中口勺target()函数Rj返回值。这个返回值标识的是target()所对

应日勺执行动作,包括系统的I默认动作以及外部提交的自定义动作。

不过,在顾客空间中提交的I数据往往是类似于“ACCPET”之类的I字符串,在程序处理时则是以^define

NF_ACCEPT1'日勺形式来进行的;而实际上,以上那些执行动作是以链表H勺数据构造进行存储H勺,在内核

空间中体现为偏移。

于是,verdict实际上描述了两个本质相似但实现不一样的值:一种是顾客空间中的执行动作,另一种

则是内核空间中在链表中的偏移一而这就出现了冲突。

处理这种冲突日勺措施就是:用正值表达内核中欧I偏移,而用负值来表达数据报欧I那些默认动作,而外部

提交的自定义动作则也是用正值来表达。这样,在实际使用这个verdict时,我们就可以通过判断值的

正负来进行对应时处理了。

位于net/ipv4/netfilter/ip_tables.h中的)函数ipt_do_table()中有一种经典的verdict使用

(Line335,其中v是一种verdict欧J实例):

if(v!=IPT_RETURN){

verdict=(unsigned)(-v)-1;

break;

其中MJTT其TURN定义为:

SdefineTPTRETURN(-NFMAXVERDICT-1)

而宏NF_MAX_VERDICT实际上就是:

#defineNF_MAX_VERDICTNF_REPEAT

这样,实际上TPTRETURN口勺值就是-NFREPEAT7,也就是对应REPEAT,这就是对执行动作的实际

描述;而我们可以看到,在下面对verdict进行赋值时,它所使用日勺值是'(unsigned)(-v)-1',这就

是在内核中实际对偏移进行定位时所使用的值。

那么总之呢,表和规则的实现如图所示:

图6.表和规则的实现

从上图中不难发现,match的)定位如下:

起始地址为:目前规则(起始)地址+sizeof(structipt_entry);

结束地址为:目前规则(起始)地址+ipt_entry->target_offset;

每一种natch日勺大小为:ipt_entry_match->u.matchesizeo

target的定位则为:

起始地址为match日勺结束地址,即:目前规则(起始)地址一ipt_entry->target_offset;

结束地址为下一条规则日勺起始地址,即:目前规则(起始)地址+ipt_entry->next_offset;

每一种target的大小为:iptentrytarget->u.targetsize。

这些对于理解match以及target有关函数的实现是很有必要明确H勺。

同步,include/linux/netfilter_ipv4/ip_tables.h中提供了三个"helperfunctions”,可用于

使对于entry、tartget和matchH勺操作变得以便,分别是:

函数ipt_get_target():Line274,作用是获得target日勺起始地址,也就是上面所说的目前规则(起始)

地址+iptentry->targetoffset;

宏中1'_"八花也"£1^^():小区28:,作用是遍历规则的所有g1:2,并执行同一种(参数中)给定的函

数。其参数为一种ipt_entry_match构造和一种函数,以及函数需要时参数。当返回值为0时,表达遍

历以及函数执行顺利完毕;返回非。值时则意味着出现问题已终止。

宏小丁_£皿^丫」丁£!^^():一区300,作用是遍历一种表中的)所有规则,并执行同一种给定的函数。其参

数为一种ipl_enlry构造、整个规则表口勺大小,以及一种函数和其所需参数。其返回值的意义与宏

IPT_MATCH_ITERATE()类似。

那么怎样保证传入日勺ipt_entry构造是整个规则表欧I第一种构造呢?据源码看来,实际调用这个宏的

时候传入的第一种参数都是某个ipt_table_info构造的实例所指向的entries组员,这样就保证了对整

个规则表的完整遍历。

4.规则的使用

当一种特定的HOOK被激活时,数据报就开始进入Netfilter/TPTables系统进行遍历,首先检卷

'structipt_ipip',然后数据报将依次遍历各个match,乜就是'structipt_entry_match',并执行

对应的match函数,即ipt_match构造中区|*match所指向H勺函数。当match函数匹配不成功时返回0,或

者hotdrop被置为1时,遍历将会停止。

对natch/、J遍历完毕后,会开始检查'structipt_entry_targct',其中假如是一种原则『、Jtarget,

那么会检查'structipt_standard_target'中的Jverdict,假如verdict值是正欧I而偏移却指向不对的

的位置,那么ipl_entry中的comefrom组员就有了用武之地一一数据报返回所经历的上一种规则。对于

非原则日勺target呢,就会调用target()函数,然后根据其返回值进行背面日勺处理。

5.规则的扩展

Netfilter/IPTables提供了对规则进行扩展日勺机制:可以写一种LKM来扩展内核空间的功能,

也可以写一种共享库来扩展顾客空间中IPTables曰勺功能。

内核H勺扩展

要对内核空间口勺功能进行扩展,实际上就是写一种具有表、match以及target增长功能口勺模块,有

关日勺函数为(位于net/ipv4/netf[lter/ip_tables.c,Linel318to1444):

ipt_register_table()>ipt_unregister_table(),参数为structipt_table*。

ipt_register_table()函数是这三对函数中最复杂的一种,波及了内存、信号量等方方面面口勺东西,但

总起来说就做了初始化表以及加入双向链表两件事。

其复杂一是由于波及到多CPU的处理(每个CPU拥有各自独立的“规则空间”),需要首先将新日勺entries

放入第一种CPU空间,在检查完毕后再复制到其他CPU中;二是就是上面所说对新tab*各个entry的

检查,包括边界检查以及完整性检查等。

其中的重要函数有这样几种:

translate_table()(位于net/ipv4/netfilter/ip_tables.c,Line797):这个函数聆)重要作用是检查

并应用顾容空间传来的规则:

对新表进行边界检查(由宏1PT_ENTRY_ITERATE()调用函数check_entry_size_and_Dlocks(),位于

net/ipv4/netfilter/iptables.c,Line732),包括对齐、过大过小等,尤其是保证赋给hookentries

和underflows值日勺对欧I性。

调用函数make_source_chains()(位于net/ipv4/netfilter/ip_tables.c,Line499)检查新欧I表中与

否存在规则环,同步将HOOKH勺规则遍历次序存入comefrom变量。(这个函数我没有仔细看,只是大概略

了一下)

对ipt_entry依次进行ipt_ip头、match以及target的完整性检查(由宏IPT_ENTRY」TERATE()调用函

数check_entry(),位于net/ipv4/netfilter/ip_tables.c,Line676),保证ipt_entry对时性。

将龙•日勺的ipt_tablcs复制给其他的CPU。

这个函数此外还在do_replace()函数(仅在一种源码中没有被调用过H勺函数中被调用,不予分析)中被

调用。

replacetable0(位于net/ipv4/netfilter/iptables.c,Line877):这个函数的J重要作用是:将得

到模块初始值日勺ipt_table_info构造(newinfo)中日勺值传给ipt_table中欧)private,并返回ip_table

中旧aJprivate0

list_prepend()(位于include/linux/netfilter_ipv4/listhelp.h,Line75):在这个函数被调用之

前,火人初始化的过程就已经结束了,这个函数『、金要作用是:互斥地调用Linux源码中的list_add()

函数(位于include/linux/list.h,Line55),将新的Itable加入到双向链表之中。

ipt_registerjnatch()>ipt_unregister_match(),参数为structipt_match*。

ipt_registertarget()Nipt_unregistertarget(),参数为structipt_target*0

这三对函数除了ipt_register_table()外的5个函数重要就是互斥地将table/match/target加入

到双向链表中或者从双向链表中删除。

其中向双向链表中加入新节点是通过调用list_named_inscrt()函数(位于

include/linux/netfilter_ipv4/listhelp.h,LinelOl)实现的I。这个函数H勺重要工作是首先确定待插

入的match名字与否已经加在,只有不存在时才进行插入的操作。

顾客空间口勺扩展

顾客空间中的扩展用的是共享库配合libiptc库的机制,但这种机制是在单独日勺IPTbales程序中提

供日勺,内核源码中并没有提供,这里就不做分析了。

五、数据报过滤模块一一filter表

1.概述

filter表日勺功能仅仅是本数据报进行过滤,并不对数据报进行任何日勺修改。

filter模块在Netfilter中是基于下列HOOK点的J:

NF_IP_LOCAL_IN

NF_IP_FORWARD

NF_IP_LOCAL_OUT

这几种HOOK分别对应着filter表中的INPUT>FORWARD.OUTPUT三条规则链,对于任何一种数

据报都会通过这3个HOOK之一。

filter模块的I接口位于文献net/ipv4/netfilter/iptables_filter.c中。

2.filter表的定义和初始化

filter表是前面所述数据构造ipt_tablc的一种实例,它的定义和初始化位于

net/ipv4/netfilter/iptable_fiIter,c,Line84:

staticstructipt_tablepacket_filter={

{NULL,NULL),

&initial_table.repl,//对应replace数据构造

FILTER_VALID_HOOKS,

RW_LOCK_UNLOCKED,

NULL,//对应private数据构造

THISMODULE

};

对照构造ipt_table的定义,我们可以发现,filter表日勺初始化数据为:

链表初始化为空

表名为filter

初始化日勺模板为&init:al_table.repl:

初始化的模板表定义于net/ipv4/netfi1ter/iptable_fi1ter.c,Line30,是一种很简朴日勺数据构造,

只是赋值有些复杂,由于要对所波及的各个HOOK进行示一样日勺处理:

staticstruct

(

structipt_replacerepl;

structipt_standardentries[3];

structipt_errorterm;

}initial_table={

//对构造structipt_replacerepl;初始化

{“filter”,

FILTER_VAL1D_HOOKS,

4,

sizeof(structipt_standard)*3+sizeof(structipt_error),

{[NF_IP_LOCAL_IN]0,

[NF_IP_FORWARD]sizeof(structipt_standard),

[NF_IP_LOCAL_OUT]sizeof(structipt_standard)*2

{[NFIPLOCALIN]0,

[NFIPFORWARD]sizeof(structiptstandard;,

[NF_IPLOCALOUT]sizeof(structipt_standard)*2

},

0,

NULL,

(}

},

//对构造structiptstandardentries[。];初始化

(

/*LOCAL_IN*/

{0},

{0},

{0},

{0},

〃〃

X*A*

{0},

{0},

0,

0,

0

),

0,

sizeof(structiptentry),

sizeof(structiptstandard),

0,

{0,0},

(}

),

iptALIGN(sizeof(structiptstandardtarget)),

()

),

-NH_ACCEET-1

)

},

//对构造structipt_standardentries[l];初始化

/*FORWARD*/

{{{{0},{0},{0},{0},〃〃,〃〃,{0},{0},0,0,0},

0,

sizeof(structipt_entry),

sizeof(structiptstandard),

0,{0,0},{1},

{{{{iptALIGN(sizeof(structiptstandardtarget)),〃〃}},{}},

-NF_ACCEPT-1)},

//对构造structipt_standardentries[2];初始化

/*L0CAL_0UT*/

{{{{0},{0},{0},{0},”,〃〃,{0},{0},0,0,0},

0,

sizeof(structipt_entry),

sizeof(structipt_standard),

0,{0,0},{}},

{{{{ipt_ALIGN(sizeof(structipt_standard_target)),〃”}},{}},

-NF_ACCEPT-1)}

),

//对构造structipt_errortern;初始化

/*ERROR*/

{{{{0},{0},{0},{0},〃〃,〃〃,{0},{0},0,0,0},

0,

sizeof(structipt_entry),

sizeof(structipterror),

0,{0,0},{1},

{{{{ipt_ALIGN(sizeof(structipt_error_target)),ipt_ERRORTARGET}),

{)},

“ERROR”

}

}

1:

我们可以看到,一种initial_table包括三个组员:

structipt_replacercpl;:是对一种表进行初始化的I最重要

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论