詳解:NAT原理及在VxWorks上的實(shí)現(xiàn)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
Internet的最初設(shè)計(jì),并沒(méi)有考慮到需要支持目前這樣龐大的互聯(lián)網(wǎng),因此在IPv4的設(shè)計(jì)當(dāng)中,IP地址僅使用了32bit來(lái)標(biāo)識(shí)網(wǎng)絡(luò)中的一個(gè)節(jié)點(diǎn)設(shè)備,雖然這很好地解決了IP數(shù)據(jù)報(bào)的對(duì)齊問(wèn)題,但隨著Internet的迅猛發(fā)展,加上一些不合理的地址分配方式,目前IP地址已嚴(yán)重缺乏,IP地址短缺已成為目前Internet所面臨的最大問(wèn)題之一。
為了節(jié)約IP地址資源,IETF拋棄了傳統(tǒng)的地址分類方式(把IP地址空間人為地劃分為A、B、C、D類地址的方式)。開(kāi)始使用在RFC 1918中指定的CIDR(Classless Inter-Domain Routing)。同時(shí)為了解決IP地址耗損的問(wèn)題,在RFC 1631中提出了使用NAT來(lái)解決共用IP地址訪問(wèn)Internet的問(wèn)題。
1 NAT 概況
NAT是把一個(gè)網(wǎng)絡(luò)中使用的IP地址翻譯成能被另一個(gè)網(wǎng)絡(luò)識(shí)別的IP地址。一個(gè)網(wǎng)絡(luò)被指定為內(nèi)部網(wǎng)絡(luò),另一個(gè)為外部網(wǎng)絡(luò)。通常,一個(gè)公司把自己的本地內(nèi)部網(wǎng)絡(luò)地址映射到一個(gè)或多個(gè)全局外部IP地址,并把收到的包中的全局IP地址解釋成本地IP地址。這也有助于安全,因?yàn)槊總€(gè)出去和進(jìn)來(lái)的請(qǐng)求都必須經(jīng)過(guò)一個(gè)翻譯過(guò)程,這是一個(gè)認(rèn)證請(qǐng)求或把它與以前請(qǐng)求匹配的過(guò)程。
NAT包含在路由器中,通常也是防火墻的一部分。網(wǎng)絡(luò)管理員創(chuàng)建一個(gè)NAT表,用它來(lái)實(shí)現(xiàn)全局到本地和本地到全局地址的映射。NAT也可以和策略利用路由一起使用。NAT可以靜態(tài)定義,也可以根據(jù)IP地址池動(dòng)態(tài)進(jìn)行。
NAT的描述詳見(jiàn)RFC 1631。它討論了NAT與CIDR的關(guān)系,這是一個(gè)解決IP地址耗盡的方法。NAT通過(guò)區(qū)別公共IP地址和私有IP地址而減少了對(duì)公共IP地址的需求。CIDR把公共IP地址聚集在一起,減少了IP地址的浪費(fèi)。
2 NAT 原理
在傳統(tǒng)的標(biāo)準(zhǔn)的TCP/IP通信過(guò)程中,所有的路由器僅僅是充當(dāng)一個(gè)中間人的角色,也就是通常所說(shuō)的存儲(chǔ)轉(zhuǎn)發(fā),路由器并不會(huì)對(duì)轉(zhuǎn)發(fā)的數(shù)據(jù)包進(jìn)行修改,比如對(duì)于以太網(wǎng)接口,路由器除了將源MAC 地址換成自己的MAC 地址以外,路由器不會(huì)對(duì)轉(zhuǎn)發(fā)的數(shù)據(jù)包做任何修改。NAT(Network Address Translate,網(wǎng)絡(luò)地址翻譯)恰恰是出于某種特殊需要而對(duì)數(shù)據(jù)包的源IP地址、目的IP地址、源端口、目的端口進(jìn)行改寫的操作。
從原理的角度可以將NAT分成了兩種類型,即源NAT(SNAT)和目的NAT(DNAT),顧名思義,所謂SNAT就是改變轉(zhuǎn)發(fā)數(shù)據(jù)包的源地址,所謂DNAT就是改變轉(zhuǎn)發(fā)數(shù)據(jù)包的目的地址。
3 NAT 的VxWorks 實(shí)現(xiàn)
3.1 VxWorks的底層接口概況
3.1.1 VxWorks MUX 接口層
在VxWorks中,TCP/IP協(xié)議棧使用MUX接口去和數(shù)據(jù)鏈路層通信,MUX接口的目的是隔離數(shù)據(jù)鏈路層和網(wǎng)絡(luò)層。MUX接口之上是網(wǎng)絡(luò)協(xié)議層,比如TCP/IP、 MUX_PROTO_OUTPUT、 MUX_PROTO_SNARF等協(xié)議,在MUX之下為網(wǎng)絡(luò)硬件的驅(qū)動(dòng)程序。MUX接口層提供一套接口去完成協(xié)議和驅(qū)動(dòng)注冊(cè),協(xié)議和驅(qū)動(dòng)之間數(shù)據(jù)接收、發(fā)送,Multicast地址訪問(wèn),MUX ioctl等工作。整個(gè)層次結(jié)構(gòu)如圖1所示。
3.1.2 VxWorks 中對(duì)IP數(shù)據(jù)包的截獲
要在VxWorks中實(shí)現(xiàn)NAT,必須實(shí)現(xiàn)兩個(gè)基本操作:IP數(shù)據(jù)包的截獲與IP數(shù)據(jù)包的偽裝處理。
對(duì)于VxWorks協(xié)議棧來(lái)講,NAT的存在是透明的。所以,要實(shí)現(xiàn)NAT的功能,必須在VxWorks網(wǎng)絡(luò)協(xié)議棧處理數(shù)據(jù)包之前截獲數(shù)據(jù)。要實(shí)現(xiàn)這一點(diǎn),VxWorks為我們提供了兩類鉤子函數(shù),截獲以太幀的EtherHook和截獲IP數(shù)據(jù)包的IpFilterHook。
其中EtherHook又包括EtherInputHook和EtherOutputHook,分別用來(lái)截獲接收和發(fā)送的以太幀。用戶可以通過(guò)EtherInputHookAdd和EtherOutputHookAdd來(lái)分別進(jìn)行安裝。
而IpFilterHook提供對(duì)IP數(shù)據(jù)包的截獲,它只對(duì)應(yīng)一個(gè)鉤子函數(shù),用IpFilterHookAdd來(lái)進(jìn)行安裝。當(dāng)收到一個(gè)IP數(shù)據(jù)包的時(shí)候,IpFilterHook會(huì)被自動(dòng)調(diào)用,從而達(dá)到對(duì)IP數(shù)據(jù)包截獲的目的。
對(duì)比兩種接口,EtherInputHookAdd將調(diào)用MuxBind去添加一個(gè)MUX_PROTO_SNARF協(xié)議,這樣可以得到進(jìn)入MUX接口層的所有數(shù)據(jù)包。而由IpFilterHookAdd安裝的IpFilterHook,不屬于MUX接口層,僅僅用來(lái)截獲IP數(shù)據(jù)包,而不會(huì)接收到非IP數(shù)據(jù)包。
鑒于以上的區(qū)別,我們使用IpFilterHookAdd函數(shù)安裝的IpFilterHook來(lái)截獲IP數(shù)據(jù)包比較合適,參見(jiàn)圖2。
3.2 NAT偽裝策略
3.2.1 網(wǎng)絡(luò)接口
網(wǎng)絡(luò)接口是VxWorks的一個(gè)內(nèi)核對(duì)象,它是由網(wǎng)絡(luò)驅(qū)動(dòng)程序注冊(cè)的。它在內(nèi)核中用于標(biāo)識(shí)網(wǎng)絡(luò)設(shè)備的驅(qū)動(dòng)程序,包含著該網(wǎng)絡(luò)設(shè)備特有的屬性、配置及操作接口等。而這個(gè)驅(qū)動(dòng)程序可以驅(qū)動(dòng)一個(gè)特定型號(hào)的網(wǎng)絡(luò)芯片,比如I82557,RTL 8139等,也可以驅(qū)動(dòng)一些其他類型的設(shè)備,比如通過(guò)Serial Port、CompactPCI Bus、Loopback等。在VxWorks中,接收到的IP數(shù)據(jù)被保存在一個(gè)mBlk的結(jié)構(gòu)當(dāng)中。該結(jié)構(gòu)除保存數(shù)據(jù)內(nèi)容外,還保存了管理數(shù)據(jù)內(nèi)容的信息結(jié)構(gòu)以及接口信息。
3.2.2 哪些IP數(shù)據(jù)包需要偽裝
在做NAT地址映射時(shí),我們需要判斷對(duì)哪些IP包進(jìn)行偽裝(NAT變換)。我們通過(guò)下面這個(gè)實(shí)例來(lái)進(jìn)行講解(見(jiàn)圖3)。
在這個(gè)實(shí)例中,網(wǎng)關(guān)通過(guò)網(wǎng)絡(luò)接口If0連接到局域網(wǎng)中,并通過(guò)If1連接到Internet上,同時(shí),網(wǎng)關(guān)啟用NAT功能。此時(shí),位于局域網(wǎng)中的主機(jī)A如果想訪問(wèn)Internet上10.2.4.0/24網(wǎng)段的主機(jī)B,最好的方法是通過(guò)網(wǎng)關(guān)上的NAT。
那么,具體哪些包需要進(jìn)行NAT變換呢?我們先根據(jù)源地址和目的地址來(lái)劃分網(wǎng)關(guān)可能收到的包的類型。
(1)接口If0收到的IP數(shù)據(jù)包,目的地址為網(wǎng)關(guān)If0接口的IP地址。
(2)接口If0收到的IP數(shù)據(jù)包,目的地址為網(wǎng)關(guān)If1接口的IP地址。
(3)接口If0收到的IP數(shù)據(jù)包,目的地址非網(wǎng)關(guān)任一接口的地址的私網(wǎng)IP地址。
(4)接口If0收到的IP數(shù)據(jù)包,目的地址非網(wǎng)關(guān)任一接口的地址的公網(wǎng)IP地址。
(5)接口If1收到的IP數(shù)據(jù)包,目的地址為If1接口的IP地址。
(6)接口If1收到的IP數(shù)據(jù)包,目的地址非If1接口的IP地址。
對(duì)于前面3種情況,NAT不進(jìn)行任何處理,直接交給VxWorks網(wǎng)絡(luò)協(xié)議棧,由協(xié)議棧來(lái)做進(jìn)一步的處理。
對(duì)于第4種情況,符合NAT變換的需求,NAT將改變?cè)璉P包的源地址為網(wǎng)關(guān)的外出口地址,同時(shí)選擇網(wǎng)關(guān)該接口未分配的端口來(lái)修改原IP包中的源端口,并添加該記錄到NAT映射表內(nèi)。最后把IP包送到If1接口,然后發(fā)送到目的主機(jī)。
對(duì)于第5種情況,我們將收到的IP數(shù)據(jù)包送到NAT處理。通過(guò)查找NAT映射表,決定是否將其目標(biāo)地址轉(zhuǎn)換為L(zhǎng)AN中的某一個(gè)地址,還是不做任何處理,直接歸還給協(xié)議棧。對(duì)于第6種情況,我們這里也簡(jiǎn)單地直接歸還給協(xié)議棧進(jìn)行處理。[!--empirenews.page--]
3.3 NAT 映射表及timer管理
3.3.1 NAT 映射表
對(duì)于每一個(gè)需要進(jìn)行地址翻譯的IP數(shù)據(jù)包,內(nèi)核必須知道如何翻譯它。NAT 映射表就是用來(lái)解決這個(gè)問(wèn)題的。NAT 映射表中記錄有足夠標(biāo)識(shí)一個(gè)連接的所有信息:協(xié)議類型、源地址、源端口、目的地址、目的端口、NAT地址、NAT端口等。通過(guò)IP數(shù)據(jù)包中攜帶的信息可以在NAT表中找到最匹配的一項(xiàng)。在實(shí)現(xiàn)當(dāng)中,我們采用表1的結(jié)構(gòu)來(lái)表示一個(gè)映射表項(xiàng)。
3.3.2 為什么NAT 映射表項(xiàng)需要設(shè)置timer
為了避免通過(guò)NAT進(jìn)行通信的主機(jī)突然崩潰后,出現(xiàn)殘留的映射表項(xiàng)占據(jù)系統(tǒng)資源的情況。在每個(gè)NAT映射表項(xiàng)中,我們使用了一個(gè)軟件定時(shí)器來(lái)指示這個(gè)映射表項(xiàng)是否超時(shí)。如果在一段時(shí)間內(nèi)這個(gè)表項(xiàng)沒(méi)有被訪問(wèn)過(guò),從而導(dǎo)致定時(shí)器超時(shí),NAT將清除這個(gè)表項(xiàng),以減少系統(tǒng)資源消耗。在這個(gè)NAT的實(shí)現(xiàn)過(guò)程中,為了使TCP/IP協(xié)議棧能夠正常工作,針對(duì)不同的協(xié)議以及協(xié)議的不同階段,我們使用了不同的默認(rèn)超時(shí)值。如表2所示。
3.4 NAT 映射表管理
3.4.1 NAT 映射表的創(chuàng)建、查找及刪除
在NAT的實(shí)現(xiàn)過(guò)程當(dāng)中,如何快速地尋找一個(gè)IP包在NAT中是否有對(duì)應(yīng)的映射選項(xiàng),需要一個(gè)高效的數(shù)據(jù)結(jié)構(gòu)和快速的查找算法。
在實(shí)現(xiàn)當(dāng)中,我們選用采用索引查詢的散列表來(lái)作為存儲(chǔ)NAT映射表項(xiàng)的數(shù)據(jù)結(jié)構(gòu)。使用協(xié)議類型值、內(nèi)部網(wǎng)絡(luò)地址和端口來(lái)計(jì)算散列值,并結(jié)合映射表項(xiàng)的標(biāo)志來(lái)確定需要做地址翻譯的IP數(shù)據(jù)包。
如果當(dāng)前的IP數(shù)據(jù)包是外出的IP數(shù)據(jù)包,但是沒(méi)有匹配到一個(gè)合適的映射表項(xiàng),那么NAT將建立一個(gè)新的映射表項(xiàng),添加到散列表中。
如果當(dāng)前的IP數(shù)據(jù)包是來(lái)自于外部網(wǎng)絡(luò)的,要么能夠匹配到一項(xiàng)合適的映射表項(xiàng),要么目的端口已經(jīng)被配置為端口轉(zhuǎn)發(fā)(在這種情況下,NAT將依據(jù)端口轉(zhuǎn)發(fā)配置,在NAT映射表中靜態(tài)添加一個(gè)入口),否則,將不會(huì)改變這個(gè)IP數(shù)據(jù)包。
為了避免已經(jīng)出現(xiàn)異常的連接繼續(xù)占用系統(tǒng)資源,在每個(gè)映射表項(xiàng)的定時(shí)器超時(shí)后,其回掉函數(shù)將刪除存儲(chǔ)在散列表中的對(duì)應(yīng)的NAT映射表項(xiàng)。
3.4.2 如何互斥地訪問(wèn)NAT映射表
在NAT映射表的處理和映射表項(xiàng)超時(shí)處理中,都需要對(duì)映射表進(jìn)行查找、添加和刪除操作。為了安全地訪問(wèn)映射表,我們必須同步對(duì)NAT映射表的訪問(wèn)。在實(shí)現(xiàn)當(dāng)中,我們使用了VxWorks提供的二進(jìn)制信號(hào)量來(lái)保護(hù)對(duì)NAT映射表的操作。
3.5 TCP session state和TCP sequence number管理
3.5.1 TCP SYN/FIN/RST 狀態(tài)
對(duì)于一個(gè)TCP連接,如果NAT收到一個(gè)帶有RST標(biāo)志的TCP數(shù)據(jù)包,我們將NAT映射表中對(duì)應(yīng)表項(xiàng)的定時(shí)器超時(shí)值置1,那么這個(gè)映射表很快將被刪除。如果收到一個(gè)FIN數(shù)據(jù)包,那么就重新設(shè)置對(duì)應(yīng)表項(xiàng)的定時(shí)器超時(shí)值為120s。否則,我們?cè)O(shè)置對(duì)應(yīng)映射表項(xiàng)的定時(shí)器超時(shí)值為5min。
3.5.2 TCP sequence number 調(diào)整
NAT的原理就是通過(guò)修改過(guò)往IP數(shù)據(jù)包的內(nèi)容,來(lái)達(dá)到偽裝IP數(shù)據(jù)包的目的。
在對(duì)部分基于TCP的應(yīng)用協(xié)議(如FTP)的數(shù)據(jù)包進(jìn)行NAT變換時(shí),如果由于應(yīng)用程序支持模塊改變了TCP數(shù)據(jù)包的內(nèi)容,導(dǎo)致數(shù)據(jù)包的長(zhǎng)度發(fā)生變化,那么,為了使當(dāng)前的TCP連接能夠繼續(xù)正常連接,就必須重新調(diào)整TCP的序列號(hào)(見(jiàn)圖4)。
TCP連接的序列號(hào)是在兩個(gè)方向上進(jìn)行調(diào)整的。調(diào)整的原則如下:
如果外出的數(shù)據(jù)包長(zhǎng)度減小,那么當(dāng)前外出的TCP數(shù)據(jù)包的序列號(hào)將減小,反之則增加。
對(duì)于收到的來(lái)自于外部網(wǎng)絡(luò)的ACK 序列號(hào),就要相應(yīng)地增加和減小了。
這里我們需要注意,由于VxWorks沒(méi)有使用Real Time來(lái)初始化TCP連接的初始序列號(hào),而是使用一個(gè)固定的值來(lái)初始化它,導(dǎo)致每次重啟之后VxWorks的第一次TCP連接都會(huì)以相同的序列號(hào)開(kāi)始遞增。由于VxWorks的TCP/IP協(xié)議棧的這種特征,我們?cè)诮邮盏絋CP連接的第一個(gè)TCP數(shù)據(jù)包(帶有SYN標(biāo)志,沒(méi)有ACK標(biāo)志)時(shí),要重新初始化已經(jīng)匹配的NAT映射表項(xiàng),避免因?yàn)門CP連接序列號(hào)調(diào)整出錯(cuò)。
3.6 端口轉(zhuǎn)發(fā)功能
3.6.1 為什么需要端口轉(zhuǎn)發(fā)功能
如果有某個(gè)處在Internet上的主機(jī)想訪問(wèn)NAT服務(wù)器后的某個(gè)主機(jī),這個(gè)連接必須已經(jīng)被記錄在NAT映射表中,但由于某些安全原因,NAT僅僅對(duì)由內(nèi)部網(wǎng)絡(luò)發(fā)起的網(wǎng)絡(luò)連接有效。當(dāng)外部IP數(shù)據(jù)包進(jìn)入允許NAT功能的接口時(shí),如果NAT找不到合適的映射表項(xiàng),IP數(shù)據(jù)包將交給VxWorks協(xié)議棧來(lái)處理。
為了使NAT能夠處理這種由外部網(wǎng)絡(luò)首先發(fā)起的網(wǎng)絡(luò)連接,NAT允許手工配置一些NAT的映射表項(xiàng)。這項(xiàng)功能就叫端口轉(zhuǎn)發(fā)。
3.6.2 端口轉(zhuǎn)發(fā)實(shí)現(xiàn)過(guò)程
由外到內(nèi)的IP包指的是從公網(wǎng)通過(guò)NAT發(fā)送到私有網(wǎng)絡(luò)的IP包。它的源IP是公共IP,目的IP是NAT的公共IP。當(dāng)截獲到一個(gè)由外到內(nèi)的IP包時(shí),NAT就以IP包的目的IP和目的Port加上包的協(xié)議類型作為NAT映射表項(xiàng)的匹配查詢條件進(jìn)行搜索。如果找到一個(gè)對(duì)應(yīng)的表項(xiàng),就用表項(xiàng)的Real Src IP和Real Src Port來(lái)替換IP包的目的IP和目的Port,而保持IP包的源IP和源Port不變。然后,重新計(jì)算TCP或UDP的校驗(yàn)和,再計(jì)算IP頭的校驗(yàn)和,最后把IP包重新歸還給VxWorks的網(wǎng)絡(luò)協(xié)議棧。如果在映射表中沒(méi)有搜索到對(duì)應(yīng)的表項(xiàng),則對(duì)IP包不作任何處理,直接歸還給VxWorks網(wǎng)絡(luò)協(xié)議棧。
3.7 NAT配置接口
為了使NAT能夠適應(yīng)某些變化,我們?cè)趯?shí)現(xiàn)過(guò)程當(dāng)中加入了對(duì)NAT的配置接口,主要對(duì)以下兩方面需要進(jìn)行配置。
NAT接口配置:配置在那個(gè)允許NAT功能的網(wǎng)絡(luò)接口上。這個(gè)接口是和外部網(wǎng)絡(luò)相連的,有唯一的全局IP地址。
端口轉(zhuǎn)發(fā)映射表配置:配置NAT可以對(duì)那些由外部網(wǎng)絡(luò)發(fā)起的網(wǎng)絡(luò)連接進(jìn)行地址轉(zhuǎn)換,以及如何進(jìn)行地址轉(zhuǎn)換。
3.8 NAT如何處理IP分片
NAT本身還應(yīng)該考慮IP數(shù)據(jù)包的分片。但是在分片的IP數(shù)據(jù)包中,除了第一個(gè)IP數(shù)據(jù)包帶有源、目的端口信息以外,后續(xù)的IP分片都沒(méi)有端口信息。
這樣,IP數(shù)據(jù)包分片的這個(gè)特征給我們的NAT處理帶來(lái)了很多不便。因此,在這次的實(shí)現(xiàn)過(guò)程中,我們的NAT實(shí)現(xiàn)暫時(shí)不支持分片的IP數(shù)據(jù)包。
3.9 NAT的測(cè)試
如圖3所示,主機(jī)A通過(guò)NAT訪問(wèn)主機(jī)B上的HTTP服務(wù)器,主機(jī)B通過(guò)手工配置在NAT上的映射表項(xiàng)訪問(wèn)主機(jī)A上的TFTP服務(wù)器。
整個(gè)過(guò)程非常良好,TCP包和UDP包以及Port-Forward功能也成功得到了驗(yàn)證。[!--empirenews.page--]
4 NAT的未來(lái)
NAT這項(xiàng)技術(shù)主要是為了解決IP地址空間不足。在NAT功能的支持下,內(nèi)部網(wǎng)絡(luò)可以使用一個(gè)公共的IP地址訪問(wèn)外部網(wǎng)絡(luò),因此,它很好地隱藏內(nèi)部網(wǎng)絡(luò)的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu),也使網(wǎng)絡(luò)更安全。由于這些特點(diǎn),NAT也常常是作為Firewall的重要部分一起提供的,但是它并不是Firewall。由于NAT可以帶來(lái)一定的安全性,相信即使在IPv6的時(shí)代,它還是能夠繼續(xù)應(yīng)用。