Web 前端 WebRTC 攻略: NAT 穿越與 ICE

WebRTC 進行端對端進行實時音視頻通訊時,常常一方或者雙方都是隱藏在 NAT 之後的內網地址。ICE 則用於尋找一條傳輸數據通道連接。本文介紹了 NAT 穿越和 ICE 框架的基礎知識和主要步驟。

我們知道使用 WebRTC 進行端對端進行實時音視頻通訊時,WebRTC 本身是基於點對點(Peer-to-Peer)連接的,最便捷的方式就是通話的雙方通過 IP 直連,擺脫原始的直播服務器中轉的方式。

如果連接雙方都是公網地址,則可以直接訪問到對方,從而建立連接。但是在現實的應用場景中,大部分情況下其中一方或者雙方都不是公網地址,而是隱藏在 NAT(Network Address Translation,網絡地址轉換)之後的內網地址。

比如局域網 A 中的 192.168.2.232 和局域網 B 中的 192.168.2.161 之間是不能直接連接通訊的。由於需要連接的個人設備絕大多數都隱藏在各自的內網當中,導致無法直接獲取客戶端 IP 地址,也無法直接進行 P2P 的音視頻通信。

爲了解決這個問題,WebTRTC 採用了 ICE 技術框架來實現 NAT 穿越。

一、NAT 網絡地址轉換

1. 什麼是 NAT

或許你在之前聽聞過 IPv4 地址枯竭的報道,IPv4 地址只有 32 位長,理論最多 42.9 億條。大概在 94 年時候,提出了 **NAT( Network Address Translation 網絡地址轉換)**RFC 規範,作爲一個臨時方案來解決 IPv4 地址枯竭的問題。

這個方案就是把 IP 地址重用,在邊緣網絡引入 NAT 設備,由它來負責維護本地服務 IP 和端口的映射到公網 IP 和端口。NAT 內部的本地 IP 地址空間可以被許多不同的子網絡重用,從而解決地址耗盡的問題。

可是臨時方案很快成爲了最終方案,成爲了互聯網基礎設施的組成部分。它不僅用來解決 IP 地址枯竭的問題,你能發現路由器、防火牆、代理設備都具備 NAT 功能。

2. NAT 類型

關於 NAT 被人們研究總結過,大體兩種:錐型和對稱型。而錐型又可分細分爲三種。

所以歸納起來,總共四種類型:完全錐型、IP 限制錐型、端口限制錐型對稱型。

a. 完全錐型

當內網 Host 與外網機器通訊,就會在 NAT 上打洞,這個過程就是指在 NAT 建立內外網映射表,這個表上記錄內外網 IP 端口映射關係。外網機器與 P 地址 p 端口的通訊,都會在 NAT 上轉發到對應的內網地址與端口,從而實現和內網 host 機器通訊。

b. IP 限制型

IP 限制錐型更加嚴格,在完全錐形基礎上,只允許 Host 訪問過的 IP 通過打洞。(映射表多記錄了被訪問外網的 IP 地址)如圖,A 和 C 等其它外網主機想通過 B 機的打洞 IP 端口,也是無法和 Host 通訊。

c. 端口限制錐型

