NAT的完全分析及其UDP穿透的完全解決方案

2021-05-25 07:01:37 字數 3566 閱讀 7574

三:nat對session的處理

以下分析napt是依據什麼策略來判斷是否要為乙個請求發出的udp資料報建立session的.主要有一下幾個策略:  

a.   源位址(內網ip位址)不同,忽略其它因素,   在napt上肯定對應不同的session

b.   源位址(內網ip位址)相同,源埠不同,忽略其它的因素,則在napt上也肯定對應不同的session

c.   源位址(內網ip位址)相同,源埠相同,目的位址(公網ip位址)相同,目的埠不同,則在napt上肯定對應同乙個session

d.   源位址(內網ip位址)相同,源埠相同,目的位址(公網ip位址)不同,忽略目的埠,則在napt上是如何處理session的呢?

a,b,c三種情況的都是比較簡單的,可以很容易的實現.而d的情況就比較複雜了.所以d情況才是我們要重點關心和討論的問題。

四:完全解決方案

以下針對四種session與四種nat的完全解決方案,為了方便將使用以下縮寫形式:

c代表   cone   nat

s代表symmetric   nat,

fc代表   full   cone   nat,

rc代表   restrict   cone   nat,

pc   代表   port   restrict   cone   nat.

首先依據client   (客戶)端在nat後   的個數不同可以分為兩大類:

type   one   :乙個在nat後   +   乙個在公網中.

這種情況下可以分為兩大類:

a.   s   vs   公網:此種情況下,由於公網的位址在乙個session內是不變的,所以可以打洞是可以成功的.

b.   c   vs   公網:   與上面類似,這種情口下打洞是可以成功的.

type   two:兩個客戶都在nat後面.

這種情況下也可以細分為兩大類:

a.   其中乙個nat   是   s(symmetric   nat)   型的,既:s   vs   c或者是s   vs   s   .

下面論證這種情口下按照常規打洞是行不通的,在常規打洞中,所有的客戶首先登陸到乙個伺服器上去.伺服器記錄下每個客戶的[公網ip:埠],然後在打洞過程中就使用這個記錄的值,然而對於s型的nat來說,它並不繫結[私網ip:埠]和[公網ip:埠]的對映.所以在不同的session中,nat將會重新分配一對[公網ip:埠].這樣一來對於s型的nat來說打洞的[公網ip:埠]與登記在伺服器上的[公網ip:埠]是不同的.而且也沒有辦法將打洞的[公網ip:埠]通知到另乙個位於nat下的客戶端,   所以打洞是不會成功的.然而如果另乙個客戶端是在公網時,打洞是可以的.前面已經論證了這種情況.

這種情況下的解決方案是只能通過埠**來進行打洞,具體解決方法如下:例如(以兩個都是s型的為例)   nat   a   分配了它自己的udp埠62000,用來保持   客戶端a   與伺服器s的通訊會話,   nat   b   也分配了31000埠,用來保持客戶端b與伺服器s   的通訊會話。通過與   伺服器s的對話,客戶端a   和   客戶端b都相互知道了對方所對映的真實ip和埠。

客戶端a傳送一條udp訊息到138.76.29.7:31001(請注意到埠號的增加),同時客戶端b傳送一條udp訊息到155.99.25.11:62001。如果nat   a   和nat   b繼續分配埠給新的會話,並且從a-s和b-s的會話時間消耗得並不多的話,那麼一條處於客戶端a和客戶端b之間的雙向會話通道就建立了。

客戶端a發出的訊息送達b導致了nat   a開啟了乙個新的會話,並且我們希望nat   a將會指派62001埠給這個新的會話,因為62001是繼62000後,nat會自動指派給   從伺服器s到客戶端a之間的新會話的埠號;類似的,客戶端b發出的訊息送達a導致了   nat   b開啟了乙個新的會話,並且我們希望   nat   b將會指派31001這個埠給新的會話;如果兩個客戶端都正確的猜測到了對方新會話被指派的埠號,那麼這個   客戶端a-客戶端b的雙向連線就被打通了。其結果如下圖所示:

明顯的,有許多因素會導致這個方法失敗:如果這個預言的新埠(62001和31001)   恰好已經被乙個不相關的會話所使用,那麼nat就會跳過這個埠號,這個連線就會宣告失敗;如果兩個nat有時或者總是不按照順序來生成新的埠號,那麼這個方法也是行不通的。

如果隱藏在nata後的乙個不同的客戶端x(或者在nat   b後)開啟了乙個新的「外出」udp   連線,並且無論這個連線的目的如何;只要這個動作發生在客戶端a   建立了與伺服器s的連線之後,客戶端a   與   客戶端b   建立連線之前;那麼這個無關的客戶端x   就會趁人不備地「偷」   到這個我們渴望分配的埠。所以,這個方法變得如此脆弱而且不堪一擊,只要任何乙個nat方包含以上碰到的問題,這個方法都不會奏效。

在處於   cone   nat   系列的網路環境中這個方法還是實用的;如果有一方為   cone   nat   而另外一方為   symmetric   nat,那麼應用程式就應該預先發現另外一方的   nat   是什麼型別,再做出正確的行為來處理通訊,這樣就增大了演算法的複雜度,並且降低了在真實網路環境中的普適性。

最後,如果p2p的一方處在兩級或者兩級以上的nat下面,並且這些nats   接近這個客戶端是symmetric   nat的話,埠號預言是無效的!

因此,並不推薦使用這個方法來寫新的p2p應用程式,這也是歷史的經驗和教訓!

b.   兩個都是cone   nat型的.

這種情況下可以分為六大型別:

a:   fc   +   fc

b:   fc   +   rc

c:   fc   +   pc  

d:   pc   +   rc  

e:   pc   +   pc  

f:   rc   +   rc  

雖然有這麼多種情況,但是由於cone   nat   的特性,所以還是很好辦的,因為對於cone   nat   來說,在同乙個session中它會繫結一對[私網ip:埠]和[公網ip:埠]的對映,所以它們打洞用的[公網ip:埠]與登記在伺服器上的[公網ip:埠]是一致的,所以打洞是可以行的通的.

綜上所述,就已經完全的概括了所有型別的nat之間的可能的通訊情況了.並且都提供了可行的解決方案.

五:對前一階段的總結

1.前一階段使用的打洞方法是有缺陷的,它只適應於兩個都是full   cone   nat的型別的client(客戶端).以下論證它不適應於兩個都是cone   nat的型別中的

b:   fc   +   rc

c:   fc   +   pc  

d:   pc   +   rc  

e:   pc   +   pc  

f:   rc   +   rc  

這五種情況.

因為對於受限的nat它登記了外出包的[ip位址&埠],它僅僅接受這些已登記位址發過來的包,所以它們報告伺服器的埠只能接受來自伺服器的包.不能接受來自另一客戶端的包.所以前一階段的打洞方法是不可行的.

六:   存在的問題

按照理論.nat將在一定時間後關閉udp的乙個對映,所以為了保持與伺服器能夠一直通訊,伺服器必須要傳送udp心跳包,來保持對映不被關閉.這就需要乙個合適的時間值.

P2P之UDP穿透NAT原始碼分析

p2p之udp 穿透nat 原始碼分析 說明 有關這方面的介紹很多,請參考p2p 之udp 穿透nat 的原理與實現的講解。主要技術就是nat 網路位址轉換。要強調的一點是,當內網客戶端要連線公網伺服器時,會在nat 上建乙個session,並且分配乙個埠 十分重要 並且記錄相應的公網ip 位址和埠...

P2P 之 UDP穿透NAT的原理與實現

原創 shootingstars 參考 http midcom p2p.sourceforge.net draft ford midcom p2p 01.txt 論壇上經常有對p2p原理的討論,但是討論歸討論,很少有實質的東西產生 源 呵呵,在這裡我就用自己實現的乙個源 來說明udp穿越nat的原理...

P2P之UDP穿透NAT的原理與實現

nat network address translators 網路位址轉換 網路位址轉換是在ip位址日益缺乏的情況下產生的,它的主要目的就是為了能夠位址重用。nat分為兩大類,基本的nat和napt network address port translator 最開始nat是執行在路由器上的乙個...