日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

洞悉linux下的Netfilter&iptables:網(wǎng)絡(luò)地址轉(zhuǎn)換原理之DNAT

 mrjbydd 2012-11-20

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

     NetfitlerNAT在內(nèi)核中維護了一張名為nat的表,用來處理所有和地址映射相關(guān)的操作。諸如filternat、mangle抑或raw這些在用戶空間所認(rèn)為的“表”的概念,在內(nèi)核中有的是以模塊的形式存在,如filter;有的是以子系統(tǒng)方式存在的,如nat,但它們都具有“表”的性質(zhì)。因此,內(nèi)核在處理它們時有很大一部操作都是相同的,例如表的初始化數(shù)據(jù)、表的注冊、鉤子函數(shù)的注冊等等。關(guān)于NAT表的初始化模板數(shù)據(jù)和表的注冊流程并不是本文的重點,大家可以對照第四篇博文中filter表的相關(guān)分析來研究。本文還是側(cè)重于從整體上對整個NAT子系統(tǒng)的設(shè)計思想和原理進行,當(dāng)然,有時間我還是會簡單和大家分析一NAT表的東西。因為最近確實太忙了,本來想著在四月份結(jié)束這個系列,無奈一轉(zhuǎn)眼就晃到了五月份,做IT的娃,都不容易?。?/span>

     通過前面的幾篇文章我們已經(jīng)知道,NAT的設(shè)計是獨立于連接跟蹤系統(tǒng)的,即連接跟蹤是NAT的基礎(chǔ)框架,我們還了解到連接跟蹤不會修改數(shù)據(jù)包,它只是負責(zé)維護數(shù)據(jù)包和其所屬的業(yè)務(wù)會話或數(shù)據(jù)連接狀態(tài)的相關(guān)信息而已。連接跟蹤最終是被iptables模塊所使用的,它所定義的那些狀態(tài)信息如NEWESTABLISHED、RELEATED等等,NAT統(tǒng)統(tǒng)不用關(guān)心。

     根據(jù)前面的hook函數(shù)掛載圖我們可以清晰的知道,對于那些需要被本機轉(zhuǎn)發(fā)的數(shù)據(jù)包,注冊在NF_IP_PRE_ROUTING點的ip_nat_in ()函數(shù)完成對其目的地址轉(zhuǎn)換的操作,注冊在NF_IP_POST_ROUTING點的ip_nat_out()函數(shù)完成源地址轉(zhuǎn)換任務(wù)。如果在編譯Linux內(nèi)核源碼時打開了CONFIG_IP_NF_NAT_LOCAL選項,則注冊在NF_IP_LOCAL_OUTNF_IP_LOCAL_IN點的hook函數(shù)就會工作,最常見的用法的是用NF_IP_LOCAL_OUT點的ip_nat_local_fn()函數(shù)來改變本機發(fā)出報文的目的地址。至于注冊在NF_IP_LOCAL_IN點的ip_nat_fn()函數(shù)一般不會起作用,只是當(dāng)數(shù)據(jù)包到達該HOOK點后會例行被調(diào)用一下。因為,NAT的所有規(guī)則只可能被配置到nat表的PREROUTING、POSTROUTINGOUTPUT三個點上,一般也很少有人去修改那些路由給本機的報文的源地址。

         NAT的分類如下圖所示:

    相信大家在看iptables用戶指南都見過這么一句解釋:

    只有每條連接的第一個數(shù)據(jù)包才會經(jīng)過nat表,而屬于該連接的后續(xù)數(shù)據(jù)包會按照第一個數(shù)據(jù)包則會按照第一個報所執(zhí)行的動作進行處理,不再經(jīng)過nat表。Netfilter為什么要做這個限制?有什么好處?它又是如何實現(xiàn)的?我們在接下來的分析中,將一一和大家探討這些問題。

    ip_nat_rule.c文件中定義了nat表的初始化數(shù)據(jù)模板nat_table,及相應(yīng)的target實體:SNATDNAT,并將其掛在到全局xt[PF_INET].target鏈表中。關(guān)于NAT所注冊的幾個hook函數(shù),其調(diào)用關(guān)系我們在前幾篇博文中也見過:

