在VOIP的環境中,特別是基於SIP通信的環境中,我們經常會遇到一些非常常見的問題,例如,單通,30秒就斷線,注冊問題,回聲等。這些問題事實上都有非常直接的排查方式和解決辦法,用戶可以按照一定的排查方式,工具非常高效地解決這些問題。但是,因為讀者技術水平參差不齊,網絡上的很多技術也不完整。筆者今天系統歸納了這些問題。根據一些用戶的使用環境和用戶經常遇到一些問題,我們列舉了以下十個在SIP呼叫中經常遇到的問題,並且給出了相應的排查方式,用戶可以按照這些方法來解決SIP通話中的這些問題。這十個經典的問題包括:
- 不能注冊或呼叫到SIP服務器端
- 30秒掛斷呼叫的黃金法則
- 咬線或摘機狀態
- 單通或無語音
- 收到400 bad request
- 收到413,513 Request Entity Too Large或Message Too Large消息
- 收到408, 480或者487 消息
- 483 - Too Many Hops
- 488 – Not Acceptable Here
- 語音質量和思科語音文件示例分享
這里,讀者一定要注意,我們這里僅討論關於SIP環境中的常見問題,可能涉及網絡環境或者硬件終端的問題,因為很多廠家和SIP服務器的配置不同,可能存在一定的差異,所以用戶在我們的方法中特別需要根據廠家的不同,增加一些專門針對每個廠家或者SIP服務器的排查方式。我們僅討論一般情況下的排查方式。
1、在一般的SIP 環境中,通常來說,SIP 終端需要注冊到SIP服務器端來實現認證,服務器端獲得SIP終端的位置,然后才能進行正常的呼叫流程。注冊問題可能有以下幾種呈現方式:
- 不能注冊,完全沒有和SIP服務器連接。如果終端發送注冊消息給服務器端時,雙方完全可能完全沒有實現通訊。用戶需要在服務器端通過日志排查方式,檢查SIP終端是否有注冊消息進入到服務器端,或者SIP終端通過網絡工具對服務器端進行排查,例如使用Ping 命令。如果連Ping命令都檢測不到服務器地址,基本上可以斷定SIP終端根本沒有和服務器端連接。關於服務器端排查方式很多,最典型的就是使用的Asterisk,FreeSWITCH,OpenSIPS或者Kamailio等開源的軟交換平台。每個平台都有各自的排查命令,用戶可以參考官方手冊來判斷。當然,用戶也可以使用linux排查工具對5060端口抓包排查(例如,sngrep)。本人非常推薦這個工具,非常好用,可以實時檢查SIP消息。



- SIP終端發出了注冊消息,但是SIP服務器端沒有返回的消息。如果SIP終端對SIP服務器端發送了注冊消息,但是服務器端沒有返回響應消息,則可能是服務器端的問題。用戶需要排查服務器端為什么沒有返回消息,或者在返回路徑上的節點是否出現了問題。
- 客戶端收到錯誤消息,收到太多401/407 Unauthorized。SIP終端在注冊時,如果用戶的安全設置出現了錯誤,可能導致服務器端發送多個 401 錯誤。服務器端第一次發送到是正常的401驗證信息,如果連續多次發送401/407 錯誤的話,可能是SIP終端輸入了錯誤的用戶賬號信息,SIP終端側需要配合服務器端進行排查,也可能服務器端的SIP賬號消息保存錯誤,或者沒有重新加載服務器相應模塊,用戶最好通過服務器端的CLI命令來檢查內存中的SIP終端的真實數據信息。

- 客戶端收到403 Forbidden 消息。如果用戶帳戶信息沒有問題的話,SIP終端可能沒有輸入正確的From domain或者R-URI。有時,服務器端禁止同時注冊幾個SIP終端賬號,或者注冊過於頻繁,服務器端可能過濾了此地址。需要用戶配合服務器端地址進行進一步檢查。這里,筆者僅討論注冊階段出現的403 問題,當然也可能是系統防火牆或者其他的配置禁止了注冊消息。如果是呼叫時出現403的話,則可能是另外的原因,例如可能欠費,可能呼叫了服務器端禁止的號碼碼位等其他因素。

