WebRTC 傳輸協議詳解

我們知道WebRTC要解決的是兩個瀏覽器之間如何進行實時音影片互動的問題。從底層來看,就是要解決兩個點之間如何進行高效的網路傳輸。這就涉及要很多重要的傳輸協議,下面我們針對涉及到的協議進行梳理和說明。

一、NAT(Network Address Translator)

NAT主要做的事情就是地址對映,其作用就是將內網的主機經過NAT的對映生成外網的ip地址和埠,如下圖所示:

WebRTC 傳輸協議詳解

NAT產生的原因如下:

IPV4的地址不夠。

處於安全考慮,保證某區域網下的裝置的安全。

NAT的種類有以下幾種:

完全錐型NAT:所有從同一個內網IP和埠號傳送過來的請求都會被對映成同一個外網IP和埠號,並且任何一個外網主機都可以透過這個對映的外網IP和埠號向這臺內網主機發送包。

地址限制錐型NAT:它也是所有從同一個內網IP和埠號傳送過來的請求都會被對映成同一個外網IP和埠號。與完全錐形不同的是,外網主機只能夠向先前已經向它傳送過資料包的內網主機發送包。

埠限制錐型NAT:埠限制錐形NAT與限制錐形NAT很相似,只不過它包括埠號。也就是說,一臺IP地址X和埠P的外網主機想給內網主機發送包,必須是這臺內網主機先前已經給這個IP地址X和埠P傳送過資料包。

對稱型NAT:所有從同一個內網IP和埠號傳送到一個特定的目的IP和埠號的請求,都會被對映到同一個IP和埠號。如果同一臺主機使用相同的源地址和埠號傳送包,但是發往不同的目的地,NAT將會使用不同的對映。此外,只有收到資料的外網主機才可以反過來向內網主機發送包。

二、STUN(Session Traversal Utilities for NAT)

STUN即NAT會話穿透實用工具[RFC5389],用於進行UAT穿透,採用的是典型的客戶端/服務端模式。客戶端傳送請求,服務端進行響應。

STUN是一個C/S架構的協議,支援兩種傳輸型別。一種是請求/響應型別,由客戶端給服務端傳送請求並等待服務端響應;另一種是指示型別,由伺服器或者客戶端傳送指示,另一方不產生響應。兩種型別的傳輸都包含一個96位的隨機數作為事務ID(transaction ID),對於請求/響應型別,事務ID允許客戶端將響應和產生響應的請求連線起來;對於指示型別,事務ID通常作為debugging aid使用。

STUN報文和大多數網路型別的格式一樣,是以大端編碼(big-endian)的,即最高有效位在左邊。所有的STUN報文都以20位元組(160位)的頭部開始,後面跟著若干個屬性。

2。1 STUN報文頭部

STUN頭部包含了STUN訊息型別,magic cookie,事務ID和訊息長度,如下:

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0 0| STUN Message Type | Message Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Magic Cookie | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | Transaction ID (96 bits) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

下面來說明一下報文頭部的各個資料的意義:

前兩位必須設定為00,這樣可以在當STUN和其他協議複用的時候,用來區分STUN包和其他資料包,如RTP資料的報頭前兩位為01。

Message Length

欄位儲存了資訊的長度,以位元組為單位,不包括20位元組的STUN頭部。由於所有的STUN屬性都是都是4位元組對齊(填充)的,因此這個欄位最後兩位應該恆等於零,這也是辨別STUN包的一個方法之一。

STUN Message Type

是14位是訊息型別,其中包括訊息型別和訊息主方法。

Magic Cookie

欄位包含固定值

0x2112A442

,這是為了前向相容RFC3489,因為在classic STUN中,這一區域是事務ID的一部分。另外選擇固定數值也是為了伺服器判斷客戶端是否能識別特定的屬性。還有一個作用就是在協議多路複用時候也可以將其作為判斷標誌之一。

Transaction ID

