NAT穿越

weixin_34127717發表於2018-08-02

NAT穿越方案目前有:

  • STUN
  • TURN
  • ICE
  • 其它技術:ALG、UPnP、Midcom、Full Proxy

區別:

  • TURN、STUN、ICE都是應用程式提供的解決方案,不依賴於硬體裝置;
  • TURN、STURN的共同點都是通過修改應用層中的私網地址達到NAT穿透的效果,異同點是TURN是通過兩方通訊的“中間人”方式實現穿透。
  • ICE跟STUN和TURN不一樣,ICE不是一種協議,而是一個框架(Framework),它整合了STUN和TURN,可以穿越任何nat裝置。
  • ALG、UPnP屬於裝置提供的方案,依賴於各個終端NAT裝置的支援。

1. STUN

STUN的全稱是Simple Traversal of UDP Through Network Address Translators,即穿越NAT的簡單UDP傳輸。
它允許應用程式發現自己和公網之間的NAT型別,同時也能允許應用程式通過STUN伺服器發現自己被NAT分配的公網IP,這些資訊被用來在兩個同時處於NAT [路由器]之後的[主機]之間建立UDP通訊。

  • 優點:是無需改變nat/fw,只需要應用程式支援stun協議。
  • 缺點:不支援對防火牆和對稱NAT的穿越

2.turn

Traversal Using Relays around NAT,即採用中繼器的NAT穿越,也叫中轉方式(Relay)
與stun方式類似採用客戶端伺服器模式,但是內網主機的公共地址是伺服器分配的,內網主機傳送的報文都要經過Turn伺服器進行中繼轉發,即集中式的拓撲結構。
優點是可以解決stun無法穿越對稱式nat,也支援tcp。
缺點是當資料量大時,伺服器的併發和處理能力成為瓶頸,且增大了包的延遲和丟包的可能性。

stun是對中間伺服器輕依賴的,可是存在部分無法穿越問題;
turn對中間伺服器強依賴,但是可以穿越所有nat;
可以想到一種理想的方式,stun可以穿越的主機使用stun,stun無法穿越的部分使用turn,兩者結合。
這正是ice要做的事情,講起來簡單,其實ice的真正實現比這個複雜太多。

3.ice方式

ICE(Interactive Connectivity Establishment)互動式連線建立方式,結合了stun,turn等協議來提供一個通用的解決方案。是被認為在非對稱NAT環境下首選的NAT穿越解決方案。由於該技術不需要為VoIP流量手動開啟防火牆,所以也不會產生潛在的安全隱患。


12830151-2372f656533b0ea9.png
image.png

如上圖所示,如果A想與B通訊,那麼其過程如下:
(1)A收集所有的IP地址,並找出其中可以從STUN伺服器和TURN伺服器收到流量的地址;
(2)A向STUN伺服器傳送一份地址列表,然後按照排序的地址列表向B傳送啟動資訊,目的是實現節點間的通訊;
(3)B向啟動資訊中的每一個地址傳送一條STUN請求;
(4)A將第一條接收到的STUN請求的回覆資訊傳送給B;
(5)B接到STUN回覆後,從中找出那些可在A和B之間實現通訊的地址;
(6)利用列表中的排序列最高的地址進一步的裝置間通訊;

4. UPnP

路由器要支援UPnP並開啟

擴充:那種穿越方式最適合區塊鏈專案?
答案是:

IETF規範

  • RFC3489中定義STUN,作為一個完整的NAT穿透解決方案,英文全稱是Simple Traversal of UDP Through NATs,即簡單的用UDP穿透NAT。
  • RFC5389新修訂中把STUN協議定位於為穿透NAT提供工具,而不是一個完整的解決方案,英文全稱是Session Traversal Utilities for NAT,即NAT會話穿透效用,除了名稱變化外,最大的區別是支援TCP穿透。
  • RFC5766中定義TURN,英文全稱是Traversal Using Relays around NAT:Relay Extensions to Session Traversal Utilities for NAT,即使用中繼穿透NAT
  • RFC 5245: Interactive Connectivity Establishment (ICE): A Protocol for NAT Traversal for Offer/Answer Protocols.
  • RFC 6544: TCP Candidates with Interactive Connectivity Establishment (ICE)