2、我們經常會遇到客戶抱怨這樣的問題,電話通話時,在大概30秒左右就斷線。這樣的問題最主要的原因是SIP終端沒有收到ACK消息。SIP終端發送了 200 OK以后就開始了媒體的創建,RTP語音流開始啟動,事實上,SIP終端可能還沒有收到ACK消息,因此在30秒左右,沒有收到消息的一方就發送了一個BYE消息。那么,為什么我們沒有收到ACK消息呢?

具體的場景如下兩種示例,返回時因為NAT問題導致ACK沒有辦法返回到相應的終端:


在很多應用場景中,用戶可能遇到更為復雜的NAT環境,如果其中一個代理出現了NAT處理無效的結果,就可能導致整個SIP信令路徑出現ACK丟失的問題。

一般情況下,缺少ACK消息的原因主要來自於以下幾個方面:
- Contact header 錯誤
- 客戶端沒有支持router header
- 網關在NAT后
- Contact header 的地址在NAT后
以上幾種情況都需要用戶排查網絡環境和NAT設置。因為NAT問題,ACK返回的路徑地址發生了改變,所以SIP終端沒有收到ACK消息。
一些廠家的設備或者媒體服務器也有類似的設置,例如Lync 服務器,它支持了RTCP 呼叫活動檢測功能,如果超過30秒的檢測周期沒有收到RTCP數據包,則會掛機。在開源Asterisk平台上,RTP的默認設置時間為30秒,一些SIP運營商可能會忽略UPDTAE消息,在SIP的設置中可以對其進行設置調整disallowed_methods=UPDATE 或SIP的會話定時器設置。
3、SIP終端不能掛機或者處於摘機狀態是第三個經常遇到的問題。在SIP終端中的表現形式為終端沒有發送BYE消息或者發送了錯誤的BYE消息內容。

沒有發送BYE的狀態:

其原因主要表現在:
- 沒有發送BYE消息
- 發送到BYE消息攜帶了錯誤的to-tag
- 發送了格式不規范的BYE消息,例如格式錯誤,sequences錯誤或者時間戳錯誤。
- 發送的BYE消息中攜帶的是錯誤的路由信息
對於出現的這些問題,用戶需要根據SIP消息來進行排查,對比哪些路徑節點出現了問題。當然,這些問題帶來的結果大家可能都非常清楚。首先,計費的准確性出現了問題,用戶的計費不能完整准確地監控。另外,如果媒體服務器對呼叫有限制的話,因為其中一個SIP終端沒有真正掛機,其他用戶可能不能呼出的問題。如果是一台模擬網關的話,可能出現FXO或者FXS不能正常工作的問題。
出現以上這些問題,讀者還是要從終端的配置來解決問題,是否出現了終端的配置問題,終端的質量問題。如果是FXO或者FXS的話,是否出現了制式不匹配的問題導致咬線或者摘機的問題。
從服務器端處理的話,可以通過兩種辦法來通過服務器端對其進行強制掛機處理。這四種服務器端的檢測方式是:
- 開啟RTP超時檢測來檢測終端的RTP流是否仍然活動
- 開啟SIP的KeepAlive 檢測SIP 會話狀態
- 使用Proxy中的dialog中的OPTION來檢測SIP終端響應狀態,SIP終端發送 200 OK到proxy來檢測終端的狀態。
- 使用SIP session timer 定時器來進行周期檢測,SIP終端一直在周期內刷新自己的狀態。如果SIP終端來定時器的時間范圍內,則表示終端參與活動狀態;否則,則對其發送BYE消息,強行掛機。

關於session timer的規范,大家可以參考rfc4028,具體的定義方式如下:

完整的SIP sesison timer 流程圖如下:

