netfilter深入數(shù)據(jù)規(guī)則存儲(chǔ)分析_第1頁(yè)
netfilter深入數(shù)據(jù)規(guī)則存儲(chǔ)分析_第2頁(yè)
netfilter深入數(shù)據(jù)規(guī)則存儲(chǔ)分析_第3頁(yè)
netfilter深入數(shù)據(jù)規(guī)則存儲(chǔ)分析_第4頁(yè)
netfilter深入數(shù)據(jù)規(guī)則存儲(chǔ)分析_第5頁(yè)
已閱讀5頁(yè),還剩39頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Netfilter分析:這是完整的Netfilter源碼分析

一、概述

1.Netfi1ter/TPTables框架簡(jiǎn)介

2.直要源代碼文獻(xiàn)

二、Netfilter/IPTables-IPv4總體架構(gòu)

1.NetfilterHOOK機(jī)制

2.IPTables基礎(chǔ)模塊

3.詳細(xì)功能模塊

三、HOOK的實(shí)現(xiàn)

1.Netfilter-IPv4中的HOOK

2.HOOKH勺調(diào)用

3.HOOK點(diǎn)的實(shí)現(xiàn)

4.HOOKH勺注冊(cè)和注銷

四、IPTables系統(tǒng)

1.表一規(guī)則系統(tǒng)

2.表的實(shí)現(xiàn)

3.規(guī)則的實(shí)現(xiàn)

4.規(guī)則的使用

5.規(guī)則的擴(kuò)展

五、數(shù)據(jù)報(bào)過(guò)濾模塊一一filter表

1.概述

2.filter表的定義和初始化

3filter表的實(shí)現(xiàn)

六、連接跟蹤模塊(Conntrack)

1.概述

2.連接狀態(tài)的管理

3.連接跟蹤時(shí)實(shí)現(xiàn)

4.協(xié)議的擴(kuò)展

七、網(wǎng)絡(luò)地址轉(zhuǎn)換模塊(NetworkAddressTranslation)

1.概述

2.基于連接跟蹤的有關(guān)數(shù)據(jù)構(gòu)造

3.nat表口勺實(shí)現(xiàn)

4.協(xié)議的擴(kuò)展

八、數(shù)據(jù)報(bào)修改模塊---mangle表

L概述

2.mangle表的實(shí)現(xiàn)

3.數(shù)據(jù)報(bào)的修改

九、其他高級(jí)功能模塊

一、概述

1.Netfilter/IPTables框架簡(jiǎn)介

Netfilter/IPTables是繼2.0.x的IPfwadm.2.2.x的IPchains之后,新一代日勺Linux防火墻機(jī)制。

Netfilter采用模塊化設(shè)計(jì),具有貪好H勺可擴(kuò)充性。其重要工具模塊IPTables連接到Netfilter的架構(gòu)

中,并容許使用者對(duì)數(shù)據(jù)報(bào)進(jìn)行過(guò)濾、地址轉(zhuǎn)換、處理等操作。

Netfilter提供了一種框架,將對(duì)網(wǎng)絡(luò)代碼日勺直接干涉降到最低,并容許用規(guī)定的接口將其他包處

理代碼以模塊的形式添加到內(nèi)核中,具有極強(qiáng)的靈活性。

2.重要源代碼文獻(xiàn)

Netfilter主文獻(xiàn):net/core/netfiIter,c

Netfilter主頭文獻(xiàn):includc/linux/nctfilter.h

