sipp模拟电信运营商VoIP终端测试(SIP协议调试)
三大运营商和其他众多通信业务厂商都可能有SIP服务器,用来支持语音对讲,多媒体调度等功能,他们的平台可能不是标准的SIP协议会话。
为了应对没完没了的对接各个厂商的平台,这里再整理了一套协议脚本,毕竟全都是没有意义的无用功,标准化的SIP会话就是最好的。
感谢西安的枫林晨曦,帮忙抓包,整理了这套脚本。
1、先熟悉一下SIP的各种请求方法
INVITE,ACK,BYE,CANCEL,OPTIONS,REGISTER,PRACK,SUBSCRIBE,NOTIFY,PUBLISH,INFO,REFER,MESSAGE,UPDATE
SIP request methods
https://en.wikipedia.org/wiki/List_of_SIP_request_methods
2、调试协议,少不了要抓包分析数据,手机app抓包,最简单,最靠谱的就是在电脑上装个wifi热点,让手机连上这个热点,在电脑上抓取这个wifi网卡的数据。
有的电脑网卡能模拟wifi AP,如果不支持,就买个wifi网卡吧
Android抓包方法(三)之Win7笔记本Wifi热点+WireShark工具
https://www.cnblogs.com/findyou/p/3491065.html
3、各请求流程的协议脚本
不一定能直接用,一般都需要调整,因为每家都可能有差异,按照厂商给的协议文档,或者抓包信息来调整。
虽然抓包就什么都有了,但是我这里还是把运营商的信息屏蔽了,毕竟签了保密协议,免得被找茬。
不熟悉协议可以参考https://github.com/saghul/sipp-scenarios
1)regclient_set_c_port.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name="regclient"> <!--本脚本特为持续性测试使用,如单次使用,建议-p 与-set c_port的端口设为相同--> <!--执行命令样例:sipp -sf regclient_set_c_port.xml SIP_Proxy_IP:SIP_Proxy_Port -i 172.16.0.6 -p 5088 -inf callee.csv -set c_port 5088 -m 1--> <Global variables="c_port" /> <nop hide="true"> <action> <!--设置EXP的值为3600--> <assignstr assign_to="EXP" value="3600" /> <assignstr assign_to="DOMAIN" value="运营商域名" /> </action> </nop> <send> <![CDATA[ REGISTER sip:[$DOMAIN] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=acknnkkg.[call_number] To: <sip:[field0]@[$DOMAIN]> Call-ID: [call_id] CSeq: 1 REGISTER Contact: <sip:[field0]@[local_ip]:[$c_port];line=79169130b56d431> Max-Forwards: 70 Subject: Reg Performance Test made by wangwei user-agent: SIPp client Digest username="sip:[field0]@[$DOMAIN]", realm="[$DOMAIN]", uri="sip:[$DOMAIN]" Expires: [$EXP] Content-Length: 0 ]]> </send> <recv response="401" optional="true" auth="true" next="auth" > </recv> <recv response="403" optional="true" next="END"> </recv> <recv response="404" optional="true" next="END"> </recv> <recv response="200" next="END" timeout="5000"> </recv> <label id="auth" /> <send> <![CDATA[ REGISTER sip:[$DOMAIN] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] [last_From:] [last_To:] [last_Call-ID:] [last_CSeq:] Contact: <sip:[field0]@[local_ip]:[$c_port];line=79169130b56d431> Max-Forwards: 70 Subject: Reg Performance Test made by wangwei user-agent: SIPp client Expires: [$EXP] [field2] Content-Length: 0 ]]> </send> <recv response="200" next="END" timeout="5000"> </recv> <label id="END"/> <nop hide="true"> </nop> <!--<Reference variables="microseconds,seconds" />--> <!-- Definition of the response time repartition table (unit is ms) --> <ResponseTimeRepartition value="50, 200"/> <!-- Definition of the call length repartition table (unit is ms) --> <CallLengthRepartition value="500, 5000"/> </scenario>
2)publish.xml
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name="publish_client"> <!----> <!--执行命令样例:sipp -sf publish.xml SIP_Proxy_IP:SIP_Proxy_Port -i 172.16.0.6 -p 5088 -inf callee.csv -m 1--> <nop hide="true"> <action> <!--设置EXP的值为3600--> <assignstr assign_to="EXP" value="3600" /> <assignstr assign_to="DOMAIN" value="运营商域名" /> </action> </nop> <send> <![CDATA[ PUBLISH sip:[field0]@[$DOMAIN] SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=acknnkkg.[call_number] To: <sip:[field0]@[$DOMAIN]> Call-ID: [call_id] CSeq: 2 PUBLISH Max-Forwards: 70 User-Agent: SIPp client Expires: [$EXP] Event: poc-settings Accept-Contact: 请查找运营商文档字段 Supported: 100rel,eventlist,timer,multiple-refer Content-Type: 请查找运营商文档字段 Content-Length:[len] <?xml version="1.0" encoding="UTF-8"?> <poc-settings xmlns="请查找运营商文档字段" xsi:schemaLocation="请查找运营商文档字段"> <entity id="sip:[field0]@[$DOMAIN]"> <isb-settings> <incoming-session-barring active="false" /> </isb-settings> <am-settings> <answer-mode>automatic</answer-mode> </am-settings> <ipab-settings> <incoming-personal-alert-barring active="false" /> </ipab-settings> <sss-settings> <simultaneous-sessions-support active="true" /> </sss-settings> </entity> </poc-settings> ]]> </send> <recv response="200" next="END" timeout="5000"> </recv> <label id="END"/> <nop hide="true"> </nop> <!--<Reference variables="microseconds,seconds" />--> <!-- Definition of the response time repartition table (unit is ms) --> <ResponseTimeRepartition value="50, 200"/> <!-- Definition of the call length repartition table (unit is ms) --> <CallLengthRepartition value="500, 5000"/> </scenario>
3)poc.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name="caller_with_auth"> <nop hide="true"> <action> <!--设置EXP的值为3600--> <assignstr assign_to="POCID" value="C127375" /> <assignstr assign_to="EXP" value="120" /> <assignstr assign_to="DOMAIN" value="运营商域名" /> </action> </nop> <!--执行命令样例:sudo sipp -sf poc.xml SIP_Proxy_IP:SIP_Proxy_Port -i 172.16.0.6 -p 5088 -inf callee.csv -m 1 -d 60000 -oocsn ooc_default--> <!--发送INVITE消息,设定重传定时器为1000ms,同时启动定时器invite--> <send> <![CDATA[ INVITE sip:[$POCID]&[field1]@[$DOMAIN];session=chat SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=4140059 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat> Call-ID:[call_id] CSeq: 1 INVITE Contact: <sip:[field0]@[local_ip]:[local_port]>;请查找运营商文档字段 Allow: INVITE,ACK,CANCEL,BYE,REGISTER,PRACK,PUBLISH,REFER,SUBSCRIBE,NOTIFY,MESSAGE P-Preferred-Identity: <sip:[field0]@[$DOMAIN]> Session-Expires: [$EXP] Supported: replaces, 100rel, timer Max-Forwards: 70 User-Agent: SIPp client mode Accept-Contact: 请查找运营商文档字段 Content-Type: application/sdp Content-Length:[len] v=0 o=SIPp [pid][call_number] 8[pid][call_number]8 IN IP[local_ip_type] [local_ip] s=SIPp Normal Call Test c=IN IP[media_ip_type] [media_ip] t=0 0 m=audio [media_port] RTP/AVP 106 a=rtpmap:106 AMR/8000 a=fmtp:106 mode-set=0,1,2,3,4,5,6,7; octet-align=1 a=ptime:200 m=application 10667 UDP TBCP a=fmtp:TBCP queuing=0; tb_priority=1; poc_sess_priority=0 ]]> </send> <!--1xx响应均为可选接收消息,且接收到临时响应后,即可停止invite定时器的计时--> <!--收到4xx/5xx错误响应后,直接进入呼叫失败--> <recv response="100" optional="true"> </recv> <recv response="183" optional="true" next="normal"> </recv> <recv response="403" optional="true" next="err_ack"> </recv> <recv response="480" optional="true" next="err_ack"> </recv> <recv response="486" optional="true" next="err_ack"> </recv> <recv response="500" optional="true" next="err_ack"> </recv> <recv response="503" optional="true" next="err_ack"> </recv> <recv response="180" optional="true" next="normal"> </recv> <label id="normal"/> <!--<recv response="200"> </recv>--> <recv response="200"> </recv> <send> <![CDATA[ ACK sip:[$POCID]&[field1]@[$DOMAIN];session=chat SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] Route: <sip:[remote_ip];lr> From: <sip:[field0]@[$DOMAIN]>;tag=4140059 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat>;tag=9500414 Call-ID: [call_id] CSeq: 1 ACK Contact: <sip:[field0]@[local_ip]:[local_port]>;请查找运营商文档字段 Max-Forwards: 70 User-Agent: SIPp client mode Content-Length: 0 ]]> </send> <!--<pause hide="true" milliseconds="500"/> <send> <![CDATA[ SUBSCRIBE sip:[$POCID]&[field1]@[$DOMAIN];session=chat SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=4628763 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat> Call-ID: [call_id] CSeq: 2 SUBSCRIBE Contact: <sip:[field0]@[local_ip]:[local_port]> Max-Forwards: 70 User-Agent: SIPp client mode Expires: [$EXP] Event: conference Accept-Contact:请查找运营商文档字段 Content-Length: 0 ]]> </send> <recv response="200"> </recv>--> <pause hide="true" milliseconds="500"/> <!--使用rtp_stream循环播放PCMA音频 <nop hide="true"> <action> <exec rtp_stream="pcap/g711a.pcap,-1,0"/> </action> </nop> --> <!--使用rtp_stream循环播放PCMU音频 <nop hide="true"> <action> <exec rtp_stream="pcap/g711u.pcap,-1,0"/> </action> </nop> --> <!--使用play_pcap单次播放PCMA音频 <nop hide="true"> <action> <exec play_pcap_audio="pcap/g711a.pcap"/> </action> </nop>--> <!--使用play_pcap单次播放PCMU音频 <nop hide="true"> <action> <exec play_pcap_audio="pcap/g711u.pcap"/> </action> </nop> --> <!--使用play_pcap单次播放amr音频--> <nop hide="true"> <action> <exec play_pcap_audio="pcap/amr.pcap"/> </action> </nop> <!--媒体流传输完毕后,暂停发送BYE结束呼叫,在执行命令中增加参数-d 指定暂停时间:如-d 10000暂停10秒--> <pause /> <!--<send> <![CDATA[ SUBSCRIBE sip:[$POCID]&[field1]@[$DOMAIN] SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=4628763 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat>[peer_tag_param] Call-ID: [call_id] CSeq: 3 SUBSCRIBE Contact: <sip:[field0]@[local_ip]:[local_port]> Max-Forwards: 70 User-Agent: SIPp client mode Accept: 请查找运营商文档字段 Expires: 0 Event: conference Accept-Contact: 请查找运营商文档字段 Content-Length: 0 ]]> </send> <recv response="200"> </recv>--> <send start_rtd="bye"> <![CDATA[ BYE sip:[$POCID]&[field1]@[$DOMAIN];session=chat SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] Route: <sip:[remote_ip];lr> From: <sip:[field0]@[$DOMAIN]>;tag=4140059 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat>;tag=9500414 Call-ID: [call_id] CSeq: 4 BYE Contact: <sip:[field0]@[local_ip]:[local_port]> Max-Forwards: 70 User-Agent: SIPp client mode Content-Length: 0 ]]> </send> <recv response="200" rtd="bye" next="END"> </recv> <!--异常结束,复用err_ack流程--> <label id="err_ack"/> <send> <![CDATA[ ACK sip:[$POCID]&[field1]@[$DOMAIN];session=chat SIP/2.0 [last_Via:] From: <sip:[field0]@[$DOMAIN]>;tag=[call_number]zhg8 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat>[peer_tag_param] [last_Call-ID:] CSeq: 1 ACK Contact: <sip:[field0]@[local_ip]:[local_port]>;请查找运营商文档字段 Max-Forwards: 70 User-Agent: SIPp client mode Content-Length: 0 ]]> </send> <!--正常结束--> <label id="END"/> <nop hide="true"> </nop> <!--如果存在定义了但未被使用的变量,可以在下面语句的双引号中增加,避免运行时报错 <Reference variables="junk,callee_media_port" />--> <!--definition of the response time repartition table (unit is ms) --> <ResponseTimeRepartition value="50, 200,1000,2000,4000,10000"/> <!--definition of the call length repartition table (unit is ms) --> <CallLengthRepartition value="500, 1000, 10000"/> </scenario>
4) subscribe.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name="subscribe"> <Global variables="c_port" /> <!--执行命令样例:sipp -sf subscribe.xml SIP_Proxy_IP:SIP_Proxy_Port -i 172.16.0.6 -p 5077 -set c_port 5088 -inf callee.csv -m 1 -d 40000--> <nop hide="true"> <action> <!--设置EXP的值为3600--> <assignstr assign_to="POCID" value="C127375" /> <assignstr assign_to="EXP" value="120" /> <assignstr assign_to="DOMAIN" value="运营商域名" /> </action> </nop> <send> <![CDATA[ SUBSCRIBE sip:[$POCID]&[field1]@[$DOMAIN];session=chat SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=4629583 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat> Call-ID: [call_id] CSeq: 2 SUBSCRIBE Contact: <sip:[field0]@[local_ip]:[$c_port]> Max-Forwards: 70 User-Agent: SIPp client mode Expires: [$EXP] Event: conference Accept-Contact: 请查找运营商文档字段 Content-Length: 0 ]]> </send> <recv response="200"> </recv> <pause /> <send> <![CDATA[ SUBSCRIBE sip:[$POCID]&[field1]@[$DOMAIN] SIP/2.0 Via: SIP/2.0/UDP [local_ip]:[local_port];rport;branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=4629583 To: <sip:[$POCID]&[field1]@[$DOMAIN];session=chat>[peer_tag_param] Call-ID: [call_id] CSeq: 3 SUBSCRIBE Contact: <sip:[field0]@[local_ip]:[$c_port]> Max-Forwards: 70 User-Agent: SIPp client mode Accept: 请查找运营商文档字段 Expires: 0 Event: conference Accept-Contact: 请查找运营商文档字段 Content-Length: 0 ]]> </send> <recv response="200"> </recv> <!--正常结束--> <label id="END"/> <nop hide="true"> </nop> <!--如果存在定义了但未被使用的变量,可以在下面语句的双引号中增加,避免运行时报错 <Reference variables="junk,callee_media_port" />--> <!--definition of the response time repartition table (unit is ms) --> <ResponseTimeRepartition value="50, 200,1000,2000,4000,10000"/> <!--definition of the call length repartition table (unit is ms) --> <CallLengthRepartition value="500, 1000, 10000"/> </scenario>
5) sip里的rtcp操作, 抢占讲话权限
https://wenku.baidu.com/view/854dd3e55ef7ba0d4a733bed.html
TBCP 消息简要概述
https://blog.csdn.net/wunderup/article/details/5136441
6) deregclient_set_c_port.xml
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE scenario SYSTEM "sipp.dtd"> <scenario name="regclient"> <!--本脚本特为持续性测试使用,如单次使用,建议-p 与-set c_port的端口设为相同--> <!--执行命令样例:sipp -sf deregclient_set_c_port.xml SIP_Proxy_IP:SIP_Proxy_Port -i 172.16.0.6 -p 5088 -inf callee.csv -set c_port 5088 -m 1--> <Global variables="c_port" /> <nop hide="true"> <action> <!--设置EXP的值为3600--> <assignstr assign_to="EXP" value="0" /> <assignstr assign_to="DOMAIN" value="运营商域名" /> </action> </nop> <send> <![CDATA[ REGISTER sip:[$DOMAIN] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] From: <sip:[field0]@[$DOMAIN]>;tag=acknnkkg.[call_number] To: <sip:[field0]@[$DOMAIN]> Call-ID: [call_id] CSeq: 1 REGISTER Contact: <sip:[field0]@[local_ip]:[$c_port];line=79169130b56d431> Max-Forwards: 70 Subject: Reg Performance Test made by wangwei user-agent: SIPp client Digest username="sip:[field0]@[$DOMAIN]", realm="[$DOMAIN]", uri="sip:[$DOMAIN]" Expires: [$EXP] Content-Length: 0 ]]> </send> <recv response="401" optional="true" auth="true" next="auth" > </recv> <recv response="403" optional="true" next="END"> </recv> <recv response="404" optional="true" next="END"> </recv> <recv response="200" next="END" timeout="5000"> </recv> <label id="auth" /> <send> <![CDATA[ REGISTER sip:[$DOMAIN] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch] [last_From:] [last_To:] [last_Call-ID:] [last_CSeq:] Contact: <sip:[field0]@[local_ip]:[$c_port];line=79169130b56d431> Max-Forwards: 70 Subject: Reg Performance Test made by wangwei user-agent: SIPp client Expires: [$EXP] [field2] Content-Length: 0 ]]> </send> <recv response="200" next="END" timeout="5000"> </recv> <label id="END"/> <nop hide="true"> </nop> <!--<Reference variables="microseconds,seconds" />--> <!-- Definition of the response time repartition table (unit is ms) --> <ResponseTimeRepartition value="50, 200"/> <!-- Definition of the call length repartition table (unit is ms) --> <CallLengthRepartition value="500, 5000"/> </scenario>
4、sipp xml正则表达式获取接收的信息
<recv response="200"> <action> <ereg regexp="\r\n\r\n(.*)" search_in="msg" assign_to="sdp_info" /> <!-- <ereg regexp=".*" search_in="msg" body="" assign_to="1" /> <ereg regexp=".*" search_in="hdr" header="CSeq:" check_it="true" assign_to="2" /> <exec command="echo [$1] >> from_list.log"/>--> <exec command="echo '[$sdp_info]' >> from_list.log"/> </action> </recv>