但是,因為很多SIP網絡環境中介入了SBC或者其他的網絡設備,很多情況下,有時定時器時間設置過短,SBC作為UAC或者UAS,或者proxy不刷新都可能出現上述問題。所以,會話的定時器的管理需要特別小心。
4、在SIP 語音呼叫中,一些用戶也經常遇到單通的問題,簡單來說,就是雙方呼叫時,只能聽到一方的語音。單通問題的主要原因來自於以下幾個方面:
- INVITE和200 OK中的SDP的地址不通。用戶可以通過sngrep工具來檢查SDP的地址是否可以ping 通。如果INVITE中的地址不能和200 OK中的SDP地址不能連通的話,可能導致單通的問題,有時也存在NAT問題,需要用戶針對性地進行排查。

- 網絡防火牆過濾了UDP端口。如果以上兩個地址相通的話,也有可能是網絡的防火牆過濾了RTP端口。用戶必須開啟路由器的端口轉發策略,媒體服務器的端口范圍不同,可能rtp的端口設置不同。一般的例如Asterisk或者FreeSWITCH都是10000-20000的端口范圍,也有一些服務器端口從其他的數值開始計算。
- ALG 網關設置問題。ALG網關有時可以解決NAT問題,但是也同樣會帶來其他的問題。ALG可以設置其他的SIP 服務器端口。有時用戶可以關閉路由器上的ALG選項解決單通問題。
5、有時,SIP終端可能收到400 Bad Request的消息。通常情況下,這是因為消息體中攜帶了非法的參數或者SIP服務器或者代理不能正確解析消息體格式,有可能在消息體中攜帶了重復的參數設置或者其他非法字符。在以下的示例中,出現了兩個重復的mkp參數設置,顯然,SIP proxy 不可能解析這個格式。另外,在最后一個header中,因為解析失敗的原因,可能丟失了To以后的最后Contact 頭域值。

還有很多其他的配置也可能導致400 Bad Request,例如Content-Length長度的問題,NAT地址的無效的host問題等問題。讀者一定要特別注意,對於Content-Length或者其他的語法格式的規范。具體的規范用戶可以參考rfc4475。在rfc4475中有如下定義:
- When sent over UDP (as this message ostensibly was), the receiving
- element should respond with a 400 Bad Request error.
- 用戶在SIP的消息體中,可以看到關於Content-Length的數值,然后通過實際計算,獲得真正的Content-Length數值。以下的示例說明了一個簡單的400 Bad Request。這里,因為Content-Length數值不符導致的400 Bad Request錯誤。