端口限制錐型比 IP 限制錐型更加嚴格,IP 限制錐型不限制端口。IP 限制錐型情況下,同一外網主機的其它端口服務,都能和內網 Host 通訊。但是端口限制性情況下,只允許外網機器指定的端口服務通過打洞。(映射表多記錄了被訪問的外網的 IP 地址和端口

d. 對稱型

對稱型,是最嚴格的 NAT 類型,它一樣有 IP 和端口限制(這點和端口限制錐型一致)。它最大不同在於,每次連接都會在 NAT 上新開 IP 地址或者新開 IP 地址和端口與外網通訊。也就是說每一次 NAT 的打洞都不相同。基本上對稱型 NAT 是無法穿越的。

3. NAT 類型檢測

根據上面的介紹,我們可以瞭解到,在實際的網絡場景中,各種設備所處的網絡環境是不同的。那麼在進行設備間的通信之前,首先需要判斷出設備當前所處的網絡類型是非常重要的一步。

下圖是在 STUN(Session Traversal Utilities for NAT),對於 NAT 類型檢測的流程圖。當走到紅色結束時:表明穿越失敗,無法 UDP 通訊。當走到綠色(公網地址)或黃色時(錐型 NAT)纔可能進行通訊。

整個流程大體上發起了 5 次檢測:

test1

test2

test3

test4

test5

以上關於 NAT,及其打洞和穿越原理的介紹。實際穿越比這個包含更多細節且更加複雜,可以參考有相應的 RFC 規範 RFC5389 進行了解,但是整個耗時還是相當快的。

二、STUN/TURN 協議

前文提到,客戶主機不可避免的在防火牆或 NAT 之後。在 UDP 傳輸時,一般只會帶上 NAT 的 Host。如果沒有目標機器的 entry 是不會轉發到目標機器。在 client-server 情形下沒有問題。如果是 peer-to-peer 情形下則無法傳輸。因此我們需要藉助 STUN/TURN 方式進行 NAT 穿透。


WebRTC 採用了 ICE(Interactive Connectivity Establishment)建立端到端的數據通道。說到 ICE,就不得不提到它的兩個工具協議:STUN(Session Traversal Utilities for NAT)和 TURN(Travelsal Using Relays around NAT)協議。

1. STUN 

a. 標準規範定義

STUN,首先在 RFC3489 中定義,作爲一個完整的 NAT 穿透解決方案,英文全稱是 Simple Traversal of UDP Through NATs,即簡單的用 UDP 穿透 NAT。

在 RFC5389 修訂中把 STUN 協議定位於爲穿透 NAT 提供工具,而不是一個完整的解決方案,英文全稱是 Session Traversal Utilities for NAT,即 NAT 會話穿透效用。

b. STUN 用途

c. STUN 服務的簡易過程

內網主機需要藉助 STUN 服務器,遵循 STUN 協議機制,便能得到本機 NAT 映射後的外網的 IP 和端口,以下是簡易過程。

  1. 首先在搭建一個 STUN 服務器,現在比較流行的 STUN 服務器是 CoTURN。

  2. 內網主機發送一個 binding request 的 STUN 消息到 STUN 服務器。

  3. STUN 服務器收到 binding request 後,會將請求的 IP 地址和端口填充到 binding response 消息中,再原路將該消息返回給內網主機。

  4. 收到 binding response 的內網主機就會解析 binding response 消息了,並可以從中得到自己的外網 IP 和端口。

2. TURN

a. 標準規範定義

TURN,在 RFC5766 中定義,英文全稱 Traversal Using Relays around NAT(TURN):Relay Extensions to Session Traversal Utilities for NAT(STUN),即使用中繼穿透 NAT:STUN 的中繼擴展。簡單的說,TURN 是通過兩方通訊的 “中間人” 方式實現穿透。 注意:這裏Relay 或 TURN 是同一個概念都是值中繼型傳輸。

b. 用途

當 STUN 服務檢測,發現直接以 peer-to-peer 的形式連接時,就走 TURN 方式,使用中間網點提供的中繼連接服務。TURN 協議就是用來允許主機控制中繼的操作並且使用中繼與對端交換數據。TURN 與其它中繼控制協議不同的是它能夠允許一個客戶端使用一箇中繼地址與多個對端連接。

三、ICE 連接機制

1. 收集 ICE Candidate(候選項)

WebRTC 兩端要進行連接時,每一端都會提供多個候選者,比如一端有兩塊網卡,那麼每塊網卡的不同端口都對應一個候選者。

ICE Candidate 主要分爲以下三種類型:

一般由以下字段組成:

IP: xxx.xxx.xxx.xxx       \\IP地址
  port: number              \\端口
  type: host/srflx/relay    \\類型
  priority: number          \\優先級
  protocol: UDP/TCP         \\傳輸協議
  usernameFragment: string  \\訪問服務的用戶名
  ...

2. ICE 連接流程

a. 連通性檢測

當收集完 ICE Candidate 後,雙方通過信令通道交換,並拿到彼此的 ICE candidate 之後,WebRTC 就開始按優先級順序進行連通性檢測了。

一般情況下:host 類型的候選者優先級是最高的,srflx 類型次之,最後是 relay 類型。

這個階段對於對等項發來的通過身份驗證的任何 STUN 連接 request,ICE 代理都會生成 STUN response。候選項依照之前的排序按次序進行檢查,當收到對方的響應時,檢查視爲成功,而如果檢查超時後仍沒有收到響應時,則該候選對失敗。

連通性檢測的原則簡單歸納:

b. 選定候選項

在 WebRTC 中,P2PTransportChannel 會維護連接狀態表,並排序表中記錄(Sort-Connections-And-UpdateState)。排序指的是計算每條記錄的連接 “成本“,把成本最低的排在第一位。如何計算成本則涉及到很多因素,比如發出 STUN 請求到收到應答耗時,用時越少的“成本” 自然會低些。當一端有視頻 RTP 數據要發送時,會檢查狀態表的第一條記錄,如果判斷出它的狀態是發送就緒,就會用此 Connection 進行發送。否則直接放棄這個發送任務。 

c. ICE 長連接和重啓

爲了確保 NAT 映射和過濾規則不在音視頻通話過程中超時,ICE 會不斷對使用中的候選項對(通道)進行連接檢查,每 15s 發送一次,這樣是爲了保證在音視頻流暫停等情況下沒有發送數據流時,仍然有數據包持續發送。

當 ICE 代理檢測到正在使用的傳輸地址發生更改或連接時,會觸發重新啓動 ICE 事件,也就是會重新回到收集 ICE candidate 及其之後的流程。

四、小結

其實 WebRTC 的 ICE 就是包括 STUN、TURN 協議的一套框架,用於找到一條可用且最優傳輸數據通道連接。瞭解 NAT 穿越和 ICE 框架的基礎知識,你會更容易理解 WebRTC 如何建立連接並傳輸數據。當然實際的 ICE 過程要複雜很多,本文只是簡要介紹主要的步驟,感興趣的讀者可以自行閱讀參考 RFC5245。

參考文章與規範:

 https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Protocols 

https://datatracker.ietf.org/doc/html/rfc5245

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/yIC3pNvQp-YrLUD-pjz1iw