完整SIP/SDP媒體協商概論-ICE概覽

在前面的章節中,我們完整介紹了SIP中SDP的offer/answer交互流程。接下來,我們重點介紹關於SDP在WebRTC中的交互方式以及使用ICE來支持NAT處理的內容。一些讀者可能注意到了,WebRTC技術雖然具有非常大的市場前景,但是因為本身和瀏覽器等其他工具的兼容性問題,發展的速度仍然沒有想象的那麼快,一些應用場景也不是太完善。很多針對ICE的規範也快速進行更迭。最近的一次更迭就是針對ICE的RFC5245規範已廢除,使用了RFC8445。因為,RFC8445是2018年發佈的最新的規範,因此,可能一些廠家的產品還沒有完全實現對此規範版本的支持。所以,我們的討論儘量按照RFC5245的規範來進行,也同時兼顧RFC8445的框架。提前說明,WebRTC中關於ICE的規範流程非常龐雜,筆者需要分成多個章節來解釋。所以,在WebRTC/ICE章節需要花費一定的時間,如果讀者對ICE沒有興趣的話或者暫時沒有使用WebRTC技術的話,可以跳過關於WebRTC/ICE的介紹直接閱讀SIP/SDP的部分內容


在本章節和後續章節的討論中,筆者將根據RFC5245/RFC8445的規範架構,結合筆者的這篇歷史文章來討論WebRTC/ICE的技術內容。希望通過筆者完整的討論,讀者可以非常清楚瞭解WebRTC的流程,特別是關於ICE的處理。筆者在文章中使用的一些本規範的專有名詞(例如,check 或者check list,事實上,在本規範中它具有特定的含義),可能沒有直接以中文的名稱來介紹,這樣做的目的是為了保證不會產生歧義,所以筆者儘量使用規範中的專有名詞來解釋。所以,請讀者在閱讀時一定要注意。


說明:1)一些專有名詞以前的章節中已經發布,這裡不再介紹。2)筆者本人水平有限,文章中所使用的專有名詞中文命名或解釋可能和其他網上的的有所不同,建議讀者參考RFC原文理解或者發郵件給規範起草人獲得支持。


筆者會在接下來的章節中重點討論關於ICE的背景介紹,ICE概覽,ICE使用/ICE候選對象採集交互,ICE候選對象流程處理,執行連接性檢查,結束ICE流程,ICE啟動/選項等話題。


在前面的章節中,我們完整介紹了SIP中SDP的offer/answer交互流程。接下來,我們重點介紹關於SDP在WebRTC中的交互方式以及使用ICE來支持NAT處理的內容。一些讀者可能注意到了,WebRTC技術雖然具有非常大的市場前景,但是因為本身和瀏覽器等其他工具的兼容性問題,發展的速度仍然沒有想象的那麼快,一些應用場景也不是太完善。很多針對ICE的規範也快速進行更迭。最近的一次更迭就是針對ICE的RFC5245規範已廢除,使用了RFC8445。因為,RFC8445是2018年發佈的最新的規範,因此,可能一些廠家的產品還沒有完全實現對此規範版本的支持。所以,我們的討論儘量按照RFC5245的規範來進行,也同時兼顧RFC8445的框架。提前說明,WebRTC中關於ICE的規範流程非常龐雜,筆者需要分成多個章節來解釋。所以,在WebRTC/ICE章節需要花費一定的時間,如果讀者對ICE沒有興趣的話或者暫時沒有使用WebRTC技術的話,可以跳過關於WebRTC/ICE的介紹直接閱讀SIP/SDP的部分內容,或者,如果讀者僅想了解WebRTC技術和基本的工作原理的話,可以閱讀:

完整WebRTC技術及應用概要

在本章節和後續章節的討論中,筆者將根據RFC5245/RFC8445的規範架構,結合筆者的這篇歷史文章來討論WebRTC/ICE的技術內容。希望通過筆者完整的討論,讀者可以非常清楚瞭解WebRTC的流程,特別是關於ICE的處理。筆者在文章中使用的一些本規範的專有名詞(例如,check 或者check list,事實上,在本規範中它具有特定的含義),可能沒有直接以中文的名稱來介紹,這樣做的目的是為了保證不會產生歧義,所以筆者儘量使用規範中的專有名詞來解釋。所以,請讀者在閱讀時一定要注意。


說明:1)一些專有名詞以前的章節中已經發布,這裡不再介紹。2)筆者本人水平有限,文章中所使用的專有名詞中文命名或解釋可能和其他網上的的有所不同,建議讀者參考RFC原文理解或者發郵件給規範起草人獲得支持。


