SIP语音环境中十大经典问题及解决办法
在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";tag=329cfeaa6ded039da25ff8cbb8668bd2.3724.
- From: "100";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
更多推荐
所有评论(0)