SIP網絡環境中,特別是涉及了多個應用節點或多個網絡要素環境的SIP呼叫中,因為涉及的網絡節點比較複雜,所以SIP路由所涉及的路徑就比較多,例如註冊服務,定位服務等,另外,因為目前的SIP網絡環境中,很多SIP呼叫業務又涉及了SBC,使用SBC作為一個SIP安全的保護機制,因此,在SIP路由或呼叫中增加了SBC處理的場景。因此,很多SIP網絡用戶就對這些相關的問題感到非常困惑。今天,筆者針對SBC和SIP路由以及所涉及的相關業務問題進行淺析和說明,希望讀者能夠對SBC,SIP路由以及路由策略有一個大概的理解。
筆者首先說明,因為篇幅有限,筆者很難在比較短的篇幅涵蓋所有細節。另外,很多基本概念在以前的歷史文檔中也早已有完整深入的介紹,所以,筆者在這裡可能簡單重複介紹一些基本的概念,或者不再介紹一些基本的概念,讀者可以查閱歷史文檔學習或者補充相關知識。最後,因為涉及到具體的業務應用,筆者只能比較寬泛地討論一些經常使用的或者相對規範的應用場景,特別具體場景這裡不再做更多討論。
針對本文章所需要涉及到的內容,筆者首先討論一些基本的針對SIP路由的相關的概念和處理流程,另外因為SIP業務伺服器可能需要經過SBC的調度處理,筆者將針對SIP路由經過SBC以後的一些流程進行討論。
1、關於SIP註冊服務介紹
在SIP技術中,非常重要的一個概念就是註冊(Registrar)。註冊本身就是一種服務的處理流程,他一般是一個資料庫存儲Registrar地址,終端用戶通過地址查找來實現其可達性的狀態查詢。如何發現註冊地址,讀者可以參考RFC10.2.6的規範細節。筆者也發布過歷史文檔,此文檔中比較詳細說明了註冊和定位的處理流程,讀者可以參考此文檔做進一步學習:
深入理解SIP伺服器的註冊和定位服務流程
在實際SIP網絡或者IP網絡的應用場景中,特別是現在的移動端的使用中,IP位址可能會經常發生變化,而且一個SIP終端帳號有幾種表現形式(一個分機同時有物理終端,PC端分機或者APP分機)。這些IP位址一般又是臨時地址,這樣的話,伺服器端對終端狀態的管理存在很多挑戰。因此,在SIP應用場景中,SIP協議使用了一個永久地址來匹配一個SIP帳號信息,這個地址就是AOR地址(address of record)。這裡,筆者提醒讀者,在一般的企業通信或者IPPBX的討論中,我們經常使用的是SIP分機的說法。那種說法或者稱謂僅在一個比較小型的內網環境的說法,我們有時為了簡單方便也使用這樣的稱謂,但是SIP呼叫流程決不僅僅是一個分機的概念,希望一些初級用戶不要對這些概念迷惑。進一步講,即使是一個IPPBX表示也集成了以下示例的所有功能模塊,在邏輯上都是獨立的,僅表現為一個一體伺服器形式而已。如果是大型的伺服器或者其他分布式部署的伺服器,這些伺服器端都各自有自己表示的邏輯功能,包括圖例中使用的註冊伺服器,定位伺服器,路由伺服器和域名解析等等。
此圖片和以下圖片資源均來自於網際網路資源
另外,在實際應用環境中,我們還有一個contact地址。這兩個基本的地址就可以綁定大部分的呼叫業務流程。針對這兩個容易混淆的地址,讀者可以簡單理解為:AOR是告知伺服器端SIP終端是誰(唯一的),Contact告訴伺服器SIP終端此時此刻在哪裡(綁定多個contacts)。呼叫SIP終端時,應該首先檢查AOR地址,然後逐一檢查contact地址狀態,最後呼叫到有效contact地址。
在以上圖例中,兩個SIP終端註冊都分別經過了4個處理流程(M1/M2,M3/M4)。
2、關於SIP proxy路由介紹
在以上討論中,除了進行註冊以外,SIP終端雙方如果需要呼叫對方的話,仍然需要藉助於第三方的其他服務功能實現路由等處理流程。Proxy或者代理伺服器就是其中一個必要的邏輯實體。一般來說,代理伺服器負責處理域名檢查,然後做相應的路由處理轉發。代理伺服器首先必須檢查請求中的SIP Request-URI,因為此參數中可能包含必要的路由的頭域參數,例如Route/Route-Record,代理伺服器根據這些路由頭進行下一步的路由轉發處理。當我們討論proxy時,另外一個比較重要的概念就是B2BUA,如果讀者對Proxy或者B2BUA迷惑的話,可以參考筆者歷史文檔:
B2BUA/SBC/Proxy的SIP消息重構和RFC7092詳解
筆者這裡不再做更多重複介紹,請讀者仔細閱讀以上連結文檔。代理伺服器獲得了Route頭以後,它就會根據代理伺服器的列表強制執行這些路由轉發處理。Route-Record則是被proxy記錄在請求中並且強制將來的請求通過此代理伺服器。當然,這些通過代理伺服器的路由還要結合本地的策略處理,這些策略處理很大程度上會影響這些記錄值。以上圖例是一個非常典型的也是一個基本的SIP呼叫拓撲示例圖。在SIP終端呼叫過程中,雙方經過了(P1,P3,P2,流程為U1 -> P1 -> P3->P2 -> U2和其相反流程)三個代理伺服器的處理。現在,我們根據以上處理流程來分析一下代理的record-routing細節。
首先,UA1呼叫了一個P1外呼的代理伺服器,其請求如下(M5):
INVITE sip:callee@office.com SIP/2.0
Contact: sip:caller@u1.example.com
這裡,P1代理伺服器沒有對office.com 負責處理,它沒有P1代理伺服器和此域名沒有任何綁定關係,因此,它交給domin解析伺服器進行解析查詢,然後把消息繼續路由到P3,並且增加了一個Route-Record,表示通過了P1代理伺服器。這裡,contact地址發送了變化,並且增加了一個路由記錄。
INVITE sip:callee@office.com SIP/2.0
Contact: sip:caller@u1.example.com
Record-Route:
P3收到以上路由的請求以後,仍然沒有查詢到相應的office.com地址,它繼續向下一個代理進行轉發路由,轉發到P2代理伺服器。Record-Route:
INVITE sip:callee@office.com SIP/2.0
Contact: sip:caller@u1.example.com
Record-Route:
Record-Route:
在P2收到P3路由過來的請求以後,P2檢查定位伺服器,對其身份進行查詢定位。它發現了這個domain office.com 以後,P2代理伺服器執行了兩個任務,首先重寫了Request-URI值,另外,它增加了一個最新的Record-Route值,記錄了office.com domain(M8)。到此為止,SIP終端雙方的呼叫明確了呼叫的最終目的地地址。
INVITE sip:callee@u2.office.com SIP/2.0 // 重寫了請求URL
Contact: sip:caller@u1.example.com
Record-Route:
Record-Route:
Record-Route:
這裡讀者一定要注意,因為Route 頭,代理伺服器可以使用請求的URL(Request-URI)來決定最終的呼叫用戶地址,因此,代理伺服器使用地址u2.office.com對被呼叫方callee進行呼叫。U2被呼叫後,返回一個響應消息(M9)流程。因為篇幅所限,其他呼叫掛機和發送BYE消息或者ACK的流程這裡不再做太多討論,筆者可參考歷史文檔學習。
3、Record-Route 修改引起的問題以及解決辦法
在前面的討論中,兩個SIP終端分別發布在不同的網絡空間(leftspace和rightspace),這兩個SIP終端之間的呼叫需要藉助於proxy(P1)來重寫Record-Route完成(U1->P1->U2)。P1相當於一個網關來實現SIP終端之間的呼叫路由處理。U1發送的請求:
INVITE sip:callee@gateway.leftprivatespace.
com SIP/2.0
Contact:
P1然後通過定位服務,查詢domain地址,對U2發送請求消息:
INVITE sip:callee@rightprivatespace.com
SIP/2.0
Contact:
Record-Route:
com;lr>
然後U2對P1發送 200 OK:
SIP/2.0 200 OK
Contact:
Record-Route:
com;lr>
P1然後重寫其Record-Route地址,支持U1所需要的地址參數,發送到U1:
SIP/2.0 200 OK
Contact:
com>
Record-Route:
com;lr>
如果U1稍晚對U2發送BYE請求時,首先發送到P1:
BYE sip:callee@u2.rightprivatespace.com
SIP/2.0
Route:
然後P1返回到U2:
BYE sip:callee@u2.rightprivatespace.com
SIP/2.0
以上是一個簡單的針對不同網絡空間,兩個SIP終端通過proxy進行的一個關於Record-Route重寫的處理流程。在實際使用過程中,讀者可能會有遇到VIA的處理,關於VIA和Record-Route處理,建議讀者閱讀筆者的歷史文檔:
SIP系列講座-關於VIA和Record-Route header
這裡需要特別注意,在關於Record-Route時,如果網絡環境在多宿主機環境或者傳輸協議需要切換或者IPv4-IPv6的環境中,這種處理方式不是一個處理Record-Route記錄的最佳辦法。大部分情況下,通過Proxy以後,IP位址的匹配是沒有什麼問題的,但是,有時Proxy需要一定的策略修改,修改時就會生成問題。
UA多網口地址處理
IPv4到IPv6轉換
TCP到UDP轉換
這樣處理的結果可能是,呼叫方看到的route set和被呼叫方看到的route set是不同的,並且還有可能帶來其他的影響。關於針對重寫Record-Route所引起的爭議問題讀者可以查閱RFC5658。針對重寫Record-Route引起的問題,RFC5658規範推薦使用Double Record-Routing來解決以上這些問題。以下示例圖例描述了在多宿主網絡和傳輸協議切換時使用Double Record-Routing的解決方案:
根據以上圖例的流程,首先,呼叫方對P1發出一個INVITE呼叫。這裡的P1帶有兩個IP位址,一個是IPv4地址和另外一個IPv6地址。
INVITE sip:joe@howell.network.com SIP/2.0
Route:
From: Joe
To: Ken
Contact:
然後,P1收到呼叫請求以後,通過修改Route-Record地址,增加另外一個IPv6的地址繼續進行路由轉發。P1然後通過IPv6地址對U2繼續進行呼叫(兩個Route-Record):
INVITE sip: joe@howell.network.com SIP/2.0
Record-Route:
Record-Route:
From: Joe
com>;tag=1234
To: Ken
Contact:
在U2客戶端的狀態消息中,最終被呼叫方看到的是這樣的結果:
Local URI = sip:ken@atlanta.network.com
Remote URI = sip:joe@howell.network.com
Remote target = sip:joe@192.0.2.1
Route Set = sip:[2001:db8::1];lr // 通過P1的 路由set
sip:192.0.2.254:5060:lr
然後,U2就知道,它可以通過路由set中的IPv6地址發送此地址一個200 OK。
SIP/2.0 200 OK
Record-Route:
Record-Route:
From: Joe
com>;tag=1234
To: Ken
com>;tag=4567
Contact:
P1收到此200 OK以後,繼續返回給U1一個200 OK:
SIP/2.0 200 OK
Record-Route:
Record-Route:
From: Joe
com>;tag=1234
To: Ken
Contact:
這時,在U1端看到的dialog狀態中的Route-Record地址是:
Local URI = sip:joe@howell.network.com
Remote URI = sip:ken@atlanta.network.com
Remote target = sip:ken@[2001:db8::33]
Route Set = sip:192.0.2.254:5060:lr
sip:[2001:db8::1];lr
通過雙Route-Record記錄以後,雙方看到的最終結果是一致的。通過double Route-Record就實現了雙方地址的統一,也不會產生地址不一致的錯誤。其他處理流程和呼叫請求的處理方式是相同的,這裡不再累述。
4、傳輸協議切換引起的Record-Route重寫
在前面的討論中,我們也簡單涉及了如果傳輸協議切換可能導致的Record-Route重寫問題。在本章節,我們重點詳解關於TCP環境和UDP環境下的Record-Route修改問題。這裡,U1使用的是TCP傳輸,U2則使用的是UDP傳輸,proxy P1作為一個協議轉換網關進行它們之間的通信轉發處理。
以上圖例中,我們可以看到,一般情況下,U1使用TCP發送到P1,然後P1經過傳輸協議轉換以後,通過UDP把U1的呼叫請求發送到U2。這裡的使用場景是一個比較簡單化的場景,在這種比較簡單化的場景中,如果沒有涉及傳輸協議其他參數的使用的話,這種場景可能可以正常工作。但是,如果有大量的類似U1的SIP終端通過P1時,並且因為不同的需求,TCP傳輸要求支持其他參數支持時,或者在U2 端的UDP需要增加參數支持時,這樣的簡單場景就不能適應傳輸協議的支持。U1通過TCP發送呼叫請求到P1的消息示例:
INVITE sip:ken@atlanta.network.com SIP/2.0
Route:
From: Joe
com>;tag=1234
To: Ken
Contact:
com;transport=tcp>
P1收到請求以後,然後通過UDP對U1發送到呼叫請求:
INVITE sip: ken@atlanta.network.
com;transport=udp SIP/2.0
Record-Route:
From: Joe
com>;tag=1234
To: Ken
Contact: < sip:joe@u1.howell.network.com;transport=tcp>
但是,在實際生產環境中,一些代理伺服器存在一些兼容性問題,或者不能支持要求的傳輸,也可能某些代理強制使用TCP來避免UDP擁塞,這就會導致傳輸協議切換時Record-Route存在無效解析問題。因此,使用double Record-Route增加一些兼容性支持仍然是解決這些問題的比較好的辦法。
Record-Route:
com;transport=udp>
Record-Route:
com;transport=sctp>. // 增加對sctp支持
另外,除了我們討論的這種簡單場景中關於傳輸協議的切換以外,很多SIP網絡環境中涉及了NAT問題。在NAT處理中,傳輸協議也需要增加相應的傳輸參數,這就要求Record-Route做相應的修改和Via修改,包括埠修改等參數設置。
5、SBC環境中關於撥號和路由SIP呼叫/ACK處理
以上介紹了關於SIP路由中經過比較重要的概念和相關補充說明。接下來我們針對具體的SIP伺服器的業務系統-SBC呼叫進行討論。根據RFC3261的規範說明,SIP伺服器端收到SIP終端的呼叫請求以後,可以根據其伺服器端定義的呼叫路由規則來針對呼叫請求進行路由處理。具體的處理規則可以是:
以上是SIP伺服器端根據其各種決定因素對呼叫請求進行路由的幾個規則。但是,在實際的業務處理過程中,特別是SIP網絡邊界控制器的呼叫處理中還有更多具體的呼叫路由策略。此部分內容和後續章節都將基於SBC的功能對SIP呼叫進行討論。再次說明,如果讀者對SBC或者會話邊界控制器不是非常了解的話,讀者可閱讀筆者歷史文檔關於SBC和業務功能的具體詳解說明,這裡不再過多強調其具體概念和場景說明:
呼叫任何電話或者SIP終端都需要首先通過撥號盤輸入電話號碼,號碼規範和位數需要遵從ITU-T E.164,最大支持15位數號碼。
在SIP呼叫請求發起以後攜帶兩個頭消息參數(To和Request-URI)來確認呼叫目的地。一種方式是通過SIP URL/SIPS URL,另外一種是通過Tel URL的方式來標識呼叫目的地號碼。
如果終端用戶通過IP網絡進行呼叫時,雙方終端至少需要兩個不同的企業通信實體系統。在各自的企業通信平臺的邊界處,企業通信系統支持了SBC來實現SIP網絡的安全控制。根據筆者前面章節的描述,在SIP呼叫路由過程中,Via和Record-Route都需要按照呼叫路由規則進行處理。
在請求路由過程中支持了strict routing(嚴格路由)和 loose routing(鬆散路由)兩種路由方式。strict routing由RFC2543定義,而loose routing 則由RFC3261定義。嚴格路由使用Request-URI作為下一跳的URL,而鬆散路由除了使用Request-URI作為目的地URL以外,代理伺服器將使用最頂部的Route header作為下一跳的目的地地址。這兩種請求路由的區別會引起路由頭的處理不同,因此,如果經過多個代理伺服器時,它們分別支持不同的路由方式,讀者排查問題時需要特別注意這些差別。
除了在請求呼叫中使用Record-Route,在不同的代理伺服器或者SBC增加路由記錄以外,這個Record-Route也會影響ACK的處理流程,同時可能影響SBC的處理:
所有ACK請求流程中都使用了Record-Route。
所有ACK請求流程中,其中一個代理伺服器沒有插入Record-Route
雙方終端直接通過SBC進行通信。U1通過業務伺服器,SBC呼叫對端SBC,業務伺服器和U2終端。
6、SBC環境中呼叫路由類型討論
當SIP呼叫INVITE進入到SBC以後,SBC可以根據不同的呼叫路由類型做不同的呼叫路由。具體的呼叫路由類型包括:
DID匹配系統內部分機或者其他終端,例如,通過Request-URI的號碼9865556003路由到系統分機 (56003)。當然,此目的地路由還可以是其他SIP 終端,SBC或者SIP trunk,甚至於TDM 接口。
基於URL或者domain或者email格式的呼叫,一般情況下,這種路由根據SIP的domain做其他基於消息的路由切換。
基於呼叫源目的地的路由。此路由模式根據呼叫發起方的地址做呼叫路由。這樣可以保證呼叫方能夠正確路由到相關的目的地分機,例如呼叫中心的一些VIP服務呼叫。
基於中繼組的呼叫路由。這種情況通常是SBC可以同時支持TDM trunk和SIP trunk時SBC設置的路由組策略。在某些特定的需求或者使用場景中,SBC可能使用TDM/PSTN作為一個備用線路或者在本地落地,因此呼叫進入到SBC以後就需要做相應的呼叫分類管理。
基於運營商的呼叫路由。這種路由更多適用於當運營商提供了某些呼叫服務,例如toll-free號碼或者運營商的其他服務號碼。SBC需要根據其運營商的號碼特性做相應的呼叫路由。RFC4694對其Tel URL號碼有完整的規範說明,如果運營商的服務遵從其規範的話,可能某些地區有一些免費的服務,SBC可通過這些免費的數據服務來查詢更多的綁定業務。
除了以上幾種比較常見的呼叫路由服務以外,不同的SBC廠家針對呼叫路由還有很多不同的處理方式,包括一些非常靈活的自定義腳本的處理方式支持大並發部署中的各種路由管理。這種方式可以滿足以上路由處理以外,同時可以根據路由腳本實現更加強大的路由策略。具體的實現方式包括動態路由,靜態路由,標識路由和第三方籤權認證路由方式。通過腳本路由的方式,可以實現針對某些特定SIP頭或者URL進行修改,可以增加黑白名單管理,可以實現負載均衡等非常常見的SBC呼入管理策略。
www.freesbc.cn SBC/SIP INVITE 腳本路由策略
7、SBC環境中的下一跳處理機制
SBC對SIP呼叫請求進行了路由處理以後,需要針對下一個hop做處理來決定下一跳的狀態和有效性。SBC可以使用以下幾個參數來決定下一跳處理:
IP位址,支持下一跳的IP位址,這裡的IP位址可以是IPv4或者IPv6地址,傳輸方式可以是TCP,UDP或者TLS。
主機名稱,支持下一跳以主機名稱的格式出現,避免如果下一跳使用IP位址,地址發送變動後出現的連接問題。SBC將會使用DNS來對主機名稱進行支持。
服務domain/伺服器組, SBC可以通過DNS SRV對IP位址,協議,埠,傳輸方式進行組合實現對下一跳的支持。因為,一些SBC不僅僅支持SIP協議,也可能同時支持H323協議,協議可以利用不同的埠組合和地址組合實現對下一跳的支持,例如以下組合方式:
除了通過各種組合形式對下一跳支持以外,SBC必須有能力檢測到下一跳的有效性狀態。SBC不斷對對端發送option消息來檢查其有效性。如果發生故障時,需要SIP重傳的話,根據定時器的設置對對端進行重傳。以下是一個通過UDP重傳的處理流程:
一般SBC可以使用兩種方式對下一跳進行整體檢測。比較典型的下一跳的檢測方式是通過SBC發送option消息,執行ping 命令。另外一種就是使用ICMP方式進行檢測。很多時候,ICMP的方式可能被過濾,因此,大部分情況下,一般建議還是使用SIP option的方式來發送檢測消息。通過SBC,準確性地對下一跳發送檢測消息來驗證其活動狀態。當然,有的伺服器為了減少數據交互,可能關閉其option檢測。
8、SBC環境中的呼叫跟蹤
除了以上關於下一跳的討論以為,在SIP網絡環境中,我們經常會需要排查一些端對端的呼叫,跟蹤各種呼叫流程。因為涉及了太多的呼叫路徑和必要的參數設置支持,並且涉及了不同的撥號規則路由規則和號碼變換等問題,筆者不能完全介紹這些手段和工具,讀者只能根據具體的環境進行排查。比較欣慰的是,一些SBC廠家的產品本身帶了一些呼叫測試的工具,因為SBC是一個B2BUA,因此,SBC測試工具可以測試外網終端,也可以測試內網IPPBX伺服器端。
通過SBC生成對外呼叫測試(freesbc)
9、總結
在以上的內容討論中,筆者首先介紹了關於SIP呼叫中所需要了解到基本概念做了一些分享,同時結合歷史文檔,幫助讀者能夠全面掌握SIP呼叫過程中的基本的流程。然後,筆者主要針對SIP呼叫路徑中不同的代理伺服器之間通信和一些頭消息的處理。最後,筆者結合目前使用比較普遍的SBC和SIP企業通信伺服器之間的處理,重點介紹了關於SBC路由時的一些影響要素和相關的問題。
需要說明的是,以為篇幅關係,以及SBC和SIP伺服器之間的業務複雜度的關係,很多功能包括路由功能,一些業務媒體伺服器也可以實現SBC所具備的一些功能,因此,筆者沒有花費太多時間做過多介紹。
參考資料:
https://www.rfc-editor.org/rfc/rfc5658
https://www.rfc-editor.org/rfc/rfc4694
www.asterisk.org.cn
www.freesbc.cn
https://docs.telcobridges.com/tbwiki/Toolpack:Tsbc_Call_Routes_Settings_3.1