筆者會在接下來的章節中重點討論關於ICE的背景介紹,ICE概覽,ICE使用/ICE候選對象採集交互,ICE候選對象流程處理,執行連接性檢查,結束ICE流程,ICE啟動/選項等話題。


1

背景介紹

如果讀者看過前面的SDP全解的讀者可能已經瞭解,SIP使用了offer/answer結合模式,通過SDP消息來實現媒體傳輸,其最終目的是實現媒體流之間的創建和完整傳輸。ICE英文全名是Interactive Connectivity Establishment。RFC5245(更新的RFC6336)對ICE做了規定。一般簡單的定義是:ICE=STUN+TURN+協商機制+協商路徑


但是,因為網絡越來越複雜,終端的環境也發生了根本變化,因此NAT問題也越來越多。RFC3235規範針對NAT(地址轉換)發佈了一個指導。很多相關的協議希望通過媒體流之間的點對點傳輸解決媒體本身的問題(例如,低時延,降低丟包,降低部署成本),但是在涉及到NAT環境時,通常會遇到一些問題,導致實際部署的難度大大增加。為了解決NAT的問題,很多針對性的技術規範增加了對NAT環境的支持,常見的規範如:

  • Application Layer Gateways (ALGs)
  • Middlebox Control Protocol (RFC 3303)
  • STUN(RFC 3489)
  • Realm Specific IP(RFCs 3102和3103)
  • SDP拓展支持(RFC 4566和RFC 3605)


隨著技術本身的不斷髮展,這些針對NAT支持的規範也帶來了很多突出的問題,它們都存在各自的優缺點。這樣的話,網絡管理就會增加很多的不確定性,給系統管理帶來很多問題。為了解決這些問題,一些相關規範組織希望使用一種統一的解決方式或規範,並且這種協議可以提供靈活性來滿足目前網絡環境對NAT的支持。目前,市場上一致的

共識就是使用ICE技術(Interactive Connectivity Establishment)。此規範通過offer/answer模式定義ICE來支持基於UDP的媒體流NAT問題(當然,ICE也可以通過拓展支持ICE-TCP傳輸協議)。

技術進步的動力就是為了解決目前存在的問題。


ICE是offer/answer模式的一種拓展形式,通過在SDP的offer/answer消息中包含多個地址和端口,使用這些地址端口和其交互消息來檢測點對點的連接性。在SDP中的地址和端口,以及其連接性檢測是通過STUN來完成。注意,關於STUN的最新規範已經再次更新(更新時間為2020年),如果讀者有興趣做進一步研究,可參考RFC5389和RFC8489。除了STUN以外,ICE也使用了STUN的另外一個拓展協議-TURN(RFC5766)實現穿越轉發。另外,因為ICE對每個媒體流進行了多地址和端口交互,它也允許地址選擇支持多宿主和雙棧主機(IPv4/IPv6),因此也不再支持RFC4091和RFC4092。


2

ICE概覽

在一個比較典型的ICE部署環境中,至少需要兩個終端需要互相進行通信。終端之間可以通過一些信令結合SDP的offer/answer模式來實現,例如,我們前面講的SIP協議。讀者需要注意,ICE的目的不是為了某些協議(例如SIP)的NAT穿越,關於SIP相關的NAT穿越是通過RFC5626規定的,如果讀者有興趣的話,可以查閱此規範。這裡,ICE假設終端之間可以創建協議連接。具體來說,在ICE流程處理開始階段,agents就忽略了它們本身技術屬性。終端也可能在或不在NAT後,ICE允許終端獲取到技術屬性的足夠信息,然後找到一個或多個潛在的路徑,創建數據會話實現相互

圖片均來自於互聯網資源


聯網資源


在以上示例是一個非常典型的ICE部署場景示例。兩個終端分別標識為L(左邊)和R(右邊)。兩個終端都有各自的NAT環境,雙方也不清楚對端NAT的狀態屬性,左右雙方終端都有意願通過ICE候選對象交互實現通信。很多時候,雙方的交互可能都使用SIP協議。對於雙方終端,SIP服務器和NAT來說,在網絡中,ICE經常使用STUN和TURN來保證所有對象的協同。每個終端agents可以支持自己獨立的STUN和TRUN服務器,也可以同一STUN和TURN同一服務器。基本的ICE工作理念是: 針對傳輸協議(這裡重點討論UDP)每個agent都有各種候選地址(綁定了IP地址和端口),通過這種候選地址和對端agent實現通信。候選地址可能包括:附加到網絡接口的傳輸地址(server reflexive 地址),NAT中公網側的轉換後的傳輸地址,從TURN分配到的傳輸地址(轉發地址)。客觀上存在這種可能,任何L側的候選傳輸地址都用來和任何R側的候選傳輸地址進行通信。但是,在實際場景中,過多的候選傳輸地址組合可能不能工作。例如,如果L側和R側雙方都在NAT後的話,直接附加的網絡接口地址可能不會直接通信,因此這裡需要ICE介入。這裡,ICE的目的是發現何種候選地址配對可以工作。ICE的工作方式是通過系統地嘗試所有可能的候選配對(排序處理後),直到ICE找到一組或者多組可以工作的候選配對。ICE對Peers的檢測配對需要經過六個步驟:


