免费高清特黄a大片,九一h片在线免费看,a免费国产一级特黄aa大,国产精品国产主播在线观看,成人精品一区久久久久,一级特黄aa大片,俄罗斯无遮挡一级毛片

分享

洞悉linux下的Netfilter&iptables:狀態(tài)防火墻

 mrjbydd 2012-11-20

基于連接跟蹤機(jī)制的狀態(tài)防火墻的設(shè)計(jì)與實(shí)現(xiàn)

連接跟蹤本身并沒(méi)有實(shí)現(xiàn)什么具體功能,它為狀態(tài)防火墻和NAT提供了基礎(chǔ)框架。前面幾章節(jié)我們也看到:從連接跟蹤的職責(zé)來(lái)看,它只是完成了數(shù)據(jù)包從“個(gè)性”到“共性”抽象的約定,即它的核心工作是如何針對(duì)不同協(xié)議報(bào)文而定義一個(gè)通用的“連接”的概念出來(lái),具體的實(shí)現(xiàn)由不同協(xié)議自身根據(jù)其報(bào)文特殊性的實(shí)際情況來(lái)提供。那么連接跟蹤的主要工作其實(shí)可以總結(jié)為:入口處,收到一個(gè)數(shù)據(jù)包后,計(jì)算其hash值,然后根據(jù)hash值查找連接跟蹤表,如果沒(méi)找到連接跟蹤記錄,就為其創(chuàng)建一個(gè)連接跟蹤項(xiàng);如果找到了,則返回該連接跟蹤項(xiàng)。出口處,根據(jù)實(shí)際情況決定該數(shù)據(jù)包是被還給協(xié)議棧繼續(xù)傳遞還是直接被丟棄。

    我們先看一下iptables指南中關(guān)于用戶空間中數(shù)據(jù)包的四種狀態(tài)及其解釋:

狀態(tài)

解釋

NEW

NEW說(shuō)明這個(gè)包是我們看到的第一個(gè)包。意思就是,這是conntrack模塊看到的某個(gè)連接第一個(gè)包,它即將被匹配了。比如,我們看到一個(gè)SYN包,是我們所留意的連接的第一個(gè)包,就要匹配它。第一個(gè)包也可能不是SYN包,但它仍會(huì)被認(rèn)為是NEW狀態(tài)。這樣做有時(shí)會(huì)導(dǎo)致一些問(wèn)題,但對(duì)某些情況是有非常大的幫助的。例如,在我們想恢復(fù)某條從其他的防火墻丟失的連接時(shí),或者某個(gè)連接已經(jīng)超時(shí),但實(shí)際上并未關(guān)閉時(shí)。

ESTABLISHED

ESTABLISHED已經(jīng)注意到兩個(gè)方向上的數(shù)據(jù)傳輸,而且會(huì)繼續(xù)匹配這個(gè)連接的包。處于ESTABLISHED狀態(tài)的連接是非常容易理解的。只要發(fā)送并接到應(yīng)答,連接就是ESTABLISHED的了。一個(gè)連接要從NEW變?yōu)?/span>ESTABLISHED,只需要接到應(yīng)答包即可,不管這個(gè)包是發(fā)往防火墻的,還是要由防火墻轉(zhuǎn)發(fā)的。ICMP的錯(cuò)誤和重定向等信息包也被看作是ESTABLISHED,只要它們是我們所發(fā)出的信息的應(yīng)答。

RELATED

RELATED是個(gè)比較麻煩的狀態(tài)。當(dāng)一個(gè)連接和某個(gè)已處于ESTABLISHED狀態(tài)的連接有關(guān)系時(shí),就被認(rèn)為是RELATE的了。換句話說(shuō),一個(gè)連接要想是RELATED的,首先要有一個(gè)ESTABLISHED的連接。這個(gè)ESTABLISHED連接再產(chǎn)生一個(gè)主連接之外的連接,這個(gè)新的連接就是RELATED的了,當(dāng)然前提是conntrack模塊要能理解RELATED。ftp是個(gè)很好的例子,FTP-data 連接就是和FTP-controlRELATED的。還有其他的例子,比如,通過(guò)IRCDCC連接。有了這個(gè)狀態(tài),ICMP應(yīng)答、FTP傳輸、DCC等才能穿過(guò)防火墻正常工作。注意,大部分還有一些UDP協(xié)議都依賴這個(gè)機(jī)制。這些協(xié)議是很復(fù)雜的,它們把連接信息放在數(shù)據(jù)包里,并且要求這些信息能被正確理解。

INVALID

INVALID說(shuō)明數(shù)據(jù)包不能被識(shí)別屬于哪個(gè)連接或沒(méi)有任何狀態(tài)。有幾個(gè)原因可以產(chǎn)生這種情況,比如,內(nèi)存溢出,收到不知屬于哪個(gè)連接的ICMP 錯(cuò)誤信息。一般地,我們DROP這個(gè)狀態(tài)的任何東西。

    認(rèn)真體會(huì)這個(gè)表格所表達(dá)意思對(duì)我們理解狀態(tài)防火墻的機(jī)制和實(shí)現(xiàn)有很大的幫助。我們以最常見的TCP、UDPICMP協(xié)議為例來(lái)分析,因?yàn)樗麄冏畛R?。?duì)于TCP/UDP來(lái)說(shuō),我們可以用“源/目的IP+/目的端口”唯一的標(biāo)識(shí)一條連接;因?yàn)?/span>ICMP沒(méi)有端口的概念,因此對(duì)ICMP而言,其“連接”的表示方法為“源/目的IP+類型+代碼+ID”。因此,你就可以明白,如果你有一種不同于目前所有協(xié)議的新協(xié)議要為其開發(fā)連接跟蹤功能,那么你必須定以一個(gè)可以唯一標(biāo)識(shí)該報(bào)文的規(guī)格,這是必須的。

    接下來(lái)我就拋磚引玉,分析一下NEWESTABLISHED、RELATEDINVALID幾種狀態(tài)內(nèi)核中的變遷過(guò)程。


    針對(duì)于NEW狀態(tài)的理解:

依舊在ip_conntrack_in()函數(shù)中,只不過(guò)我們這次的側(cè)重點(diǎn)不同。由于該報(bào)文是某條連接的第一個(gè)數(shù)據(jù)包,ip_conntrack_find_get()函數(shù)中根據(jù)該數(shù)據(jù)包的tuple在連接跟蹤表ip_conntrack_hash中肯定找不到對(duì)應(yīng)的連接跟蹤記錄,然后重任就交給了init_conntrack()函數(shù):

如果連接跟蹤數(shù)已滿,或沒(méi)有足夠的內(nèi)存時(shí),均會(huì)返回錯(cuò)誤。否則,將新連接跟蹤記錄的引用計(jì)數(shù)置為1,設(shè)置連接跟蹤記錄“初始”和“應(yīng)答”方向的tuple鏈,同時(shí)還設(shè)置了連接跟蹤記錄被銷毀和超時(shí)的回調(diào)處理函數(shù)destroy_conntrack()death_by_timeout()等。

    至此,我們新的連接記錄ip_conntrack{}就華麗麗滴誕生了。每種協(xié)議必須對(duì)其“新連接記錄項(xiàng)”提供一個(gè)名為new()的回調(diào)函數(shù)。該函數(shù)的主要作用就是針對(duì)不同協(xié)議,什么樣的報(bào)文才被稱為“new”狀態(tài)必須由每種協(xié)議自身去考慮和實(shí)現(xiàn)。具體我就不深入分析了,大家只要知道這里有這么一出戲就可以了,感興趣的朋友可以去研究研究。當(dāng)然,這需要對(duì)協(xié)議字段和意義有比較透徹清晰的了解才能完全弄明白別人為什么要那么設(shè)計(jì)。畢竟我們不是去為TCPUDPICMP開發(fā)連接跟蹤,開源界的信條就是“永遠(yuǎn)不要重復(fù)發(fā)明車輪”。如果你想深入研究現(xiàn)有的東西,目的只有一個(gè):那就是學(xué)習(xí)別人的優(yōu)點(diǎn)和長(zhǎng)處,要有重點(diǎn),有主次的去學(xué)習(xí),不然會(huì)讓自己很累不說(shuō),還會(huì)打擊求知的積極性和動(dòng)力。

閑話不都說(shuō),我們繼續(xù)往下分析。如果該數(shù)據(jù)包所屬的協(xié)議集提供了helper接口,那么將其掛到conntrack->helper的回調(diào)接口上。最后,將該連接跟蹤項(xiàng)“初始”方向的tuple鏈添加到一條名為unconfirmed的全局鏈表中,該鏈表里存儲(chǔ)的都是截止到目前為止還未曾收到“應(yīng)答”方向數(shù)據(jù)包的連接跟蹤記錄。

費(fèi)了老半天勁兒,狀態(tài)防火墻終于出來(lái)和大家見面了:

ip_ct_get_tuple()函數(shù)里初始化時(shí)tuple.dst.dir就被設(shè)置為了IP_CT_DIR_ORIGINAL,因?yàn)槲覀冇懻摰木褪?/span>NEW狀態(tài)的連接,tuple.dst.dir字段到目前為止還未被改變過(guò),與此同時(shí),ip_conntrack.status位圖自從被創(chuàng)建之日起經(jīng)過(guò)memset()操作后就一直為全0狀態(tài),才有最后的skb->nfctinfo=*ctinfo=IP_CT_NEWskb->nfct = &ip_conntrack->ct_general。

繼續(xù)回到ip_conntrack_in()函數(shù)里,此時(shí)調(diào)用協(xié)議所提供的回調(diào)packet()函數(shù)。在博文六中我們?cè)峒斑^(guò),該函數(shù)承擔(dān)著數(shù)據(jù)包生死存亡的使命。這里我們有必要注意一下packet()函數(shù)最后給Netfilter框架返回值的一些細(xì)節(jié):

-1,其實(shí)就是-NF_ACCEPT,意思是:連接跟蹤出錯(cuò)了,該數(shù)據(jù)包不是有效連接的一部分,Netfilter不要再對(duì)這類報(bào)文做跟蹤了,調(diào)用前面的回調(diào)函數(shù)destroy()清除已經(jīng)為其設(shè)置的連接跟蹤項(xiàng)記錄項(xiàng),釋放資源。最后向Netfilter框架返回ACCEPT,讓該數(shù)據(jù)包繼續(xù)傳輸。

0,就是NF_DROP,返回給Netfilter框架的也是該值,那么這數(shù)據(jù)包就掛在這里了。

1,就是NF_ACCEPT,同樣,該數(shù)據(jù)包已經(jīng)被正確跟蹤了,通知Netfilter框架繼續(xù)傳輸該數(shù)據(jù)包。

對(duì)于像TCP這樣非常復(fù)雜的協(xié)議才用到了NF_DROP操作,像UDP、ICMPGRE、SCTP等協(xié)議都沒(méi)有到,但不排除你的項(xiàng)目中使用NF_DROP的情形。

在連接跟蹤的出口處的ip_conntrack_confirm()函數(shù)中,如果已經(jīng)為該數(shù)據(jù)包skb創(chuàng)建了連接跟蹤記錄ip_conntrack{}(skb->nfct有值),則做如下處理:

如果該連接還沒(méi)有收到回復(fù)報(bào)文----明顯如此;

如果該連接沒(méi)有掛掉----毫無(wú)疑問(wèn)。

因?yàn)槭切逻B接,因此在全局鏈表數(shù)組ip_conntrack_hash[]就沒(méi)有記錄該連接“初始”和“應(yīng)答”方向的tuplehash鏈。然后,緊接著我把該連接初始方向的tuplehaship_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].listunconfirmed鏈表上卸下來(lái)。并且,將該連接初始和應(yīng)答方向的tuplehash鏈表根據(jù)其各自的hash之加入到ip_conntrack_hash[]里,最后啟動(dòng)連接跟蹤老化時(shí)間定時(shí)器,修改引用計(jì)數(shù),將ip_conntrack.status狀態(tài)位圖更新為IPS_CONFIRMED_BIT,并向Netfilter框架返回NF_ACCEPT。數(shù)據(jù)包離開Netfilter繼續(xù)在協(xié)議棧中傳遞。

針對(duì)于ESTABLISHED狀態(tài)的理解:

    每個(gè)ip_conntrack{}結(jié)構(gòu)末尾有兩條tuplehash鏈,分別代表“初始”和“應(yīng)答”方向的數(shù)據(jù)流向,如下圖所示:

    如果一條連接進(jìn)入ESTABLISHED,那么的前一狀態(tài)一定是NEW。因此,我們繼續(xù)前面的分析分析過(guò)程,當(dāng)我們的連接跟蹤記錄收到了其對(duì)應(yīng)的響應(yīng)報(bào)文后的處理流程。注意前面剛分析過(guò)的:對(duì)于新連接的狀態(tài)位圖status已經(jīng)被設(shè)置成IPS_CONFIRMED_BIT了。

    繼續(xù)在ip_conntrack_in()函數(shù),所以數(shù)據(jù)包從skbtuple的生成過(guò)程中,初始化時(shí)都有tuple->dst.dir = IP_CT_DIR_ORIGINAL;那么tuple->dst.dir是何時(shí)被改變狀態(tài)的呢?這就牽扯到一種很重要的通信機(jī)制netlink。連接跟蹤框架還為連接記錄的躍遷改變定義了一些事件處理和通知機(jī)制,而這目前不是本文的重點(diǎn)。在入口處,雖然從連接跟蹤表中找到了該tuple所屬的連接跟蹤記錄項(xiàng),但在過(guò)濾表中該報(bào)文有可能會(huì)被丟棄,因此不應(yīng)該急于改變回應(yīng)報(bào)文所屬的連接跟蹤記錄的狀態(tài),回應(yīng)報(bào)文也有skb->nfctinfo = *ctinfo=IP_CT_NEW,該數(shù)據(jù)包所屬的連接跟蹤記錄保存在skb->nfct里。在出口處,函數(shù)ip_conntrack_confirm()中,由于在NEW狀態(tài)時(shí),連接跟蹤記錄項(xiàng)中status=IPS_CONFIRMED_BIT了,因此這里對(duì)于響應(yīng)報(bào)文,不會(huì)重復(fù)執(zhí)行函數(shù)__ip_conntrack_confirm()