TCP與UDP穿越

UDP是主流的NAT穿越協議,比起TCP穿越成功率要高很多,因為大部分NAT裝置不支援TCP的丟包處理。
反觀UDP打洞技術,缺點是無法穿越對稱形NAT,雖然可以使用埠預測的UDP穿越(因為NAT裝置對埠的隨機分配是規律性的),但是失敗率也很高。

UDP

12830151-15edcbe9d3ae6087.png
image.png

TCP

12830151-57d269faf225852d.png
image.png

TCP/UDP穿越測試結果對比

12830151-f0d5cd5f2206d814.png
image.png

問題1:tcp打洞與udp打洞的區別

  1. 會話時效問題
    通常TCP會話通過協商的方式主動關閉連線,NAT閘道器可以跟蹤這些報文,在會話結束時回收資源,清除關聯表。
    而基於UDP的通訊協議很難確定何時通訊結束,所以NAT閘道器主要依賴超時機制回收外部埠,一般是15-20秒,但是這樣做會引發很多連線中斷、找不到目標等問題,雙方必須不斷髮送心跳以保持會話。

  2. 連線問題
    udp只需要向對方傳送一次報文,就可以完成打洞,兩邊不需要建立連線,只要在有效的會話期間內(15-20s)完成打洞可以。
    tcp通訊是需要建立連線的,連線過程中,監聽的同時非同步地向對方傳送sync包,等待對方回覆ack包。如果雙發請求監聽的失效不一致可能會導致連線失敗,這時候需要設定延遲連線和重試。

  1. 套接字(socket)和埠繫結問題
    udp一個socket可以與多臺主機的通訊,建立1對多的連線;
    tcp是基於客戶端伺服器的,一般一個埠只能繫結一個socket,且只能建立1對1的連線。要建立1對多,需要使用“SO_REUSEADDR”允許應用程式將多個socket繫結到一個埠。

  2. NAT的支援問題
    UDP穿越,首先需要知道終端的NAT型別(4種型別),實際上就是需要NAT裝置對埠對映必須一致,同一個內網地址和埠建立的連線對映成相同的公網地址和埠,UDP不支援對稱形NAT(Symmertric NAT)穿越;
    TCP穿越需要NAT裝置支援對來著公網SYN包的丟棄處理,就是什麼都不做。因為有的NAT裝置收到沒有對映關係的公網SYN包會向源端傳送ICMP錯誤響應,源端收到後會直接導致TCP連線失敗;

目前的NAT路由器裝置,UDP協議比TCP協議更容易穿越成功。

問題2:同個區域網的主機進行p2p通訊,如何避免hairpin問題

hairpin 路由迴路 埠迴路 迴環NAT
案例證明了這一點:
geth私有鏈,內網兩臺電腦節點可以通過addPeer互相發現;
geth共有鏈,內網兩臺電腦節點不管是手動或者自動都無法發現對方;

問題3:p2p連線後的鑑權問題

因為nat的問題,ip+埠是動態分配、可變的,甚至還有session失效,無法作為固定的主機路由。比如區域網的兩臺主機很可能會交替使用相同的外網ip和埠出去,對於外網來說這些是不可預測的。
所以,P2P連線上,進行內容通訊前,做鑑權操作,確定目前連入的主機是所希望的。
案例:
以太坊的節點id:encode:dfdfd@139.32.33.1:30030
dddd其實是節點的公鑰,以太坊是用ECKey橢圓曲線演算法來生成金鑰對,私鑰節點自身保持,公鑰則作為節點id的一部分發給與之連線的所有節點,節點A給節點B傳送資訊前,先用B的公鑰給資訊加密,密文只有真正持有祕鑰的B才能解密,從而保證了資料傳輸的準確性和安全性;

相關文章