3

採集候選地址

如果需要執行ICE的話,agent首先需要確認候選地址。候選地址是一種特別的地址,它是由IP地址和端口的組合構成,其目的是支持傳輸協議(我們這裡僅討論UDP)。RFC8445定義了三種候選地址,一種是來自於物理網絡接口,另外一種來自於網絡的邏輯接口,還有一種是通過STURN或者TURN發現的候選地址。第一種類別的候選地址支持的傳輸地址直接從本地網絡接口獲得。這樣的候選地址我們稱之為“host candidate”,這樣類型的本地地址可以從本地網絡,WIFI,遠端網絡或者VPN的方式獲得。對agent來說,這樣的地址都可以通過分配獲得,並且作為本地接口來使用。如果agent是一個多宿主主機的話,它可以從不同的IP地址獲得候選地址。具體的候選地址如何獲得取決於網絡中peer(會話中另外一個agent)的位置。例如,如果agent支持了兩個不同的IP地址的話(一個是內網地址,一個是外網地址),不同的peer就可以通過不同的地址和agent通信。


另外一種候選地址是agent使用STUN或TURN獲得的額外的候選地址,這些候選地址主要表現為兩種地址形式:NAT公網側的已轉換地址(server-reflexive 候選地址),TURN服務器分配的轉發地址(relayed 候選地址)。這裡讀者一定要注意兩種地址的獲取方式。當使用TURN服務器時,以上兩種候選地址都來自於TURN服務器分配地址;當僅使用了STURN服務器的話,agent只能獲取到server reflexive地址。以下是候選地址的關係示例圖:


候選地址關係


在以上關係圖中,兩種類型的候選地址都是通過TURN服務器發現獲得的。這裡的地址端口配對中,大寫X表示IP地址,小寫x表示UDP端口。當agent對IP地址和端口發送一個(X:x)TURN地址分配請求時,NAT(假設這裡有NAT)就會創建一個綁定關係X1':x1',映射server-reflexive地址到主機候選地址。從本地主機候選地址發送出去的數據包將會通過NAT地址轉換變成一個server-reflexive候選地址。同樣的道理,從server-reflexive候選地址進入到主機候選地址的數據也是通過NAT地址轉換完成。這裡,base是一個比較重要的概念,需要讀者明確,“base"是一個本地主機候選地址,它關聯一個給定的server-reflexive候選地址。base指的是一個agent為指定的候選地址發出數據的地址。因此,有時存在一個比較極端的場景,主機候選地址也可以有自己的base地址,這個base 地址和主機候選地址相同。


當agent和TURN服務器存在多個NAT穿越時,TRUN請求會為每個NAT創建一個綁定,但是agent僅發現最外部的server-reflexive候選地址(距離TRUN服務器最近的候選地址)。如果agent不在NAT後的話,base 候選地址和server-reflexive候選地址相同,server-reflexive候選地址就會被移除。


Agent發出的分配請求到達TURN服務器端後,TURN服務器將會從它的本地IP地址Y中分配一個端口y,並且生成一個分配響應,分配響應通知一個agent的轉發候選地址。TRUN服務器也會通知一個agent的server-reflexive候選地址X1':x1',通知的方式是把分配請求中的源傳輸地址拷貝到分配響應中來實現。TRUN服務器的工作角色類似於一個在L側和R側之間的數據轉發。如果R側想對L側發送數據的話,R側需要發送數據到Y:y 地址,然後TRUN服務器端前轉到X1':x1'候選地址,然後經過NAT後映射到L側agent。


當僅使用了STUN服務器時,agent發送一個STUN綁定請求給它的STUN服務器,STUN將會通知一個agent的server-reflexive候選地址X1':x1',其通知的方式是綁定請求中的源傳輸地址拷貝到綁定響應中。


Connectivity Checks

一旦L側agent採集到它所有的後續地址後,它會把這些地址重新安裝從最高到最低的排序,然後通過信令通道發送給R側agent。這些候選地址通過SDP的offer消息的屬性參數發送到R側agent(開始使用offer/answer交互模式)。當R側agent收到offer消息後,R側的agent也會執行一個同樣的流程來採集候選地址,然後通過響應消息返回自己的候選地址。雙方採集發送流程完成以後,每個agent都有自己的完整的候選地址和對待peer的完整候選地址。通過雙方候選地址的配對處理,最後產生一個候選配對。候選地址配對產生以後,agent首先需要知道哪個候選地址配對是可以工作的,每個agent會按時設定一系列的檢查。每個檢查是一個STUN請求響應的事務,每個終端都會執行具體的候選地址配對流程,配對流程檢查通過本地候選地址對遠端候選地址發送一個STUN請求。連接性檢查(Connectivity Checks)的基本原理非常簡單:

  1. 對候選地址配對進行優先級排序
  2. 按照優先級排序順序對候選配對發送檢查請求
  3. 確認從其他agent

因此,在執行候選配對檢查時需要一個四次握手的處理:


基本候選地址配對檢查四次握手處理流程


這裡一定要注意,發送STUN請求的目的地和接收源的IP地址和端口,這是完全相同的IP地址和端口,使用此IP地址和端口來傳輸媒體流(包括RTP和RTCP)。因此,agent會通過數據內容多路分解STUN/RTP/RTCP相關數據,而不使用其接收端口來分解STUN/RTP/RTCP數據。相當於使用端口的方式來說,多路分解方式會更容易處理檢查狀態,特別是針對RTP和RTCP的數據。因為,STUN綁定請求是用來執行連接檢查的,在STUN響應中包含了agent的已轉譯的傳輸地址,這個地址是agent和對端peer之間的NAT公網側地址。如果這個傳輸地址和agent已學習過的候選地址不同的話,agent就會知道這個候選地址是一個新的地址(PEER REFLEXIVE CANDIDATE),這個新地址和其他候選地址一樣,也是ICE測試過的地址。


他候選地址一樣,也是ICE測試過的地址。


作為一種優化方式,只要R側獲得了L側的檢查消息,R側會在同一候選配對中按時對L側發送一個連接檢查消息。這樣的話,ICE就會加快發現有效候選流程處理時間,這個過程也稱之為“TRIGGERED CHECK”。在雙方握手完成以後,雙方都知道對對端可以接收或者發送端對端消息

根據連接檢查的介紹,讀者可能已經注意到了,前面我們討論的候選配對查詢算法還有一定的問題,假設候選配對存在的話,無論查詢方式是何種順序,查詢流程會一直查詢直到找到這一代候選配對。顯然,查詢的順序肯定影響候選配對的查詢結果。因此,為了快速生成候選配對結果,候選地址需要經過排序處理,最後,排序後的候選配對結果就是一個check list。關於排序算法筆者在發送初始offer的章節進行討論。基本上,排序算法需要遵守兩個基本原則

章節進行討論。基本上,排序算法需要遵守兩個基本原則:


  1. 每個agent給它的候選地址一個優先級數字標識,此優先級標識會隨候選地址發送到對端peer。
  2. 本地和遠端優先

其中,第二個原則非常重要。如果雙方L側agent和R側agent的都在NAT後的話,如果確保ICE工作,必須特別注意第二個原則。我們經常可以看到,NAT是不會允許一臺外部主機發送數據進入到NAT後的網絡環境中,只有在NAT後的agent通過NAT發送數據給這臺主機後才被允許交互,外部數據才能進入到NAT後的環境中。這裡要注意,直到agent雙方都已通過自己相關的NAT穿越發送check信息後,雙向的ICE check才能最終成功。agent需要通過check list才能啟動工作,所以,它需要週期性地發送一個STUN請求獲得列表中的候選配對。這個處理過程稱之為 “ORDINARY CHECKS”。


通常情況下,優先級算法的設計是為了同類候選地址直接獲得同樣的優先級,和一些非直接處理的方式相比,優先級算法在處理候選配對是可能更加高效。因此,通過優先級算法的處理流程可以快速高效地實現直接路由訪問,路由處理路徑中僅需要幾個媒體轉發和幾個NAT轉發。如果採用非直接處理的方式的話,候選配對可能需要更多媒體轉發和NAT轉發,經過越多的轉發就會導致越多的不可控因素。所以,這樣的方式不是一種好

越多的轉發就會導致越多的不可控因素。所以,這樣的方式不是一種好的推薦發送。


https://anyconnect.com/stun-turn-ice/

https://tools.ietf.org/id/draft-ietf-ice-rfc5245bis-13.html

https://tools.ietf.org/html/rfc8445

https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment

https://www.ietfjournal.org/interactive-connectivity-establishment/

https://ietf.org/documents/144/IETF_ICE_intro_92.pdf



分享到:


相關文章: