文章目錄
- The Technique
- Required NAT Behavior
- Changes in Version 2
原文: http://midcom-p2p.sourceforge.net/
NAT Check
Version 3, with TCP Support!
檢查你的NAT (Network Address Translator) 和p2p協議的相容性
NAT Check by Bryan Ford, web magic by Dave Andersen
Hosted by the MIDCOM-P2P project on SourceForge
P2P協議的實現在當前IPV4環境下,就技術上來講,更重要的是如何穿越NAT以及保證串連的穩定效能。有必要先澄清幾個概念。
Firewall, NAT, Loopback tanslation (參考 http://blog.csdn.net/hxhbluestar/archive/2004/11/11/177793.aspx)
NAT Check是這樣的一個小程式,它可以自動檢測你的NAT對P2P協議的支援程度,version 3版本可以檢測以下功能:
- TCP/UDP consistent translation
- TCP simultaneous open
- TCP/UDP loopback translation
- TCP unsolicited connections filtered
- UDP unsolicited messages filtered
你可以在下載、編譯運行這個C程式:natcheck.c (如果是64位電腦,可以在添加編譯參數"-DHAVE_STDINT"或者直接修改程式的#define)
如果你想在Windows平台上運行NAT Check, 首先安裝Windows上的GCC環境MinGW,然後使用-lws2_32編譯選項編譯即可)
Technical Explanation這個程式使用的技術相當簡單,並且已經被許多線上遊戲和其它p2p應用廣泛地使用。你可以在here和here查看以前的討論。
The Technique假定通訊中的三台機器A,B,C。主機A是“well-known" intenet server,有固定的IP地址,它充當B和C通訊的”介紹人“角色。B和C都在NAT(可能是同一個NAT)的後面,都只有私網地址。其中B希望能通過 A的協助,和C建立直接的p2p串連。為了發起一個到C的p2p串連,B首先向A發送一條訊息(UDP包,內容包含請求命令,B自己的本地地址和udp連接埠),請求”介紹“C。 A將C的真實IP和udp連接埠(也就是私網IP和連接埠)以及由A觀察IP和連接埠(C經過NAT轉換後的公網IP和連接埠)回複給B,同時A將B的這一對”地址/連接埠"資訊發送給C。(這裡隱含C立刻向A發送udp響應的需求,否則,因為nat上的session到期,A無法得知C的正確的公網連接埠)現在B和C雙方都知道建立一個p2p串連的需求,並且知道對方的公網地址/連接埠和本地地址/連接埠。雙發嘗試直接向對方發送udp包。如果兩台機器正好在一個NAT後,則兩者彙報的公網IP應該是相同的,這時B和C可以根據內網的地址/連接埠建立直接的串連。 大部分情況下,B和C在不同的子網內,他們各自的內網地址/連接埠是沒有意義的。這時候,B和C需要向對方的公網地址/連接埠發送udp請求(此時,他們各自使用的本地udp連接埠應該還是他們向A發送udp訊息時的同一連接埠,這樣,nat-cone nat-才會複用公網連接埠,並發起一個新的session),現在兩個nat上都有目的ip/port是對方的udp串連session, 所以這時候到達的udp包不會被過濾。因為發起串連有先後,所以,最初的幾個到達對方nat的udp包會因為目標地址/連接埠不一致而被過濾。一旦雙方的nat上都開啟了新的session(稱為hole)後,udp包將暢通無阻,這樣,B和C之間的p2p串連就建立起來了。 Required NAT Behavior以上技術的實現,有個重要的前提,那就是,NATS必須滿足一個條件:對於每一對內部IP/Port(UDP),NAT只分配唯一的公網 IP/Port,而不是給每一個新的udp session分配新的udp公網連接埠。NAT上session是由源地址/連接埠對和目標地址/連接埠對兩部分定義的。如果兩個udp包的這兩部分相同,那麼NAT認為它們是一個session的,就會允許存取,否則會被過濾。RFC 3022 explicitly allows and suggests that NATs behave in the former, "desirable" fashion, by maintaining a single (public IP, public port) mapping for a given (internal IP, internal port) combination independent of the number of active sessions involving this mapping. 這種behavior不僅有益於UDP應用的相容,而且有利於NAT節省寶貴的公網連接埠地址。因為在session級上一樣可以過濾進來的包,所以也不存在安全性方面的問題。NAT不採用此behavior的唯一考慮估計是為了省事,畢竟,新來一個session就新開一個連接埠在技術實現上要簡單的多。不幸的是,RFC 3022 does not
require NATs to implement the desirable behavior。寫這個小程式的一個目的也就是想知道現在的internet上到底有多少NATs是支援這種behavior的。 你可以將測試結果提交到這裡,或者查看累計結果。 Changes in Version 2Version 2 of NAT Check contains the following enhancements:
- 不再嘗試猜測nat的類型,基本NAT還是NATP。因為大部分NATP會在綁定公私網連接埠的時候,首選相同的連接埠,這在表現形式上是和基本NAT是一樣的。NAT Check碰到這種情況,就會誤以為此NAT是Basic類型的。唯一的方法是在同一私網內的兩台機器上同時運行NAT Check。
- 可以測試NAT的一個特性: 迴環轉換(loopback translation, 是原文作者自己起的名稱). 如果NAT支援迴環轉換,表示一台主機可以通過NAT賦予的公網地址和連接埠訪問位於同一NAT後的私人網域中的另外一台主機。大部分的NAT可能還不支援這個功能,不過,它將會變得越來越重要,因為許多P2P用戶端位於自己的NAT和ISP配置的公用NAT之後。(Twice-NAT) [註:此處Twice-NAT術語來自於natcheck.c,"BAD for P2P over Twice-NAT", 當NAT不支援loopback translation時,p2p over Twice-NAT會有問題。據我的理解,Twice-NAT指兩層NAT,而不是平常所說的Twice NAT,後者是NAT的一種新特性,可以同時更改IP包的源地址(連接埠)和目的地址(連接埠),解決nat內的IP地址和外部IP地址重疊的問題(IP overlapping)]
- NAT Check 的命令列選項"-v", 開啟它,你就鞥在測試過程中看到詳細的反饋資訊。
What NAT Check Does
natcheck.c 本質上來講,只是"ping" 兩個不同的位於Internet上的伺服器的眾所周知的udp連接埠。這兩台伺服器都運行同樣的程式natserver.c. 另外,還有第三台運行natbouncer.c 的"conspiring"伺服器。前面的兩台伺服器只要收到udp請求,除了直接回複客戶程式外,還會向第三台伺服器發送一份,而這第三台伺服器會將這個包回複給那個用戶端,這個由第三台伺服器發送的包不是用戶端所期望的,屬於“對方主動發起的”("unsolicited")。這個"bounce"的過程主要是測試NAT的安全效能,看它是否過濾這些"unsolicited"的包。
natcheck.c 會綁定同一本地連接埠向前兩台公網伺服器同時發送一些udp包,根據判斷兩台伺服器的回複包中報告的用戶端公網地址/連接埠是否相同來判定此NAT是否實現了上面所說的"desirable behavior",也就是同一內部ip/port發起的多個session只共用映射到nat上的一個公網ip/port對。
Related Links
- Dan Kegel's NAT/P2P page
- IETF MIDCOM working group
- nat-peer-games group on Yahoo!
- P2P area at the Global Grid Forum
- NAT/firewall page at the P2P working group page (inactive)
防火牆 (Firewall)
防火牆限制了私網與公網的通訊,它主要是將(防火牆)認為未經授權的的包丟棄,防火牆只是檢驗包的資料,並不修改資料包中的IP地址和TCP/UDP連接埠資訊。
網路位址轉譯(NAT)
當有資料包通過時,網路位址轉譯器不僅檢查包的資訊,還要將包頭中的IP地址和連接埠資訊進行修改。以使得處於NAT之後的機器共用幾個僅有的公網IP地址(通常是一個)。網路位址轉譯器主要有兩種類型:
- 基礎NAT (Basic NAT) :基礎NAT 將私網主機的私人IP地址轉換成公網IP地址,但並不將TCP/UDP連接埠資訊進行轉換。基礎NAT一般用在當NAT擁有很多公網IP地址的時候,它將公網IP地址與內部主機進行綁定,使得外部可以用公網IP地址訪問內部主機。
- 網路地址和連接埠轉換 (Network Address/Port Translator NAPT):這是最普遍的情況,網路地址/連接埠轉換器檢查、修改包的IP地址和TCP/UDP連接埠資訊,這樣,更多的內部主機就可以同時使用一個公網IP地址。
請參考[NAT-TRAD]和[NAT-TERM]兩個文檔瞭解更多的NAT分類和術語資訊。另外,關於NAPT的分類和術語,[STUN]在最近做了更多的定義。當一個內部網主機通過NAT開啟一個“外出”的TCP或UDP會話時,NAPT分配給這個會話一個公網IP和連接埠,用來接收外網的響應的資料包,並經過轉換通知內部網的主機。這樣做的效果是,NAPT在 [私人IP:私人連接埠] 和[公網IP:公網連接埠]之間建立了一個連接埠綁定。
連接埠綁定指定了NAPT將在這個會話的生存期內進行地址轉換任務。這中間存在一個這樣的問題,如果P2P應用程式從內部網路的一個[私人IP地址:連接埠]對同時發出多條會話給不同的外網主機,那麼NAT會怎樣處理呢?請看以下幾種方案。
- 錐形NAT (Cone NAT) :當建立了一個 [私人IP:連接埠]-[公網IP:連接埠] 連接埠綁定之後,對於來自同一個[私人IP:連接埠]會話,錐形NAT伺服器允許發起會話的應用程式 重複使用這個連接埠綁定,一直到這個會話結束才解除(連接埠綁定)。
- 對稱NAT (Symmetric NAT) :對稱NAT,與Cone NAT是大不相同的,並不對會話進行連接埠綁定,而是分配一個全新的 公網連接埠 給每一個新的會話。(因為很難正確得知這個新分配的公網連接埠的具體數值,本文談及的p2p udp hole punch技術並不適用於這種nat。事實上,對稱nat已不多見)
迴環轉換 (Loopback translation)
當NAT的私網內部機器想通過公用地址來訪問同一台區域網路內的機器的時,NAT裝置等價於做了兩次NAT的事情,在包到達目標機器之前,先將私人地址轉換為公網地址,然後再將公網地址轉換回私人地址。我們把具有上敘轉換功能的NAT裝置叫做“迴環轉換”裝置。
更多內容,可以技術細節可參考 http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt