ICE協議下NAT穿越的實現(STUN&TURN)

對下文的內容添加舉例說明:

四種NAT類型:

RFC3489 中將 NAT 的實現分爲四大類:

  1. Full Cone NAT (完全錐形 NAT)

  2. Restricted Cone NAT (限制錐形 NAT ,可以理解爲 IP 限制,Port不限制)

  3. Port Restricted Cone NAT (端口限制錐形 NAT,IP+Port 限制)

  4. Symmetric NAT (對稱 NAT)

1 Full Cone NAT (完全錐形 NAT) 類似獨立ip

192.168.0.3:8888 == 120.132.92.21:9202. 外部所有的ip port 訪問120.132.92.21:9202即可。

比如1.2.3.4:10000, 1.2.3.4:10001,11.12.13.14:20000,11.12.13.14.20000 都可以通過訪問120.132.92.21:9202進而訪問到192.168.0.3:8888

Restricted Cone NAT

192.168.0.3:8888 == 120.132.92.21:9202. 外部ip只有1.2.3.4,port 不限制,可以訪問120.132.92.21:9202.

比如1.2.3.4:10000, 1.2.3.4:10001 可以通過訪問120.132.92.21:9202進而訪問到192.168.0.3:8888。

但是11.12.13.14:20000,11.12.13.14.20000 不可以通過訪問120.132.92.21:9202進而訪問到192.168.0.3:8888.

notes:理解爲cone NAT是一對多關係,即120.132.92.21:9202 可以同時被多個ip和port訪問.但是必須是nat表中的.

所以必須是192.168.0.3:8888先發給peer ip,記錄在nat表中,才能接收它回來的包,不限制port。

3 Port Restricted Cone NAT

192.168.0.3:8888 == 120.132.92.21:9202.外部ip只有1.2.3.4:10000 不限制,可以訪問120.132.92.21:9202.

比如: 1.2.3.4:10001,11.12.13.14:20000,11.12.13.14.20000 不可以通過訪問120.132.92.21:9202進而訪問到192.168.0.3:8888.

notes:理解爲cone NAT是一對多關係,即120.132.92.21:9202 可以同時被多個ip和port訪問.,但是必須是nat表中的.

所以必須是192.168.0.3:8888先發給peer ip和port,記錄在nat表中,才能接收它回來的包,限制port。

4 Symmetric NAT (對稱 NAT)

一對一關係。通過stun server知道了.192.168.0.3:8888 == 120.132.92.21:9202.但是120.132.92.21:9202只能接收stun server的ip和指定port的包.所以其他外網ip知道20.132.92.21:9202也不能訪問.

=============================================================================

一. 首先來簡單講講什麼是NAT?

原來這是因爲IPV4引起的,我們上網很可能會處在一個NAT設備(無線路由器之類)之後。
NAT設備會在IP封包通過設備時修改源/目的IP地址. 對於家用路由器來說, 使用的是網絡地址端口轉換(NAPT), 它不僅改IP, 還修改TCP和UDP協議的端口號, 這樣就能讓內網中的設備共用同一個外網IP. 舉個例子, NAPT維護一個類似下表的NAT表:

NAT映射


NAT設備會根據NAT表對出去和進來的數據做修改, 比如將192.168.0.3:8888發出去的封包改成120.132.92.21:9202, 外部就認爲他們是在和120.132.92.21:9202通信. 同時NAT設備會將120.132.92.21:9202收到的封包的IP和端口改成192.168.0.3:8888, 再發給內網的主機, 這樣內部和外部就能雙向通信了, 但如果其中192.168.0.3:8888 == 120.132.92.21:9202這一映射因爲某些原因被NAT設備淘汰了, 那麼外部設備就無法直接與192.168.0.3:8888通信了。

 

我們的設備經常是處在NAT設備的後面, 比如在大學裏的校園網, 查一下自己分配到的IP, 其實是內網IP, 表明我們在NAT設備後面, 如果我們在寢室再接個路由器, 那麼我們發出的數據包會多經過一次NAT.

二. NAT的副作用以及解決方案

國內移動無線網絡運營商在鏈路上一段時間內沒有數據通訊後, 會淘汰NAT表中的對應項, 造成鏈路中斷。

這是NAT帶來的第一個副作用:NAT超時:

而國內的運營商一般NAT超時的時間爲5分鐘,所以通常我們TCP長連接的心跳設置的時間間隔爲3-5分鐘。**

而第二個副作用就是:我們這邊文章要提到的NAT牆。

NAT會有一個機制,所有外界對內網的請求,到達NAT的時候,都會被NAT所丟棄,這樣如果我們處於一個NAT設備後面,我們將無法得到任何外界的數據。

但是這種機制有一個解決方案:就是如果我們A主動往B發送一條信息,這樣A就在自己的NAT上打了一個B的洞。這樣A的這條消息到達B的NAT的時候,雖然被丟掉了,但是如果B這個時候在給A發信息,到達A的NAT的時候,就可以從A之前打的那個洞中,發送給到A手上了。

簡單來講,就是如果A和B要進行通信,那麼得事先A發一條信息給B,B發一條信息給A。這樣提前在各自的NAT上打了對方的洞,這樣下一次A和B之間就可以進行通信了。

三. 四種NAT類型:

RFC3489 中將 NAT 的實現分爲四大類:

  1. Full Cone NAT (完全錐形 NAT)

  2. Restricted Cone NAT (限制錐形 NAT ,可以理解爲 IP 限制,Port不限制)

  3. Port Restricted Cone NAT (端口限制錐形 NAT,IP+Port 限制)

  4. Symmetric NAT (對稱 NAT)

其中完全最上層的完全錐形NAT的穿透性最好,而最下層的對稱形NAT的安全性最高。

簡單來講講這4種類型的NAT代表什麼:

  • 如果一個NAT是Full Cone NAT,那麼無論什麼IP地址訪問,都不會被NAT牆掉(這種基本很少)。
  • Restricted Cone NAT,僅僅是經過打洞的IP能穿越NAT,但是不限於Port。
  • Port Restricted Cone NAT,僅僅是經過打洞的IP+端口號能穿越NAT。
  • Symmetric NAT 這種也是僅僅是經過打洞的IP+端口號能穿越NAT,但是它有一個最大的和Cone類型的NAT的區別,它對外的公網Port是不停的變化的:
    比如A是一個對稱NAT,那麼A給B發信息,經過NAT映射到一個Port:10000,A給C發信息,經過NAT映射到一個Port:10001,這樣會導致一個問題,我們服務器根本無法協調進行NAT打洞。

至於爲什麼無法協調打洞,下面我們會從STUN和TURN的工作原理來講。

四. STUN和TURN的實現:

1.STUN Server主要做了兩件事:

  • 接受客戶端的請求,並且把客戶端的公網IP、Port封裝到ICE Candidate中。
  1. 通過一個複雜的機制,得到客戶端的NAT類型。

完成了這些STUN Server就會這些基本信息發送回客戶端,然後根據NAT類型,來判斷是否需要TURN服務器協調進行下一步工作。

我們來講講這兩步具體做了什麼吧:
第一件事就不用說了,其實就是得到客戶端的請求,把源IP和Port拿到,添加到ICE Candidate中。

來講講第二件事,STUN是如何判斷NAT的類型的:

假設B是客戶端,C是STUN服務器,C有兩個IP分別爲IP1和IP2(至於爲什麼要兩個IP,接着往下看):

STEP1.判斷客戶端是否在NAT後:

B向C的IP1的pot1端口發送一個UDP 包。C收到這個包後,會把它收到包的源IP和port寫到UDP包中,然後把此包通過IP1和port1發還給B。這個IP和port也就是NAT的外網 IP和port(如果你不理解,那麼請你去看我的BLOG裏面的NAT的原理和分類),也就是說你在STEP1中就得到了NAT的外網IP。

熟悉NAT工作原理的朋友可以知道,C返回給B的這個UDP包B一定收到。如果在你的應用中,向一個STUN服務器發送數據包後,你沒有收到STUN的任何迴應包,那只有兩種可能:1、STUN服務器不存在,或者你弄錯了port。2、你的NAT拒絕一切UDP包從外部向內部通過。

當B收到此UDP後,把此UDP中的IP和自己的IP做比較,如果是一樣的,就說明自己是在公網,下步NAT將去探測防火牆類型,我不想多說。如果不一樣,說明有NAT的存在,系統進行STEP2的操作。

STEP2.判斷是否處於Full Cone Nat下:

B向C的IP1發送一個UDP包,請求C通過另外一個IP2和PORT(不同與SETP1的IP1)向B返回一個UDP數據包(現在知道爲什麼C要有兩個IP了吧,雖然還不理解爲什麼,呵呵)。

我們來分析一下,如果B收到了這個數據包,那說明什麼?說明NAT來着不拒,不對數據包進行任何過濾,這也就是STUN標準中的full cone NAT。遺憾的是,Full Cone Nat太少了,這也意味着你能收到這個數據包的可能性不大。如果沒收到,那麼系統進行STEP3的操作。

STEP3.判斷是否處於對稱NAT下:注意這步是base step1的,可以理解爲1.1節

B向C的IP2的port2發送一個數據包,C收到數據包後,把它收到包的源IP和port寫到UDP包中,然後通過自己的IP2和port2把此包發還給B。

和step1一樣,B肯定能收到這個迴應UDP包。此包中的port是我們最關心的數據,下面我們來分析:
如果這個port和step1中的port一樣,那麼可以肯定這個NAT是個CONE NAT,否則是對稱NAT。道理很簡單:根據對稱NAT的規則,當目的地址的IP和port有任何一個改變,那麼NAT都會重新分配一個port使用,而在step3中,和step1對應,我們改變了IP和port。因此,如果是對稱NAT,那這兩個port肯定是不同的。

如果在你的應用中,到此步的時候PORT是不同的,那麼這個它就是處在一個對稱NAT下了。如果相同,那麼只剩下了restrict cone 和port restrict cone。系統用step4探測是是那一種。

STEP4.判斷是處於Restrict Cone NAT還是Port Restrict NAT之下: 注意這步是base step1的,可以理解爲1.2節

B向C的IP2的一個端口PD發送一個數據請求包,要求C用IP2和不同於PD的port返回一個數據包給B。

我們來分析結果:如果B收到了,那也就意味着只要IP相同,即使port不同,NAT也允許UDP包通過。顯然這是Restrict Cone NAT。如果沒收到,沒別的好說,Port Restrict NAT.

到這裏STUN Server一共通過這4步,判斷出客戶端處於什麼類型的NAT下,然後去做後續的處理:

這4步都會返回給客戶端它的公網IP、Port和NAT類型,除此之外:

  1. 如果A處於公網或者Full Cone Nat下,STUN不做其他的了,因爲其他客戶端可以直接和A進行通信。

     

    [email protected]

  2. 如果A處於Restrict Cone或者Port Restrict NAT下,STUN還會協調TURN進行NAT打洞。

     

    Paste_Image.png

  3. 如果A處於對稱NAT下,那麼點對點連接下,NAT是無法進行打洞的。所以爲了通信,只能採取最後的手段了,就是轉成C/S架構了,STUN會協調TURN進行消息轉發。

     

    Paste_Image.png

2.TURN Server也主要做了兩件事:

  • 爲NAT打洞:

如果A和B要互相通信,那麼TURN Server,會命令A和B互相發一條信息,這樣各自的NAT就留下了對方的洞,下次他們就可以之間進行通信了。

  • 爲對稱NAT提供消息轉發:

當A或者B其中一方是對稱NAT時,那麼給這一方發信息,就只能通過TURN Server來轉發了。

最後補充一下,爲什麼對稱NAT無法打洞:

假如A、B進行通信,而B處於對稱NAT之下,那麼A與B通信,STUN拿到A,B的公網地址和端口號都爲10000,然後去協調TURN打洞,那麼TURN去命令A發信息給B,則A就在NAT打了個B的洞,但是這個B的洞是端口號爲10000的洞,但是下次B如果給A發信息,因爲B是對稱NAT,它給每個新的IP發送信息時,都重新對應一個公網端口,所以給A發送請求可能是公網10001端口,但是A只有B的10000端口被打洞過,所以B的請求就被丟棄了。
顯然Server是無法協調客戶端打洞的,因爲協調客戶端打得洞僅僅是上次對端爲Server發送端口的洞,並不適用於另一個請求。

最後的最後再補充一點,就是NAT打的洞也是具有時效性的,如果NAT超時了,那麼還是需要重新打洞的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章