欄位是個96位的識別符號,用來區分不同的STUN傳輸事務。對於request/response傳輸,事務ID由客戶端選擇, 伺服器收到後以同樣的事務ID返回response;對於indication則由傳送方自行選擇。事務ID的主要功能是把request和response聯絡起來,同時也在防止攻擊方面有一定作用。服務端也把事務ID當作一個Key來識別不同的STUN客戶端,因此必須格式化且隨機在0~2^(96-1)之間。重發同樣的request請求時可以重用相同的事務ID,但是客戶端進行新的傳輸時,

必須

選擇一個新的事務ID。

2。2 STUN 屬性

在STUN報文頭部之後,通常跟著0個或者多個屬性,每個屬性必須是TLV編碼的(Type-Length-Value)。其中Type欄位和Length欄位都是16位,如下:

0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Value (variable) 。。。。 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

2。3 STUN 通訊過程

1。 產生一個Request或Indication

當產生一個Request或者Indication報文時,終端必須根據上文提到的規則來生成頭部,class欄位必須是Request或者Indication,而method欄位為Binding或者其他使用者拓展的方法。屬性部分選擇該方法所需要的對應屬性。

2。 傳送Requst或Indication

目前,STUN報文可以透過UDP,TCP以及TLS-over-TCP的方法傳送,其他方法在以後也會新增進來。STUN的使用者必須指定其使用的傳輸協議,以及終端確定接收端IP地址和埠的方式。

下面說明一下使用不同方式傳送報文的通訊機制:

透過UDP傳送:當使用UDP協議執行STUN時,STUN的報文可能會由於網路問題而丟失。可靠的STUN請求/響應傳輸是透過客戶端重發request請求來實現的,因此,在UDP執行時,Indication報文是不可靠的。STUN客戶端透過RTO(Retransmission TimeOut)來決定是否重傳Requst,並且在每次重傳後將RTO翻倍。具體重傳時間的選取可以參考相關文章,如RFC2988。重傳直到接收到Response才停止,或者重傳次數到達指定次數Rc,Rc應該是可配置的,且預設值為7。

透過TCP或者TCP-over-TLS傳送:對於這種情景,客戶端開啟對伺服器的連線。在某些情況下,此TCP連結只傳輸STUN報文,而在其他拓展中,在一個TCP連結裡可能STUN報文和其他協議的報文會進行多路複用(Multiplexed)。資料傳輸的可靠性由TCP協議本身來保證。值得一提的是,在一次TCP連線中,STUN客戶端可能發起多個傳輸,有可能在前一個Request的Response還沒收到時就再次傳送了一個新的Request,因此客戶端應該在確認所有STUN事務都已完成之前保持TCP連結開啟。

需要更多ffmpeg/webrtc。。音影片流媒體開發學習資料加群812855908領取

WebRTC 傳輸協議詳解

3。 接受STUN訊息

當STUN終端接收到一個STUN報文時,首先檢查報文的規則是否合法,即前兩位是否為0,magic cookie是否為0x2112A442,報文長度是否正確以及對應的方法是否支援。 如果訊息類別為Success/Error Response,終端會檢測其事務ID是否與當前正在處理的事務ID相同。如果使用了FINGERPRINT拓展的話還會檢查FINGERPRINT屬性是否正確。 完成身份認證檢查之後,STUN終端會接著檢查其餘未知屬性。

3.1 處理Request

如果請求包含一個或者多個強制理解的未知屬性,接收端會返回error response,錯誤程式碼420(ERROR-CODE屬性), 而且包含一個UNKNOWN-ATTRIBUTES屬性來告知傳送方哪些強制理解的屬性是未知的。服務端接著檢查方法和其他指定要求,如果所有檢查都成功, 則會產生一個Success Response給客戶端。

3。1。1 生成Success Response或Error Response

如果伺服器透過某種

驗證方法(authentication mechanism)

通過了請求方的驗證,那麼在響應報文裡最好也加上對應的驗證屬性。

伺服器端也應該加上指定方法所需要的屬性資訊,另外協議建議伺服器返回時也加上SOFTWARE屬性。

對於Binding方法,除非特別指明,一般不要求進行額外的檢查。當生成Success Response時,伺服器在響應里加上XOR-MAPPED-ADDRESS屬性。 對於UDP,這是其源IP和埠資訊,對於TCP或TLS-over-TCP,這就是伺服器端所看見的此次TCP連線的源IP和埠。

3。1。2 傳送Success Response或Error Response

傳送響應時候如果是用UDP協議,則發往其源IP和埠,如果是TCP則直接用相同的TCP連結回發即可。

3.2 處理Indication

如果Indication報文包含未知的強制理解屬性,則此報文會被接收端忽略並丟棄。如果對Indication報文的檢查都沒有錯誤,則服務端會進行相應的處理, 但是不會返回Response。對於Binding方法,一般不需要額外的檢查或處理。收到資訊的服務端僅需要重新整理對應NAT的埠繫結。

由於Indication報文在用UDP協議傳輸時不會進行重傳,因此傳送方也不需要處理重傳的情況。

3.3 處理Success Response

如果Success Response包含了未知的強制理解屬性,則響應會被忽略並且認為此次傳輸失敗。客戶端對報文進行檢查透過之後,就可以開始處理此次報文。

以Binding方法為例,客戶端會檢查報文中是否包含XOR-MAPPED-ADDRESS屬性,然後是地址型別,如果是不支援的地址型別,則這個屬性會被忽略掉。

3.4 處理Error Response

如果Error Response包含了未知的強制理解屬性,或者沒有包含ERROR-CODE屬性,則響應會被忽略並且認為此次傳輸失敗。 隨後客戶端會對驗證方法進行處理,這有可能會產生新的傳輸。

到目前為止,對錯誤響應的處理主要基於ERROR-CODE屬性的值,並遵循如下規則:

如果error code在300到399之間,客戶端被建議認為此次傳輸失敗,除非用了ALTERNATE-SERVER拓展;

如果error code在400到499之間,客戶端認為此次傳輸失敗;

如果error code在500到599之間,客戶端可能會需要重傳請求,並且必須限制重傳的次數。

任何其他的error code值都會導致客戶端認為此次傳輸失敗。

三、TURN(Traversal Using Replays around NAT)

TURN的全稱為Traversal Using Relays around NAT,是STUN/RFC5389的一個拓展,主要添加了Relay功能。如果終端在NAT之後,那麼在特定的情景下,有可能使得終端無法和其對等端(peer)進行直接的通訊,這時就需要公網的伺服器作為一箇中繼,對來往的資料進行轉發。這個轉發的協議就被定義為TURN。TURN和其他中繼協議的不同之處在於,它允許客戶端使用同一個中繼地址(relay address)與多個不同的peer進行通訊。

如果TURN使用於ICE協議中,relay地址會作為一個候選,由ICE在多個候選中進行評估,選取最合適的通訊地址。一般來說中繼的優先順序都是最低的。TURN協議被設計為ICE協議(Interactive Connectivity Establishment)的一部分,而且也強烈建議使用者在他們的程式裡使用ICE,但是也可以獨立於ICE的執行。值得一提的是,TURN協議本身是STUN的一個拓展,因此絕大部分TURN報文都是STUN型別的,作為STUN的一個拓展,TURN增加了新的方法(method)和屬性(attribute)。

操作概述

在典型的情況下,TURN客戶端連線到內網中,並且透過一個或者多個NAT到達公網,TURN伺服器架設在公網中,不同的客戶端以TURN伺服器為中繼和其他peer進行通訊,如下圖所示:

Peer A Server-Reflexive +————-+ Transport Address | | 192。0。2。150:32102 | | | /| | TURN | / ^| Peer A | Client’s Server | / || | Host Transport Transport | // || | Address Address | // |+————-+ 10。1。1。2:49721 192。0。2。15:3478 |+-+ // Peer A | | ||N| / Host Transport | +-+ | ||A|/ Address | | | | v|T| 192。168。100。2:49582 | | | | /+-+ +————-+| | | |+————-+ / +————-+ | || |N| || | // | | | TURN |v | | v| TURN |/ | | | Client |——|A|——————| Server |——————————| Peer B | | | | |^ | |^ ^| | | | |T|| | || || | +————-+ | || +————-+| |+————-+ | || | | | || | | +-+| | | | | | | | | Client’s | Peer B Server-Reflexive Relayed Transport Transport Address Transport Address Address 192。0。2。1:7000 192。0。2。15:50000 192。0。2。210:49191

在上圖中,左邊的TURN Client是位於NAT後面的一個客戶端(內網地址是10。1。1。2:49721),連線公網的TURN伺服器(預設埠3478)後,伺服器會得到一個Client的

反射地址

(Reflexive Transport Address, 即NAT分配的公網IP和埠)192。0。2。1:7000,此時Client會透過TURN命令建立或管理

ALLOCATION

,allocation是伺服器上的一個數據結構,包含了中繼地址的資訊。伺服器隨後會給Client分配一箇中繼地址,即圖中的192。0。2。15:50000,另外兩個對等端若要透過TURN協議和Client進行通訊,可以直接往中繼地址收發資料即可,TURN伺服器會把發往指定中繼地址的資料轉發到對應的Client,這裡是其反射地址。

Server上的每一個allocation都唯一對應一個client,並且只有一箇中繼地址,因此當資料包到達某個中繼地址時,伺服器總是知道應該將其轉發到什麼地方。但值得一提的是,一個Client可能在同一時間在一個Server上會有多個allocation,這和上述規則是並不矛盾的。

傳輸

在協議中,TURN伺服器與peer之間的連線都是基於UDP的,但是伺服器和客戶端之間可以透過其他各種連線來傳輸STUN報文,比如TCP/UDP/TLS-over-TCP。 客戶端之間透過中繼傳輸資料時候,如果用了TCP,也會在服務端轉換為UDP,因此建議客戶端使用UDP來進行傳輸。 至於為什麼要支援TCP,那是因為一部分防火牆會完全阻擋UDP資料,而對於三次握手的TCP資料則不做隔離。

分配(Allocations)

要在伺服器端獲得一箇中繼分配,客戶端須使用分配事務。 客戶端傳送分配請求(Allocate request)到伺服器,然後伺服器返回分配成功響應,幷包含了分配的地址。客戶端可以在屬性欄位描述其想要的分配型別(比如生命週期)。由於中繼資料實現了安全傳輸,伺服器會要求對客戶端進行驗證,主要使用STUN的 long-term credentail mechanism。

傳送機制(Send Mechanism)

client和peer之間有兩種方法透過TURN server交換應用資訊,第一種是使用

Send

Data

方法(method),第二種是使用通道(channels),兩種方法都透過某種方式告知伺服器哪個peer應該接收資料,以及伺服器告知client資料來自哪個peer。

Send Mechanism使用了Send和Data指令(Indication)。其中Send指令用來把資料從client傳送到server,而Data指令用來把資料從server傳送到client。

四、ICE(Interactive Connectivity Establishment)

ICE跟STUN和TURN不一樣,ICE不是一種協議,而是一個框架(Framework),它整合了STUN和TURN。

其模型如下:

WebRTC 傳輸協議詳解

如上圖所示,如果A想與B通訊,那麼其過程如下:

1)。 A收集所有的IP地址,並找出其中可以從STUN伺服器和TURN伺服器收到流量的地址;

2)。 A向STUN伺服器傳送一份地址列表,然後按照排序的地址列表向B傳送啟動資訊,目的是實現節點間的通訊;

3)。 B向啟動資訊中的每一個地址傳送一條STUN請求;

4)。 A將第一條接收到的STUN請求的回覆資訊傳送給B;

5)。 B接到STUN回覆後,從中找出那些可在A和B之間實現通訊的地址;

6)。 利用列表中的排序列最高的地址進一步的裝置間通訊。

由於該技術是建立在多種NAT穿透協議的基礎之上,並且提供了一個統一的框架,所以ICE具備了所有這些技術的優點,同時還避免了任何單個協議可能存在的缺陷。因此,ICE可以實現在未知網路拓撲結構中實現的裝置互連,而且不需要進行對手配置。另外,由於該技術不需要為VoIP流量手動開啟防火牆,所以也不會產生潛在的安全隱患。