因此,我們的核心就集中在ip_nat_in()上。也就是說,當(dāng)我們弄明白了ip_nat_fn()函數(shù),你就差不多已經(jīng)掌握了nat的精髓。ip_nat_in()函數(shù)定義定在ip_nat_standalone.c文件里。連接跟蹤作為NAT的基礎(chǔ),而建立在連接跟蹤基礎(chǔ)上的狀態(tài)防火墻同樣服務(wù)于NAT系統(tǒng)。

    關(guān)于ip_nat_fn()函數(shù)我們還是先梳理整體流程,以便大家對其有一個宏觀整體的把握,然后我們再來分析其實現(xiàn)細節(jié)。這里需要大家對連接跟蹤的狀態(tài)躍遷有一定了了解。

    從流程圖可以看出,牽扯到的幾個關(guān)鍵函數(shù)都土黃色標(biāo)注出來了。ip_nat_setup_info()函數(shù)主要是完成對數(shù)據(jù)包的連接跟蹤記錄ip_conntrack對象中相應(yīng)成員的修改和替換,而manip_pkt()中才是真正對skb里面源/目的地址,端口以及數(shù)據(jù)包的校驗和字段修改的地方。


目的地址轉(zhuǎn)換:DNAT

         DNAT主要適用于將內(nèi)部私有地址的服務(wù)發(fā)布到公網(wǎng)的情形。情形如下:

    服務(wù)器上架設(shè)了Web服務(wù),其私有地址是B,代理防火墻服務(wù)器有一個公網(wǎng)地址A。想在需要通過A來訪問B上的Web服務(wù),此時就需要DNAT出馬才行。根據(jù)前面的流程圖,我們馬上殺入內(nèi)核。

當(dāng)client通過Internet訪問公網(wǎng)地址A時,通過配置在防火墻上的DNAT將其映射到了對于私網(wǎng)內(nèi)服務(wù)器B的訪問。接下來我們就分析一下當(dāng)在clientserver的交互過程中架設(shè)在防火墻上NAT是如何工作。

還是看一下hook函數(shù)在內(nèi)核中的掛載分布圖。

 

    在PREROUTING點當(dāng)一個skb被連接跟蹤過后,那么skb->ctinfoskb->nfct兩個字段均被設(shè)置了值。在接下來的分析中,對那些梢枝末節(jié)的代碼我們都將不予理睬。盜個圖:

這里牽扯到一個變量ip_conntrack_untracked,之前我們見過,但是還沒討論過。該變量定義在ip_conntrack_core.c文件里,并在ip_conntrack_init()函數(shù)進行部分初始化:

atomic_set(&ip_conntrack_untracked.ct_general.use, 1);

set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);

同時,在ip_nat_core.c文件里的ip_nat_init()函數(shù)中又有如下設(shè)置:

ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;

該變量又是何意呢?我們知道iptables維護的其實是四張表,有一張raw不是很常用。該表以-300的優(yōu)先級在PREROUTINGLOCAL_OUT點注冊了ipt_hook函數(shù),其優(yōu)先級要高于連接跟蹤。當(dāng)每個數(shù)據(jù)包到達raw表時skb->nfct字段缺省都被設(shè)置成了ip_conntrack_untracked,所以當(dāng)該skb還沒被連接蹤的話,其skb->nfct就一直是ip_conntrack_untracked。對于沒有被連接跟蹤處理過的skb是不能進行NAT的,因此遇到這種情況代碼中直接返回ACCEPT。

從上面的流程圖可以看出,無論是alloc_null_binding_confirmed()、alloc_null_binding()還是ip_nat_rule_find()函數(shù)其本質(zhì)上最終都調(diào)用了ip_nat_setup_info()函數(shù)。

 

ip_nat_setup_info()函數(shù):

該函數(shù)中主要完成了對連接跟蹤記錄ip_conntrack.status字段的設(shè)置,同時根據(jù)可能配置在nat表中的DNAT規(guī)則對連接跟蹤記錄里的響應(yīng)tuple進行修改,最后將該ip_conntrack實例掛載到全局雙向鏈表bysource里。

    在連接跟蹤系統(tǒng)里根據(jù)skb的源/目的IP分別已經(jīng)構(gòu)建生成初始tuple和響應(yīng)tuple,我們通過一個簡單的示意圖來回顧一下其流程,并加深對ip_nat_setup_info()函數(shù)執(zhí)行過程的理解。

在圖1中,根據(jù)skb的源、目的IP生成了其連接跟蹤記錄的初始和響應(yīng)tuple;

在圖2中,以初始tuple為輸入數(shù)據(jù),根據(jù)DNAT規(guī)則來修改將要被改變的地址。這里是當(dāng)我們訪問目的地址是A的公網(wǎng)地址時,DNAT規(guī)則將其改成對私網(wǎng)地址B的訪問。然后,計算被DNAT之后的數(shù)據(jù)包新的響應(yīng)。最后用新的響應(yīng)tuple替換ip_conntrack實例中舊的響應(yīng)tuple,因為數(shù)據(jù)包的目的地址已經(jīng)被改變了,所以其響應(yīng)tuple也必須跟著變。

在圖3中,會根據(jù)初始tuple計算一個hash值出來,然后以ip_conntrack結(jié)構(gòu)中的nat.info字段會被組織成一個雙向鏈表,將其插入到全局鏈表bysource里。

最后,將ip_conntrack.status字段的IPS_DST_NATIPS_DST_NAT_DONE_BIT位均置為1。

這里必須明確一點:在ip_nat_setup_info()函數(shù)中僅僅是對ip_conntrack結(jié)構(gòu)實例中相關(guān)字段進行了設(shè)置,并沒有修改原始數(shù)據(jù)包skb里的源、目的IP或任何端口。

 

ip_nat_packet()函數(shù)的核心是調(diào)用manip_pkt()函數(shù):

manip_pkt()里主要完成對數(shù)據(jù)包skb結(jié)構(gòu)中源/目的IP和源/目的端口的修改,并且修改了IP字段的校驗和。從mainip_pkt()函數(shù)中返回就回到了ip_nat_in()函數(shù)中(節(jié)選)

ret = ip_nat_fn(hooknum, pskb, in, out, okfn);

if (ret != NF_DROP && ret != NF_STOLEN&& daddr != (*pskb)->nh.iph->daddr) {

         dst_release((*pskb)->dst);

         (*pskb)->dst = NULL;

}

return ret;

    正常情況下返回值ret一般都為NF_ACCEPT,因此會執(zhí)行if條件語句,清除skb原來的路由信息,然后在后面協(xié)議棧的ip_rcv_finish()函數(shù)中重新計算該數(shù)據(jù)包的路由。

在數(shù)據(jù)包即將離開NAT框架時,還有一個名為ip_nat_adjust()的函數(shù)。參見hook函數(shù)的掛載示意圖。該函數(shù)主要是對那些執(zhí)行了NAT的數(shù)據(jù)包的序列號進行適當(dāng)?shù)恼{(diào)整。如果調(diào)整出錯,則丟棄該skb;否則,將skb繼續(xù)向后傳遞,即將到達連接跟蹤的出口ip_confirm()。至于,ip_confirm()函數(shù)的功能說明我們在連接跟蹤章節(jié)已經(jīng)深入討論了,想不起來的童鞋可以回頭復(fù)習(xí)一下連接跟蹤的知識點。

 

前面我們僅分析了從client發(fā)出的第一個請求報文到server服務(wù)器時,防火墻的處理工作。緊接著我們順著前面的思路繼續(xù)分析,當(dāng)server收到該數(shù)據(jù)包后回應(yīng)時防火墻的處理情況。

server收到數(shù)據(jù)包時,該skb的源地址(記為X)從未變化,但目的地址被防火墻從A改成了Bserver在響應(yīng)這個請求時,它發(fā)出的回應(yīng)報文目的地址是X,源地址是自己的私有地址B。大家注意到這個源、目的地址剛好匹配被DNAT之后的那個響應(yīng)tuple。

當(dāng)該回應(yīng)報文到達防火墻后,首先是被連接跟蹤系統(tǒng)處理。顯而易見,在全局的連接跟蹤表ip_conntrack_hash[]中肯定可以找到這個tuple所屬的連接跟蹤記錄ip_conntrack實例。關(guān)于狀態(tài)的變遷參見博文八。

然后,該回應(yīng)報文到達NAT框架的ip_nat_in()函數(shù),流程和前面一樣,但處理方式肯定不同。我們還是先看一下截止到目前為止,這條連接跟蹤結(jié)構(gòu)圖:

直接跳到ip_nat_packet()函數(shù)里,當(dāng)netlink通知機制將連接跟蹤狀態(tài)由NEW變?yōu)?/span>REPLY后,此時dir=1,那么根據(jù)初始tuple求出原來的響應(yīng)tuple:源地址為A,目的之為X。此時,server的響應(yīng)報文,源地址為私有網(wǎng)段B,目的地址為X。路由尋址是以目的地址為依據(jù),防火墻上有直接到client的路由,所以響應(yīng)報文是可以被client正確收到的。但是,但可是,蛋炒西紅柿,對于UDP來說client收到這樣的回復(fù)沒有任何問題的,但是對于TCPU而言確實不行的。這就引出我們接下來將要討論的SNAT。

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多