IPv4有關(guān):c文獻(xiàn):net/ipv4/netfilter/*.c

頭文獻(xiàn):include/linux/netfiltcr_ipv4.h

include/linux/netfilter_ipv4/*.h

IPv4協(xié)議棧主體的部分c文獻(xiàn),尤其是與數(shù)據(jù)報(bào)傳送過(guò)程有關(guān)的部分:

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

二、Nctfiltcr/IPTablcs-IPv4總體架構(gòu)

Netfilter重要通過(guò)表、鏈實(shí)現(xiàn)規(guī)則,可以這樣說(shuō),Netfilter是表的容器,表是鏈口勺容器,鏈

是規(guī)則日勺容器,最終形成對(duì)數(shù)據(jù)報(bào)處理規(guī)則日勺實(shí)現(xiàn)。

詳細(xì)地說(shuō),Netfilter/IPTables的體系構(gòu)造可以分為三個(gè)大部分:

1.NetfilterHOOK機(jī)制

Netfilter的J通用框架不依賴于詳細(xì)的J協(xié)議,而是為每種網(wǎng)絡(luò)協(xié)議定義一套HOOK函數(shù)。這些

HOOK函數(shù)在數(shù)據(jù)報(bào)通過(guò)協(xié)議棧的幾種要點(diǎn)時(shí)被調(diào)用,在這幾種點(diǎn)中,協(xié)議棧將數(shù)據(jù)報(bào)及HOOK函數(shù)標(biāo)號(hào)

作為參數(shù),傳遞給Netfilter框架。

對(duì)于它在網(wǎng)絡(luò)堆棧中增長(zhǎng)的這些HOOK,內(nèi)核的任何模塊可以對(duì)每種協(xié)議日勺一種或多種HOOK進(jìn)

行注冊(cè),實(shí)現(xiàn)掛接。這樣當(dāng)某個(gè)數(shù)據(jù)報(bào)被傳遞給Netfilter框架時(shí),內(nèi)核能檢測(cè)到與否有任何模塊對(duì)該

協(xié)議和HOOK函數(shù)進(jìn)行了注冊(cè)。若注冊(cè)了,則調(diào)用該模塊日勺注冊(cè)時(shí)使用的回調(diào)函數(shù),這樣這些模塊就有機(jī)

會(huì)檢查、修改、丟棄該數(shù)據(jù)報(bào)及指示Netfilter將該數(shù)據(jù)報(bào)傳入顧客空間的隊(duì)列。

這樣,HOOK提供了一種以便的機(jī)制:在數(shù)據(jù)報(bào)通過(guò)Linux內(nèi)核的不一樣位置上截獲和操作處理數(shù)據(jù)

報(bào)。

2.IPTables基礎(chǔ)模塊

IPTables基礎(chǔ)模塊實(shí)現(xiàn)了三個(gè)表來(lái)篩選多種數(shù)據(jù)報(bào),詳細(xì)地講,Linux2.4內(nèi)核提供日勺這三種數(shù)

據(jù)報(bào)的處理功能是互相間獨(dú)立的模塊,都基于Netfilter的HOOK函數(shù)和多種表、鏈實(shí)現(xiàn)。這三個(gè)表包括:

filter表,nat表以及mangle表。

3.詳細(xì)功能模塊

數(shù)據(jù)報(bào)過(guò)濾模塊

連接跟蹤模塊(Conntrack)

網(wǎng)絡(luò)地址轉(zhuǎn)換模塊(NAT)

數(shù)據(jù)報(bào)修改模塊(mangle)

其他高級(jí)功能模塊

于是,于是ilter/IPTables總體架構(gòu)如圖所示

Netfilter/IPTables

三、HOOK時(shí)實(shí)現(xiàn)

1.Netfilter-IPv4中的HOOK

Netfilter模塊需要使用HOOK來(lái)啟用函數(shù)的動(dòng)態(tài)鉤接,它在IPv4中定義了五個(gè)HOOK(位于文

include/linux/netfilter_ipv4.h,Line39),分別對(duì)應(yīng)0-4日勺hooknum

簡(jiǎn)樸地說(shuō),數(shù)據(jù)報(bào)通過(guò)各個(gè)HOOK的流程如下:

數(shù)據(jù)報(bào)從進(jìn)入系統(tǒng),進(jìn)行IP校驗(yàn)后來(lái),首先通過(guò)第一種HOOK函數(shù)NF」P_PRE_RO【ITING進(jìn)行處理:

然后就進(jìn)入路由代碼,其決定該數(shù)據(jù)報(bào)是需要轉(zhuǎn)發(fā)還是發(fā)給本機(jī)的;若該薪據(jù)報(bào)是發(fā)被本機(jī)口勺,則該數(shù)

據(jù)通過(guò)HOOK函數(shù)NF_IP_LOCAL_IN處理后來(lái)然后傳遞給上層協(xié)議;若該數(shù)據(jù)報(bào)應(yīng)當(dāng)被轉(zhuǎn)發(fā)則它被

NF_TP_FORWARD處理;施后轉(zhuǎn)發(fā)而數(shù)據(jù)報(bào)通過(guò)最終一種HOOK函數(shù)NF」P_POST_ROUTING處理后來(lái),再傳

播到網(wǎng)絡(luò)上。當(dāng)?shù)禺a(chǎn)生日勺數(shù)據(jù)通過(guò)HOOK函數(shù)NF」P_LOCAL_OUT處理后,進(jìn)行路由選擇處理,然后通過(guò)

NF」P_POST_ROUTING處理后發(fā)送出去。

總之,這五個(gè)HOOK所構(gòu)成的Netfilter-IPv4數(shù)據(jù)報(bào)篩選體系如圖(注:下面所說(shuō)

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

圖2.Netfilter-IPv4的數(shù)據(jù)報(bào)篩選體系

詳細(xì)地說(shuō),各個(gè)HOOK及其在IP數(shù)據(jù)報(bào)傳遞中口勺詳細(xì)位置如圖

NF」P_PRE_ROUTING(0)

數(shù)據(jù)報(bào)在進(jìn)入路由代碼被處理之前,數(shù)據(jù)報(bào)在IP數(shù)據(jù)報(bào)接受函數(shù)ii-rcvO(位于

net/ipv4/ip_input.c,Line379)的最終,也就是在傳入日勺數(shù)據(jù)報(bào)被處理之前通過(guò)這個(gè)HDOK。在ip_rcv()

中掛接這個(gè)HOOK之前,進(jìn)行日勺是其些與類型、長(zhǎng)度、版本有關(guān)的檢查。

通過(guò)這個(gè)HOOK處理之后,數(shù)據(jù)報(bào)進(jìn)入ip_rcv_finish()(位于net/ipv4/ip_input.c,Line306),進(jìn)

行查路曰表的工作,并判斷該數(shù)據(jù)報(bào)是發(fā)給當(dāng)?shù)丶悠鬟€是進(jìn)行轉(zhuǎn)發(fā)。

在這個(gè)HOOK上重要是對(duì)數(shù)據(jù)報(bào)作報(bào)頭檢測(cè)處理,以捕捉異常狀況。

波及功能(優(yōu)先級(jí)次序):Conntrack(-200),mangle(-150),DNAT(-IOO)

NF」P_LOCAL_IN(1)

目的地為當(dāng)?shù)刂鳈C(jī)的數(shù)據(jù)報(bào)在IP數(shù)據(jù)報(bào)當(dāng)?shù)赝哆f函數(shù)ip_local_deliver()(位于

net/ipv4/ipinput.c,Line290)H勺最終通過(guò)這個(gè)HOOK。

通過(guò)這個(gè)HOOK處理之后,數(shù)據(jù)報(bào)進(jìn)入ip_local_deliver_finish()(位于net/ipv4/ip_input.c,

Line219)

這樣,IPTables模塊就可以運(yùn)用這個(gè)HOOK對(duì)應(yīng)H勺INPUT規(guī)則鏈表來(lái)對(duì)數(shù)據(jù)報(bào)進(jìn)行規(guī)則匹配的篩

選了。防火墻一般建立在這個(gè)HOOK上。

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

NF」P_FORWARD(2)

目口勺地非當(dāng)?shù)刂鳈C(jī)口勺數(shù)據(jù)報(bào),包括被NAT修改正地址的數(shù)據(jù)報(bào),都要在TP數(shù)據(jù)報(bào)轉(zhuǎn)發(fā)函數(shù)

ip_forward()(位于net/ipv4/ip_forward.c,Line73)區(qū)|最終通過(guò)這個(gè)HOOK。

通過(guò)這個(gè)HOOK處理之后,數(shù)據(jù)報(bào)進(jìn)入ip_forward_finish()(位于net/ipv4/ip_forward.c,

Line44)

此外,在net/ipv4/ipmr.c中日勺ipmr_queue_xmit()函數(shù)(LinellI9)最終也會(huì)通過(guò)這個(gè)HOOK°(ipmr

為多播有關(guān),估計(jì)是在需要通過(guò)路由轉(zhuǎn)發(fā)少播數(shù)屬時(shí)的處理)

這樣,IPTables模塊就可以運(yùn)用這個(gè)HOOK對(duì)應(yīng)的FORWARD規(guī)則鏈表來(lái)對(duì)數(shù)據(jù)報(bào)進(jìn)行規(guī)則匹配的篩

選了。

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

NF_IP_LOCAL_OUT(3)

當(dāng)?shù)刂鳈C(jī)發(fā)出日勺數(shù)據(jù)報(bào)在IP數(shù)據(jù)報(bào)構(gòu)建/發(fā)送函數(shù)ip_queue_xmit()(位于net/ipv4/ip_output.c,

Line339)>以及ip_build_and_send_pkt()(位于net/ipv4/ip_output.c,Linel22)日勺最終通過(guò)這個(gè)

HOOKo(在數(shù)據(jù)報(bào)處理中,前者最為常用,后者用于那些不傳播有效數(shù)據(jù)的SYN/ACK包)

通過(guò)這個(gè)HOOK處理后,數(shù)據(jù)報(bào)進(jìn)入ipqucue_xmit2()(位于net/ipv4/ipoutput,c,Line281)

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

于net/ipv4/ip_output.c,Line638)中用于進(jìn)行錯(cuò)誤檢測(cè);在igmp_send_report()(位于

net/ipv4/igmp.c,Linel95)的最終也通過(guò)了這個(gè)HOOK,進(jìn)行多播時(shí)有關(guān)的處理。

這樣,IPTables模塊就可以運(yùn)用這個(gè)HOOK對(duì)應(yīng)的OUTPUT規(guī)則鏈表來(lái)對(duì)數(shù)據(jù)報(bào)進(jìn)行規(guī)則匹配H勺篩選

了。

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

NF_IP_POST_ROUTING(4)

所有數(shù)據(jù)報(bào),包括源地址為當(dāng)?shù)刂鳈C(jī)和非當(dāng)?shù)刂鳈C(jī)的I,在通過(guò)網(wǎng)絡(luò)設(shè)備離開(kāi)當(dāng)?shù)刂鳈C(jī)之前,在IP

數(shù)據(jù)報(bào)發(fā)送函數(shù)ip_finish_output()(位于net/ipv4/ip_output.c,Linel84)聆|最終通過(guò)這個(gè)HOOK。

通過(guò)這個(gè)HOOK處理后,數(shù)據(jù)報(bào)進(jìn)入ipfinish_output2:)(位于net/ipv4/ip_output.c,Linel60)

此外,在函數(shù)ip_mc_output()(位于net/ipv4/ip_output.c,Linel95)中在克隆新的I網(wǎng)絡(luò)緩存skb時(shí),

也通過(guò)"這個(gè)HOOKil行處理。

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

其中,入口為net_rx_action:)(位于net/core/dev.c,Linel602),作用是將數(shù)據(jù)報(bào)-一種個(gè)地從

CPU的輸入隊(duì)列中拿出,然后傳遞給協(xié)議處理例程。

出口為dev_queue_xmit()(位于net/core/dev.c,Linel035),這個(gè)函數(shù)被高層協(xié)議日勺實(shí)例使用,以

數(shù)據(jù)構(gòu)造structsk_buff*skb的形式在網(wǎng)絡(luò)設(shè)備上發(fā)送數(shù)據(jù)報(bào)。

2.HOOK的調(diào)用

HOOK的調(diào)用是通過(guò)宏NF_HOOK實(shí)現(xiàn)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)))

這旦先調(diào)用list_empty函數(shù)檢查HOOK點(diǎn)存儲(chǔ)數(shù)組nf_hooks與否為空,為空則表達(dá)沒(méi)有HOOK注冊(cè),

則直接調(diào)用。kfn繼續(xù)處理。假如人為空,則轉(zhuǎn)入nf_hook_s:ow()函數(shù)。

nf_hook_slow()函數(shù)(位于net/core/netfilter.c,Line449)日勺工作重要是讀nf_hook數(shù)組遍歷所有

的Jnf_hook_ops構(gòu)造,并調(diào)用nf_hookfn()處理各個(gè)數(shù)據(jù)報(bào)。

即HOOK口勺調(diào)用過(guò)程如圖示

圖4.HOOK的調(diào)用過(guò)程

下面闡明一下NFJ00K的各個(gè)參數(shù):

pf:協(xié)議族標(biāo)識(shí),有關(guān)H勺有效協(xié)議族列表位于include/linux/socket.h,Line178。對(duì)于IPv4,應(yīng)當(dāng)使

用協(xié)議族PFINET;

hook:HOOK標(biāo)識(shí),即前面所說(shuō)5個(gè)HOOK對(duì)應(yīng)的Jhooknum;

skb:是具有需要被處理包的skbuuff數(shù)據(jù)構(gòu)造Rj指針。skbuff是Linux網(wǎng)絡(luò)緩存,指那些linux內(nèi)

核處理IP分組報(bào)文的緩存,即套接字緩沖區(qū)。

網(wǎng)卡收到IP分組報(bào)文后,將它們放入sk,buff,然后再傳送給網(wǎng)絡(luò)堆棧,網(wǎng)絡(luò)堆棧幾乎一直要用到

skbuffo其定義在include/linux/skbuff.h,Line129,下面列出我認(rèn)為對(duì)分析故意義的)部提組員:

structsock*sk;':韋向創(chuàng)立分組報(bào)文/、Jsocket;

structtimcvalstamp;':分組報(bào)文抵達(dá)系統(tǒng)的時(shí)間;

下面是三個(gè)union,寄存的是各層中多種協(xié)議的I報(bào)文頭指針:

h對(duì)應(yīng)傳播層的報(bào)頭

nh對(duì)應(yīng)網(wǎng)絡(luò)層的報(bào)頭

mac對(duì)應(yīng)MAC層的報(bào)頭

'unsignedintlen;':套接字緩存所代表的I報(bào)文長(zhǎng)度,即從unsignedchar*data;'的)位置算起H勺目前

有效報(bào)文長(zhǎng)度。

unsignedcharpkttype,:表達(dá)報(bào)文的類型,詳細(xì)類型定義在include/1imix/ifpacket,h,

Line24:

^definePACKETJ1OST0//發(fā)送到本機(jī)的報(bào)文

#definePACKET_BROADCAST1//廣播報(bào)文

#definePACKETJ1ULTICAST2//多播報(bào)文

#definePACKET_OTHER11OST3//表達(dá)目的地非本機(jī)但被本機(jī)接受時(shí)報(bào)文

#definePACKET_OUTGOING4//離開(kāi)本機(jī)日勺報(bào)文

/*Theseonesareinvisiblebyuserlevel*/