緊接著,當(dāng)“回應(yīng)”報(bào)文被連接跟蹤框架看到后,它會(huì)調(diào)用ip_ct_deliver_cached_events()函數(shù),以某種具體的事件通過(guò)netlink機(jī)制來(lái)通知ip_conntrack_netlink.c文件中的ctnetlink_parse_tuple()函數(shù)將初始方向的tuple->dst.dir = IP_CT_DIR_REPLY。這里理解起來(lái)稍微有點(diǎn)抽象,不過(guò)還是提醒大家抓重點(diǎn)思路,我們后面這幾章內(nèi)容相對(duì)來(lái)說(shuō)比前面幾章要稍微復(fù)雜些,這也是能力提升必須要經(jīng)歷的過(guò)程。

    至此,該連接跟蹤記錄ip_conntrack{}的數(shù)據(jù)我們來(lái)欣賞一下:

    如果該連接后續(xù)一個(gè)初始方向的數(shù)據(jù)包又到達(dá)了,那么在resolve_normal_ct()函數(shù)中,便會(huì)執(zhí)行設(shè)置skb->nfctinfo=*ctinfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLYset_reply=1,然后退出到ip_conntrack_in()里,將上圖中ip_conntrack{}結(jié)構(gòu)體里的status成員屬性由原來(lái)的IPS_CONFIRMED_BIT設(shè)置為IPS_SEEN_REPLY_BIT,并通過(guò)函數(shù)ip_conntrack_event_cache()觸發(fā)一個(gè)netlink狀態(tài)改變事件。最后,在ip_conntrack_confirm()里也只出發(fā)netlink事件而已。緊接著,第二個(gè)應(yīng)答方向的報(bào)文也到達(dá)了,和上面的處理動(dòng)作一樣。

 

    針對(duì)于RELATED狀態(tài)的理解:

    很多文章都從FTP協(xié)議的角度來(lái)剖析這個(gè)狀態(tài),確實(shí)FTP也是最能體現(xiàn)RELATED特性的協(xié)議。假如有個(gè)報(bào)文屬于某條已經(jīng)處于ESTABLISHED狀態(tài)的連接,我們來(lái)看看狀態(tài)防火墻是如何來(lái)識(shí)別這種情況。

    依然在resolve_normal_ct()函數(shù)中,執(zhí)行到init_conntrack()里面時(shí),通過(guò)數(shù)據(jù)包相對(duì)應(yīng)的tuple即可在全局鏈表ip_conntrack_expect_list里找到該連接所屬的主連接。然后將我們這條RELATED連接記錄的status= IPS_EXPECTED_BIT,并建立我們RELATED連接和它所屬的主連接之間的對(duì)應(yīng)關(guān)系conntrack->master = exp->master,同樣將其掛載到unconfirmed鏈里。返回到resolve_normal_ct()里,為數(shù)據(jù)包設(shè)置狀態(tài)值skb->nfctinfo = *ctinfo= IP_CT_RELATED。當(dāng)數(shù)據(jù)包將要離開時(shí),在ip_conntrack_confirm()函數(shù)中也會(huì)將其加入連接跟蹤表,并設(shè)置statusIPS_CONFIRMED_BIT。剩下的流程就和前面我們討論的是一樣了,唯一卻別的地方在于屬于RELATED的連接跟蹤,其master指向了它所屬的主連接跟蹤記錄項(xiàng)。

    INVALID狀態(tài)壓根兒就沒(méi)找著,汗。跟俺玩躲貓貓,哥還不鳥你捏。。。

    本篇的知識(shí)點(diǎn)相對(duì)來(lái)說(shuō)總體來(lái)說(shuō)比較抽象,內(nèi)容比較多,實(shí)現(xiàn)上也較為復(fù)雜,我在省略了其狀態(tài)躍遷流程情況下都還寫了這么多東西,很多地方研究的其實(shí)都不是很深入,只能感慨Netfilter的博大。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多