- 用戶可以使用計算工具來計算實際的Content-Length的值,然后根據SIP中的Content-Length判斷是否是相等,在以上圖例中,Content-Length是10000,實際數值為145。通常情況下,用戶如果懷疑Content-Length的問題,系統出現了400 Bad Request就是因為兩個值不相等導致。
6、"513 Message Too Large" 是用戶經常遇到的一個問題,通常情況下,顯示的消息是413 - Entity too large 或513 Message too big等類似的錯誤。錯誤示例如下:
- U 192.168.1.109:5060 -> 192.168.1.1:5060
- SIP/2.0 513 Message too big.Via: SIP/2.0/UDP 192.168.1.109;received=192.168.1.1;branch=
- z9hG4bKcf61.2d407ae2.0.
- Via: SIP/2.0/UDP 192.168.1.109;received=192.168.1.1;branch=
- z9hG4bKcf61.1d407ae2.0.
- Via: SIP/2.0/UDP 192.168.1.109;received=192.168.1.1;branch=
- z9hG4bKcf61.0d407ae2.0.
- Via: SIP/2.0/UDP 192.168.1.109;received=192.168.1.1;branch=
- z9hG4bKcf61.fc407ae2.0.
- Via: SIP/2.0/UDP 192.168.15.100:29296;received=67.186.60.123
- ;branch=z9hG4bK-d87543-ce4dd823475b2c25-1--d87543-;rport=29296.
- To: "100"<sip:[email>;tag=329cfeaa6ded039da25ff8cbb8668bd2.3724.
- From: "100"<sip:[email>;tag=6c4a5976.
- Call-ID: Y2NhNzExOWI4ODViYjc2NjJlMTUxOGYwNTUxMTYxNDk
導致 413 或者513 錯誤主要來自於以下幾個方面的因素:
- UDP包的限制是1500 bytes
- Proxy路由路徑中添加了太多的VIA header
- 路由路徑中添加Record-Route headers
- 終端配置了太多的編碼選項支持
針對以上這些因素和具體的原因,用戶可以根據以下幾個方面的策略來排查問題:
- 盡量減少太多的proxy路由,大家知道,每經過一個proxy路由就會增加相應的頭值,最后可能出現數據包太大的問題,UDP拒絕通過。
- 盡量減少終端的編碼選項支持,我們建議用戶使用1-3種常用的編碼即可。
- 排查一些SIP 服務器可能增加額外的自有的頭包。一些商業的解決方案可能有自有的非標准的頭包,如果沒有必要的話,可以關閉這些選項設置。
- 使用拓撲隱藏方式或者B2BUA減少路由的其他開銷。這種方式僅產生新的請求,不會增加Via header頭域值和record header。
- 盡量不要使用BLF, 因為BLF會不斷發送新的消息,數據包會增加。
7、一些用戶可能會遇到408, 480 或者487的消息。通常情況下,這三個錯誤消息和SIP的定時器相關,可能服務器端或者用戶端的定時器設置相關。很多SIP服務器在收到臨時響應消息前,有一個5秒鍾的時間限定。如果超時的話,就會返回408 消息。實際上,SIP 服務器端和SIP 用戶端都有各自的呼叫等待超時設置。在實際的環境中,用戶出現錯誤碼時,問題可能來自於SIP終端設置或者SIP服務器端的超時設置。
在一個呼叫創建以后,SIP終端開始振鈴,如果SIP服務器端的超時設置首先被觸發,服務器端就會返回一個408 timeout 消息。如果是SIP終端的超時設置被首先觸發的話,客戶端會發送一個480 消息。每次觸發超時以后,對端都會發送一個Cancel, 這里的Cancel 和INVITE是兩個分別不同的事務, 他們執行各自的流程。如果SIP 用戶端在一定的超時設置時間內沒有人接聽呼叫,就會返回一個487 消息。讀者可以參考以下示例來進一步了解487(cause 487 request terminated)的使用場景。這里的OK響應的是Cancel。487響應的是INVITE。

有時也可能是SIP終端本地設置的問題,設置錯誤,也可能導致408 超時錯誤。如果SIP終端收到了408 超時消息,這表示SIP終端嘗試連接的SIP服務器沒有任何回復消息。SIP終端需要檢查本地的網絡設置(STUN或者TURN)或者NAT設置。
8、“483 too many hops”也是SIP 新用戶經常遇到的問題。一般情況下,如果用戶配置了服務器,錯誤配置domain或不清楚domain。有時,如果運營商的MAX-Forwards支持的設置比較小的時候(默認是70),SIP終端也會出現這個錯誤。服務器端會返回原來的地址,這樣就會導致一個SIP 地址形成一個自己的回環網絡。大家知道,在SIP header中的MAX-Forwards 每經過一個跳,這個數值就會遞減1,最后,Max-Forwards 減少到0。因此,服務器端響應一個483消息。
一些SIP 解決方案的廠家也支持了Loop Detection 功能,它可以支持detect 模式,超時設置和閥值,如果用戶遇到類似的設備的話,可以開啟這些參數做進一步的優化措施。
9、除了以上這些問題以外,還有一些問題是用戶根本沒有意識到的,這些問題也相對比較專業,因此,用戶很難找一下子到真正的解決方案。這些問題中,“488 Not Acceptable here" 就是一個比較特殊的問題。用戶不清楚如何解決這些問題。 因為這個問題可能涉及到了SIP服務器端的配置。一般情況下,如果SIP 終端出現這個問題的話,都是因為編碼不支持導致的。如果不同的SIP終端使用了不同的語音編碼的話,需要SIP媒體服務器進行編碼協商,如果雙方的編碼統一了,才能進行正常的呼叫。很多情況下,用戶設置的編碼有很大差異,如果媒體服務器編碼協商失敗的話,就會返回488的錯誤。
關於服務器端編碼支持能力,用戶可以和維護人員聯系,檢查是否支持SIP終端設置的編碼,如果不支持的話,需要關閉編碼選項。很多情況下,特別是用戶使用Asterisk或FreeSWITCH,為了節省網絡帶寬的開銷,很多SIP trunk 或者IMS使用了G.729。但是,很多Asterisk和FreeSWITCH 如果沒有默認配置G.729的模塊的話, 或者沒有編碼轉換的能力,那么服務器端結合出現編碼協商失敗的問題,最后返回488 響應消息。關於Asterisk或者FreeSWITCH 如何支持G.729 編碼的問題,讀者可以參考筆者微信號的歷史文檔。這里不再做過多討論。
有時,在以前的FreeSWITCH平台上,488 協商問題也可能出現在一些傳真的檢測功能上。如果傳真協商出現問題,也可能導致488 響應的錯誤消息。
10、經常聽到客戶的投訴說語音質量不好。在VOIP環境中,很多因素影響語音質量。筆者在前面的討論中討論了關於MOS的評測等技術手段。這里不再累述。
除了以上鏈接中提到的三種問題以外,我們這里簡單說明一下語音回聲的三個黃金法則:
- 回聲總是在聽到回聲的對端產生
- 回聲的問題大部分是有PSTN的接入設備導致,所以盡量使用帶回聲的處理接入設備,杜絕回聲的產生
- 如果遇到回聲,不使用帶揚聲器的終端測試,使用耳麥軟電話測試。
- 一般來說,回聲是從終端或者接入設備傳入,因此必須從接入或者終端方解決回聲問題。
- 很多客戶也不清楚語音問題的真實的感受,用戶可以聽筆者的語音文件示例,感受各種語音問題。筆者提供了一個講話人自己的回聲示例:
當然,語音質量的問題僅是一個比較寬泛的說法,其概念本身不具有規范和專業性。思科技術網站對各種語音問題的原因做了大量的研究,也提供了對各種語音問題的排查方式和產生原因。讀者可以參考思科的技術文檔。



根據思科對語音問題的定義,思科定義為:噪音和語音失真。噪音類別包括以下幾個類別:
- Absolute Silence
- Clicking
- Crackling
- Crosstalk
- Hissing
- Hum
- Popping
- Motor Sound
- Screeching
- Static
以上這些類別有不同的文件示例,因為微信不能插入多個語音文件,用戶可以到思科網站查詢。語音失真又進一步定義了多種語音失真的子類別,他們分別為:
- 回聲語音
- 混亂語音
- 音量失真
11、在本章節的討論中,筆者重點對SIP 呼叫中存在的十大常見的經典問題做了比較詳細的介紹,同時針對每個SIP 響應錯誤的原因也做了深入的分析。每個SIP消息的生成都和終端的配置,服務器的支持能力,網絡環境有着非常緊密的聯系。用戶需要借助排查工具,然后根據筆者的建議來進行排查。當然,筆者的建議僅是一個思路而已,具體的問題可能和其他的因素相關。所以,讀者一定要根據技術文檔結合實際情況來排查問題。
在最后的章節中,筆者特別建議用戶查看思科的語音示例文件和其解決辦法,這是比較權威的語音排查方式,也相對應該說VOIP領域最完整的語音示例,強烈建議讀者參考學習。
另外,筆者這里列出的問題也不能非常完整歸納所有的SIP方面的問題,也不能完全保證解決所有所列出的問題,需要讀者根據實際呼叫來動手解決。這里,筆者的目的僅是一個學習分享。有錯誤之處,望諒解!
參考資料:
https://github.com/irontec/sngrep/wiki
http://www1.coe.neu.edu/~eeichen/spring_2015/class_notes/b_jan_20/RTP_new.pdf
http://www.helpmedial.com/docs/Advanced-Router-SIP-ALG-Troubleshooting.pdf
https://blog.opensips.org/2017/02/22/troubleshooting-missing-ack-in-sip/
https://tools.ietf.org/html/rfc4028
https://tools.ietf.org/html/rfc4475#section-3.1.2.2
http://www.charactercountonline.com/
https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/rsip_reftimesumm.html
https://www.cisco.com/c/en/us/support/docs/voice/voice-quality/30141-symptoms.html