#definePACKET_LOOPBACK5//本機(jī)發(fā)給自己日勺報(bào)文

^defineEACKEIJASTKOUTE6//迅速路由報(bào)文

indev:輸入設(shè)備,收到數(shù)據(jù)報(bào)口勺網(wǎng)絡(luò)設(shè)備的net.device數(shù)據(jù)構(gòu)造指針,即數(shù)

據(jù)報(bào)抵達(dá)的接口。

用于NF_IPPREROUTING和NF」P_LOCAL」N兩個(gè)HOOK

outdev:輸出設(shè)備,數(shù)據(jù)報(bào)離開(kāi)當(dāng)?shù)厮褂萌丈拙W(wǎng)絡(luò)設(shè)備日勺net_device數(shù)據(jù)構(gòu)

造指針。

用于NF_IP_LOCAL_OUT和NF_IP_POST_ROUTING兩個(gè)HOOK

注意:在一般狀況下,在一次HOOK調(diào)用中,indev和outdev中只有一種參數(shù)會(huì)被使用

okfn:下一步要處理的函數(shù)。即假如有HOOK函數(shù),則處理完所有的HOOK函數(shù),且所有向該HOOK注

冊(cè)過(guò)的篩選函數(shù)都返回調(diào)用這個(gè)函數(shù)繼續(xù)處理;假如沒(méi)有注冊(cè)任何HOOK,則直接調(diào)

用此函數(shù)。其5個(gè)參數(shù)將由宏NF」IOOK傳入。

3.HOOK點(diǎn)的實(shí)現(xiàn)

對(duì)應(yīng)于各個(gè)不一樣協(xié)議的不一樣HOOK點(diǎn)是由一種二維數(shù)組nf_hooks存儲(chǔ)日勺(位于

net/core/netfilter.c,Line47),詳細(xì)日勺HOOK點(diǎn)則由數(shù)據(jù)構(gòu)造nf_hook_ops(位于

include/linux/netfilter.h,Line44)實(shí)現(xiàn)。如圖所示:

圖5.HOOK點(diǎn)的實(shí)現(xiàn)

其中,nf_hook_ops組員中:

intpriority;priority值越小,優(yōu)先級(jí)越高,有關(guān)優(yōu)先級(jí)在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;為處理函數(shù)的指針,其函數(shù)指針類型定

義位于include/linux/netfilter.h,Line38,為:

typedefunsignedintnfhookfn(unsignedinthooknum,

structskbuff**skb,

conststructnet^device*in,

conststructnetdevice*out,

int(*okfn)(structskbuff*));

這是nf_hook_ops中最關(guān)鍵的組員,其五個(gè)參數(shù)分別對(duì)應(yīng)前面所解釋的NFJ100K中第2到6個(gè)參數(shù)

調(diào)用HOOK的包篩選函數(shù)必須返回特定時(shí)值,這些值以宏的形式定義于頭文獻(xiàn)

include/linux/netfilter.h41(Linel5),分別為:

NF_DROP(O):丟棄此數(shù)據(jù)報(bào),嚴(yán)禁包繼續(xù)傳遞,不進(jìn)入此后的處理流程;

NF_ACCEPT(1):接受此數(shù)據(jù)報(bào),容許包繼續(xù)傳遞,直至傳遞到鏈表最終,而進(jìn)入okfn函數(shù);

以上兩個(gè)返回值最為常見(jiàn)

NF_STOLEN(2):數(shù)據(jù)報(bào)被篩選函數(shù)截獲,嚴(yán)禁包繼續(xù)傳遞,但并不釋放數(shù)據(jù)報(bào)的資源,這個(gè)數(shù)據(jù)報(bào)

及其占有的sk_buff仍然有效(c.g.將分片的數(shù)據(jù)報(bào)一一截獲,然后將其裝配起來(lái)再進(jìn)行其他處理);

NF_QUEQUE(3):將數(shù)據(jù)報(bào)加入顧客空間隊(duì)列,使顧客空間的程序可以直接進(jìn)行處理;

在nf_hook_slow()以及nf_reinject()函數(shù)(位于net/core/netfilter.c,Line449,Line505)中,當(dāng)

由調(diào)用nf_iterate()函數(shù)(位于net/core/netfilter.c,Line339,作用為遍歷所有注冊(cè)的HOOK函數(shù),

并返回對(duì)應(yīng)的NF_XX值)而返回的verdict值為NF_QUEUE時(shí)(即目前正在執(zhí)行l(wèi)f、J這個(gè)HOOK篩選函數(shù)規(guī)

定將數(shù)據(jù)報(bào)加入顧客空間隊(duì)列),會(huì)調(diào)用nf_queue()困數(shù)(位于net/core/netfliter,c,Line407),

nfqueue。函數(shù)將這個(gè)數(shù)據(jù)報(bào)加入顧客空間隊(duì)列nfinfo(位于include/linux/netfilter.h,Line77),

并保留其設(shè)備信息以備用

NF_REPEAT(4):再次調(diào)用目前這個(gè)HOOK日勺篩選函數(shù),進(jìn)行反兔處理。

4.HOOK的注冊(cè)和注銷

HOOK注冊(cè)和注銷分別是通過(guò)nfregisterhook()函數(shù)和nfunregisterhook()函數(shù)(分別

位于net/core/netfilter.c,Line60,76)實(shí)現(xiàn)『、J,其參數(shù)均為一種nf_hookops構(gòu)造,兩者『、J實(shí)現(xiàn)也

非常簡(jiǎn)樸。

nf_register_hook()的工作是首先遍歷nf_hools[][],由HOOK的優(yōu)先級(jí)確定在HOOK鏈表中的

位置,然后坂據(jù)優(yōu)先級(jí)將該HOOK日勺nf_hook_ops加入鏈表;

nfunregisterhook()[fj工作愈加簡(jiǎn)樸,其實(shí)就是將該HOOK/、Jnfhookops從鏈表中刪除。

四、IPTables系統(tǒng)

1.表一規(guī)則系統(tǒng)

IPTables是基于Netfilter基本架構(gòu)實(shí)現(xiàn)的一種可于展H勺數(shù)據(jù)報(bào)高級(jí)管理系統(tǒng),運(yùn)用table,

chain、rule二級(jí)來(lái)存儲(chǔ)數(shù)據(jù)報(bào)的J多種規(guī)則。系統(tǒng)預(yù)定義了二個(gè)table;

filter:數(shù)據(jù)報(bào)過(guò)濾表(文獻(xiàn)net/ipv4/netfilter/iptable_filter.c)

監(jiān)聽(tīng)NF」P_LOCAL」N、NF_1P_FORWARD和NF」P_LOCAL_OUT三個(gè)HOOK,作用是在所有數(shù)據(jù)報(bào)傳遞日勺要點(diǎn)

上對(duì)其虛行過(guò)濾。

nat:網(wǎng)絡(luò)地址轉(zhuǎn)換表

監(jiān)聽(tīng)NF」P_PRE_ROUTING、NF_IP_POST_ROUTING和NF_IP_LOCAL_OUT三個(gè)HOOK,作用是當(dāng)新連接日勺第一

種數(shù)據(jù)報(bào)通過(guò)時(shí),在nat表6決定對(duì)其H勺轉(zhuǎn)換操作;相酉面的其他數(shù)據(jù)報(bào)都將根據(jù)第一種數(shù)據(jù)報(bào)H勺成果

進(jìn)行相似的轉(zhuǎn)換處理。

mangle:數(shù)據(jù)報(bào)修改表(位于net/ipv4/netfilter/iptablemangle,c)

監(jiān)聽(tīng)NF_IP_PRE_ROUTING和NF」P_LOCAL_OUT兩個(gè)HOOK,作用是修改數(shù)據(jù)報(bào)報(bào)頭中的某些值。

2.表的實(shí)現(xiàn)

表日勺基石數(shù)據(jù)構(gòu)造是ipttable(位于include/linux/netfilter_ipv4/ip_tables.h,Line413):

structipttable

structlist_headlist;//一種雙向鏈表

charname[IPTTABLEMAXNAMELEN];//被顧客空間使用的表函數(shù)的名字

structipt_replacestable;//表初始化歐I模板,定義了一種初始化用的該表口勺所默認(rèn)

的HOOK所包括的規(guī)則等信息,顧客通過(guò)系統(tǒng)調(diào)用進(jìn)行表的替代時(shí)也要用

unsignedintvalid_hooks;//表所監(jiān)聽(tīng)/、JHOOK,實(shí)質(zhì)是一種位圖

rwlock_tlock;//整個(gè)表口勺讀/寫(xiě)自旋鎖

structipt_table_info*private;//表所存儲(chǔ)的數(shù)據(jù)信息,也就是實(shí)際住)數(shù)據(jù)區(qū),僅在處

理ipt_table口勺代碼內(nèi)部使用

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

};

其中:

unsignedintvalid_hooks;這個(gè)位圖有兩個(gè)作用:一是檢查NetfiIter中哪些HOOK對(duì)應(yīng)著合法日勺

entries;二是用來(lái)為iptmatch以及ipttarget數(shù)據(jù)構(gòu)造中的checkentry()函數(shù)核算也許的IHOOK。

structmodule*n】e;當(dāng)取值為T(mén)HIS_MODULE時(shí),可以制止顧客rmmod一種仍然被某個(gè)規(guī)則指向的)模塊的

嘗試。

structipt.replacestable;的數(shù)據(jù)構(gòu)造是被顧客空間用來(lái)替代一種表的,其定義位于

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

structipt_replace

(

charname[IPT_TABLE_MAXNAMELEN];

unsignedintvalid_hooks;

unsignedintnumcntrics;//規(guī)則表入口的數(shù)量

unsignedintsize;//新的規(guī)則表的J總大小

/.Hoo.entr.points.*/

unsignedinthookentry[NF_IP_NUMHOOKS];//表所監(jiān)聽(tīng)HOOK的J規(guī)則入口,是對(duì)于cntriesE]

M扁移

unsignedintunderflow[NF_ZP_NUMHOOKS];//規(guī)則表/、J最大卜界

unsignedintnumcounters;//IH膚J計(jì)數(shù)器數(shù)目,即目前歐I舊entries隹J數(shù)目

structipt_countcrs"counters;//舊口勺計(jì)數(shù)器

structipt_entryentries[0];//規(guī)則表入口

);

上文所提到的filter,nat和mangle表分別是ipt_table這個(gè)數(shù)據(jù)構(gòu)造的三個(gè)實(shí)例:

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)是實(shí)際描述規(guī)則表的I數(shù)據(jù)構(gòu)造:

structipt_table_info

(

unsignedintsize;

unsignedintnumber;//表項(xiàng)的數(shù)目

unsignedintinitial_entries;//初始表項(xiàng)數(shù)目

unsignedinthook_entry[NF_IP_NUMHOOKS];//所監(jiān)聽(tīng)HOOK的規(guī)則入口

unsignedintunderflow[NF_ZP_NUMHOOKS];//規(guī)則表的J最大下界

charentries[0];//規(guī)則表入口,即真正日勺規(guī)則存儲(chǔ)構(gòu)造ipt_entry

構(gòu)成塊日勺起始地址,對(duì)多CPU,每個(gè)CPU對(duì)應(yīng)一種

};

3.規(guī)則的實(shí)現(xiàn)

IPTables中日勺規(guī)則表可以在顧客空間中使用,但它所采用的數(shù)據(jù)構(gòu)造與內(nèi)核空間中日勺是同樣的,

只不過(guò)有些組員不會(huì)在顧客空間中使用。

一種完整H勺規(guī)則由三個(gè)數(shù)據(jù)構(gòu)造共同實(shí)現(xiàn),分別是:

1個(gè)ipjentry構(gòu)造,存儲(chǔ)規(guī)則的整體信息;

0或多種ipt_entry_match構(gòu)造,寄存多種match,每個(gè)構(gòu)造都可以寄存任意日勺數(shù)據(jù),這樣也就擁有了良

好日勺可擴(kuò)展性;

1個(gè)ipt_ent門(mén)「target構(gòu)造,寄存規(guī)則日勺target,類似的,每個(gè)構(gòu)造也可以寄存任意日勺數(shù)據(jù)。

下面將依次對(duì)這三個(gè)數(shù)據(jù)構(gòu)造進(jìn)行分析:

存儲(chǔ)規(guī)則整體日勺構(gòu)造ipt_entry,其形式是一種鏈表(位于

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

structipt_entry

structipt_ipip;

unsignedintnfcache;

uint!6ttargetoffset;

uintl6tnextoffset;

unsignedintcomefrom;

structipt_counterscounters;

unsignedcharelems[0];

};

其組員如下:

structipt_ipip;:這是對(duì)其將要進(jìn)行匹配動(dòng)作日勺TP數(shù)據(jù)報(bào)報(bào)頭日勺描述,其定義于

include/linux/netfilter_ipv4/ip_tables.h,Linel22,其組員包括源/目的IIP及其掩碼,出入端口及

其掩碼,協(xié)議族、標(biāo)志/取反flag?信息。

unsignedintnfcache;:HOOK函數(shù)返回cache標(biāo)識(shí),用以闡明通過(guò)這個(gè)規(guī)則后數(shù)據(jù)報(bào)『、J狀態(tài),其也

許值有三個(gè),定義于include/linux/netfilter.h,Line23:

#defineNFC_ALTERED0x8000〃已變化

#defineNFC_UNKNOWN0x4000〃萬(wàn)確定

另一種乜許值是0,即沒(méi)有變化.

u_intl6_ttargetoffset;:指出了target日勺數(shù)據(jù)構(gòu)造ipt_cntry_targct%J起始位置,即從ipt_cntry

的起始地址到match存儲(chǔ)結(jié)束的位置

u_intl6_tncxt_offsct;:指出了整條規(guī)則的大小,也就是下一條規(guī)則H勺起始地址,即ipt_cntry的)起

始地址到match偏移再到target存儲(chǔ)結(jié)束的位置

unsignedintcomefrom;:所謂『、J"backpointer”,據(jù)引用此變量『、J代碼(重要是

net/ipv4/netfilter/ip_tables.c中)來(lái)看,它應(yīng)當(dāng)是指向數(shù)據(jù)報(bào)所經(jīng)歷『、J上一種規(guī)則地址,由此實(shí)現(xiàn)

對(duì)數(shù)據(jù)報(bào)行為的跟蹤

structipt_counterscounters;:闡明了匹配這個(gè)規(guī)則日勺數(shù)據(jù)報(bào)日勺計(jì)數(shù)以及字節(jié)計(jì)數(shù)(定義于

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

unsignedcharelems[0];:表達(dá)擴(kuò)展的malch開(kāi)始口勺詳細(xì)位置(由于它是大小不確定的),當(dāng)然,假如

不存在擴(kuò)展的Imatch那么就是target日勺開(kāi)始位置

擴(kuò)展match日勺存儲(chǔ)構(gòu)造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;//總長(zhǎng)度

}u:

unsignedchardata[0];

);

其中描述match大小的match_size;',從波及這個(gè)變量日勺源碼看來(lái),在使用H勺時(shí)候需要

注意使月一種宏IPT_ALIGN(位于includc/linux/netfiltcr_ipv4/ip_tables.h,Linc445)來(lái)進(jìn)行4

的對(duì)齊處理(0x3&Oxfffffffc),這應(yīng)當(dāng)是由于match、target擴(kuò)展后大小的不確定性決定的J。

在構(gòu)造中,顧客空間與內(nèi)核空間為不一樣的J實(shí)現(xiàn),內(nèi)核空間中的描述擁有更多歐J信息。在顧客空間

中寄存的僅僅是match日勺名稱,而在內(nèi)核空間中寄存的則是一種指向iptjnatch構(gòu)造的指針

構(gòu)造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,//指向規(guī)則中match數(shù)據(jù)的指針,詳細(xì)是什么數(shù)據(jù)構(gòu)造依狀

況而定

intoffset,//TP數(shù)據(jù)報(bào)的偏移

constvoid*hdr,//指向協(xié)議頭口勺指針

u_intl6_tdatalen,//實(shí)際數(shù)據(jù)長(zhǎng)度,即數(shù)據(jù)報(bào)長(zhǎng)度TP頭長(zhǎng)度

int*hotdrop);

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

conststructipt_ip*ip,

void*matchinfo,

unsignedintmatchinfosize,

unsignedinthookmask);//對(duì)應(yīng)HOOKH勺位圖

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

structmodule

);

其中幾種重要組員:

int(*match)(....);:指向用該natch進(jìn)行匹配時(shí)『、J匹配函數(shù)的指針,match有關(guān)的J關(guān)鍵實(shí)現(xiàn)。返回0

時(shí)hotdrop置1,立即丟棄數(shù)據(jù)報(bào);返回非0表達(dá)匹配成功。

int(*checkentry)(....);:當(dāng)試圖插入新的Imatch表項(xiàng)時(shí)調(diào)用這個(gè)指針?biāo)赶虻膢函數(shù),對(duì)新的Jmatch

表項(xiàng)進(jìn)行有效性檢查,即檢查參數(shù)與否合法;假如返回false,規(guī)則就不會(huì)被接受(譬如,一種TCP的

match只會(huì)TCP包,而不會(huì)接受其他)。

void("destroy)(....);:當(dāng)試圖刪除一種使用這個(gè)match日勺表項(xiàng)時(shí),即模塊釋放時(shí),調(diào)用這個(gè)指針?biāo)?/p>

指向的函數(shù)。我們可以在checkentry中動(dòng)態(tài)地分派資源,并在destroy中將其釋放。

擴(kuò)展target的J存儲(chǔ)構(gòu)造ipt_entry_target,位于include/linux/netfilter_ipv4/ip_tables.h,

Line71,這個(gè)構(gòu)造與ipt_entrymatch構(gòu)造類似。

同步其中描述內(nèi)核空間target時(shí)構(gòu)造ipt_target(位于include/linux/netfilter_ipv4/ip_tables.h,

Line375)也與ipt_match類似,只不過(guò)其中口勺target()函數(shù)返回值不是0/1,而是verdict。

而target的實(shí)際使用中,是用一種構(gòu)造ipt_standard_target專門(mén)來(lái)描述,這才是實(shí)際的target

描述數(shù)據(jù)構(gòu)造(位于include/1inux/netfilter_ipv4/ip_tables.h,Line94),它實(shí)際上就是一種

ipt_entry_target力口——種verdict。

其中組員verdict這個(gè)變量是一種很巧妙的設(shè)計(jì),也是一種非常重要的東東,其值日勺正負(fù)有著不一樣的

意義.我沒(méi)有找到這個(gè)變量H勺中文名稱,在內(nèi)核開(kāi)發(fā)者日勺新聞組中稱這個(gè)變量為“amagicnumberL它

時(shí)也許值包括IPT_C0NTINUE>IPT_RETURN以及前文所述的INF_DR0P等值,那么它日勺作月是什么呢?

由于IPTablcs是在顧客空間中執(zhí)行的,也就是說(shuō)Nctfiltcr/IPTablcs這個(gè)框架需要顧客態(tài)與內(nèi)核態(tài)之

間日勺數(shù)據(jù)互換以及識(shí)別。而在詳細(xì)日勺程序中,verdict作為'structipt_standard_target'及J一種組員,

也是對(duì)于struclipt_entrytarget'中口勺target()函數(shù)Rj返回值。這個(gè)返回值標(biāo)識(shí)的是target()所對(duì)

應(yīng)日勺執(zhí)行動(dòng)作,包括系統(tǒng)的I默認(rèn)動(dòng)作以及外部提交的自定義動(dòng)作。

不過(guò),在顧客空間中提交的I數(shù)據(jù)往往是類似于“ACCPET”之類的I字符串,在程序處理時(shí)則是以^define

NF_ACCEPT1'日勺形式來(lái)進(jìn)行的;而實(shí)際上,以上那些執(zhí)行動(dòng)作是以鏈表H勺數(shù)據(jù)構(gòu)造進(jìn)行存儲(chǔ)H勺,在內(nèi)核

空間中體現(xiàn)為偏移。

于是,verdict實(shí)際上描述了兩個(gè)本質(zhì)相似但實(shí)現(xiàn)不一樣的值:一種是顧客空間中的執(zhí)行動(dòng)作,另一種

則是內(nèi)核空間中在鏈表中的偏移一而這就出現(xiàn)了沖突。

處理這種沖突日勺措施就是:用正值表達(dá)內(nèi)核中歐I偏移,而用負(fù)值來(lái)表達(dá)數(shù)據(jù)報(bào)歐I那些默認(rèn)動(dòng)作,而外部

提交的自定義動(dòng)作則也是用正值來(lái)表達(dá)。這樣,在實(shí)際使用這個(gè)verdict時(shí),我們就可以通過(guò)判斷值的

正負(fù)來(lái)進(jìn)行對(duì)應(yīng)時(shí)處理了。

位于net/ipv4/netfilter/ip_tables.h中的)函數(shù)ipt_do_table()中有一種經(jīng)典的verdict使用

(Line335,其中v是一種verdict歐J實(shí)例):

if(v!=IPT_RETURN){

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

break;

其中MJTT其TURN定義為:

SdefineTPTRETURN(-NFMAXVERDICT-1)

而宏NF_MAX_VERDICT實(shí)際上就是:

#defineNF_MAX_VERDICTNF_REPEAT

這樣,實(shí)際上TPTRETURN口勺值就是-NFREPEAT7,也就是對(duì)應(yīng)REPEAT,這就是對(duì)執(zhí)行動(dòng)作的實(shí)際

描述;而我們可以看到,在下面對(duì)verdict進(jìn)行賦值時(shí),它所使用日勺值是'(unsigned)(-v)-1',這就

是在內(nèi)核中實(shí)際對(duì)偏移進(jìn)行定位時(shí)所使用的值。

那么總之呢,表和規(guī)則的實(shí)現(xiàn)如圖所示:

圖6.表和規(guī)則的實(shí)現(xiàn)

從上圖中不難發(fā)現(xiàn),match的)定位如下:

起始地址為:目前規(guī)則(起始)地址+sizeof(structipt_entry);

結(jié)束地址為:目前規(guī)則(起始)地址+ipt_entry->target_offset;

每一種natch日勺大小為:ipt_entry_match->u.matchesizeo

target的定位則為:

起始地址為match日勺結(jié)束地址,即:目前規(guī)則(起始)地址一ipt_entry->target_offset;

結(jié)束地址為下一條規(guī)則日勺起始地址,即:目前規(guī)則(起始)地址+ipt_entry->next_offset;

每一種target的大小為:iptentrytarget->u.targetsize。

這些對(duì)于理解match以及target有關(guān)函數(shù)的實(shí)現(xiàn)是很有必要明確H勺。

同步,include/linux/netfilter_ipv4/ip_tables.h中提供了三個(gè)"helperfunctions”,可用于

使對(duì)于entry、tartget和matchH勺操作變得以便,分別是:

函數(shù)ipt_get_target():Line274,作用是獲得target日勺起始地址,也就是上面所說(shuō)的目前規(guī)則(起始)

地址+iptentry->targetoffset;

宏中1'_"八花也"£1^^():小區(qū)28:,作用是遍歷規(guī)則的所有g(shù)1:2,并執(zhí)行同一種(參數(shù)中)給定的函

數(shù)。其參數(shù)為一種ipt_entry_match構(gòu)造和一種函數(shù),以及函數(shù)需要時(shí)參數(shù)。當(dāng)返回值為0時(shí),表達(dá)遍

歷以及函數(shù)執(zhí)行順利完畢;返回非。值時(shí)則意味著出現(xiàn)問(wèn)題已終止。

宏小丁_£皿^丫」丁£!^^():一區(qū)300,作用是遍歷一種表中的)所有規(guī)則,并執(zhí)行同一種給定的函數(shù)。其參

數(shù)為一種ipl_enlry構(gòu)造、整個(gè)規(guī)則表口勺大小,以及一種函數(shù)和其所需參數(shù)。其返回值的意義與宏

IPT_MATCH_ITERATE()類似。

那么怎樣保證傳入日勺ipt_entry構(gòu)造是整個(gè)規(guī)則表歐I第一種構(gòu)造呢?據(jù)源碼看來(lái),實(shí)際調(diào)用這個(gè)宏的

時(shí)候傳入的第一種參數(shù)都是某個(gè)ipt_table_info構(gòu)造的實(shí)例所指向的entries組員,這樣就保證了對(duì)整

個(gè)規(guī)則表的完整遍歷。

4.規(guī)則的使用

當(dāng)一種特定的HOOK被激活時(shí),數(shù)據(jù)報(bào)就開(kāi)始進(jìn)入Netfilter/TPTables系統(tǒng)進(jìn)行遍歷,首先檢卷

'structipt_ipip',然后數(shù)據(jù)報(bào)將依次遍歷各個(gè)match,乜就是'structipt_entry_match',并執(zhí)行

對(duì)應(yīng)的match函數(shù),即ipt_match構(gòu)造中區(qū)|*match所指向H勺函數(shù)。當(dāng)match函數(shù)匹配不成功時(shí)返回0,或

者h(yuǎn)otdrop被置為1時(shí),遍歷將會(huì)停止。

對(duì)natch/、J遍歷完畢后,會(huì)開(kāi)始檢查'structipt_entry_targct',其中假如是一種原則『、Jtarget,

那么會(huì)檢查'structipt_standard_target'中的Jverdict,假如verdict值是正歐I而偏移卻指向不對(duì)的

的位置,那么ipl_entry中的comefrom組員就有了用武之地一一數(shù)據(jù)報(bào)返回所經(jīng)歷的上一種規(guī)則。對(duì)于

非原則日勺target呢,就會(huì)調(diào)用target()函數(shù),然后根據(jù)其返回值進(jìn)行背面日勺處理。

5.規(guī)則的擴(kuò)展

Netfilter/IPTables提供了對(duì)規(guī)則進(jìn)行擴(kuò)展日勺機(jī)制:可以寫(xiě)一種LKM來(lái)擴(kuò)展內(nèi)核空間的功能,

也可以寫(xiě)一種共享庫(kù)來(lái)擴(kuò)展顧客空間中IPTables曰勺功能。

內(nèi)核H勺擴(kuò)展

要對(duì)內(nèi)核空間口勺功能進(jìn)行擴(kuò)展,實(shí)際上就是寫(xiě)一種具有表、match以及target增長(zhǎng)功能口勺模塊,有

關(guān)日勺函數(shù)為(位于net/ipv4/netf[lter/ip_tables.c,Linel318to1444):

ipt_register_table()>ipt_unregister_table(),參數(shù)為structipt_table*。

ipt_register_table()函數(shù)是這三對(duì)函數(shù)中最復(fù)雜的一種,波及了內(nèi)存、信號(hào)量等方方面面口勺東西,但

總起來(lái)說(shuō)就做了初始化表以及加入雙向鏈表兩件事。

其復(fù)雜一是由于波及到多CPU的處理(每個(gè)CPU擁有各自獨(dú)立的“規(guī)則空間”),需要首先將新日勺entries

放入第一種CPU空間,在檢查完畢后再?gòu)?fù)制到其他CPU中;二是就是上面所說(shuō)對(duì)新tab*各個(gè)entry的

檢查,包括邊界檢查以及完整性檢查等。

其中的重要函數(shù)有這樣幾種:

translate_table()(位于net/ipv4/netfilter/ip_tables.c,Line797):這個(gè)函數(shù)聆)重要作用是檢查

并應(yīng)用顧容空間傳來(lái)的規(guī)則:

對(duì)新表進(jìn)行邊界檢查(由宏1PT_ENTRY_ITERATE()調(diào)用函數(shù)check_entry_size_and_Dlocks(),位于

net/ipv4/netfilter/iptables.c,Line732),包括對(duì)齊、過(guò)大過(guò)小等,尤其是保證賦給hookentries

和underflows值日勺對(duì)歐I性。

調(diào)用函數(shù)make_source_chains()(位于net/ipv4/netfilter/ip_tables.c,Line499)檢查新歐I表中與

否存在規(guī)則環(huán),同步將HOOKH勺規(guī)則遍歷次序存入comefrom變量。(這個(gè)函數(shù)我沒(méi)有仔細(xì)看,只是大概略

了一下)

對(duì)ipt_entry依次進(jìn)行ipt_ip頭、match以及target的完整性檢查(由宏IPT_ENTRY」TERATE()調(diào)用函

數(shù)check_entry(),位于net/ipv4/netfilter/ip_tables.c,Line676),保證ipt_entry對(duì)時(shí)性。

將龍?日勺的ipt_tablcs復(fù)制給其他的CPU。

這個(gè)函數(shù)此外還在do_replace()函數(shù)(僅在一種源碼中沒(méi)有被調(diào)用過(guò)H勺函數(shù)中被調(diào)用,不予分析)中被

調(diào)用。

replacetable0(位于net/ipv4/netfilter/iptables.c,Line877):這個(gè)函數(shù)的J重要作用是:將得

到模塊初始值日勺ipt_table_info構(gòu)造(newinfo)中日勺值傳給ipt_table中歐)private,并返回ip_table

中舊aJprivate0

list_prepend()(位于include/linux/netfilter_ipv4/listhelp.h,Line75):在這個(gè)函數(shù)被調(diào)用之

前,火人初始化的過(guò)程就已經(jīng)結(jié)束了,這個(gè)函數(shù)『、金要作用是:互斥地調(diào)用Linux源碼中的list_add()

函數(shù)(位于include/linux/list.h,Line55),將新的Itable加入到雙向鏈表之中。

ipt_registerjnatch()>ipt_unregister_match(),參數(shù)為structipt_match*。

ipt_registertarget()Nipt_unregistertarget(),參數(shù)為structipt_target*0

這三對(duì)函數(shù)除了ipt_register_table()外的5個(gè)函數(shù)重要就是互斥地將table/match/target加入

到雙向鏈表中或者從雙向鏈表中刪除。

其中向雙向鏈表中加入新節(jié)點(diǎn)是通過(guò)調(diào)用list_named_inscrt()函數(shù)(位于

include/linux/netfilter_ipv4/listhelp.h,LinelOl)實(shí)現(xiàn)的I。這個(gè)函數(shù)H勺重要工作是首先確定待插

入的match名字與否已經(jīng)加在,只有不存在時(shí)才進(jìn)行插入的操作。

顧客空間口勺擴(kuò)展

顧客空間中的擴(kuò)展用的是共享庫(kù)配合libiptc庫(kù)的機(jī)制,但這種機(jī)制是在單獨(dú)日勺IPTbales程序中提

供日勺,內(nèi)核源碼中并沒(méi)有提供,這里就不做分析了。

五、數(shù)據(jù)報(bào)過(guò)濾模塊一一filter表

1.概述

filter表日勺功能僅僅是本數(shù)據(jù)報(bào)進(jìn)行過(guò)濾,并不對(duì)數(shù)據(jù)報(bào)進(jìn)行任何日勺修改。

filter模塊在Netfilter中是基于下列HOOK點(diǎn)的J:

NF_IP_LOCAL_IN

NF_IP_FORWARD

NF_IP_LOCAL_OUT

這幾種HOOK分別對(duì)應(yīng)著filter表中的INPUT>FORWARD.OUTPUT三條規(guī)則鏈,對(duì)于任何一種數(shù)

據(jù)報(bào)都會(huì)通過(guò)這3個(gè)HOOK之一。

filter模塊的I接口位于文獻(xiàn)net/ipv4/netfilter/iptables_filter.c中。

2.filter表的定義和初始化

filter表是前面所述數(shù)據(jù)構(gòu)造ipt_tablc的一種實(shí)例,它的定義和初始化位于

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

staticstructipt_tablepacket_filter={

{NULL,NULL),

&initial_table.repl,//對(duì)應(yīng)replace數(shù)據(jù)構(gòu)造

FILTER_VALID_HOOKS,

RW_LOCK_UNLOCKED,

NULL,//對(duì)應(yīng)private數(shù)據(jù)構(gòu)造

THISMODULE

};

對(duì)照構(gòu)造ipt_table的定義,我們可以發(fā)現(xiàn),filter表日勺初始化數(shù)據(jù)為:

鏈表初始化為空

表名為filter

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

初始化的模板表定義于net/ipv4/netfi1ter/iptable_fi1ter.c,Line30,是一種很簡(jiǎn)樸日勺數(shù)據(jù)構(gòu)造,

只是賦值有些復(fù)雜,由于要對(duì)所波及的各個(gè)HOOK進(jìn)行示一樣日勺處理:

staticstruct

(

structipt_replacerepl;

structipt_standardentries[3];

structipt_errorterm;

}initial_table={

//對(duì)構(gòu)造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,

(}

},

//對(duì)構(gòu)造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

)

},

//對(duì)構(gòu)造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)},

//對(duì)構(gòu)造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)}

),

//對(duì)構(gòu)造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包括三個(gè)組員:

structipt_replacercpl;:是對(duì)一種表進(jìn)行初始化的I最重要

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論