sip消息拆包原理及组包流程
操作系统 :CentOS 7.6_x64
freeswitch版本 :1.10.9
sofia-sip版本: sofia-sip-1.13.14
freeswitch使用sip协议进行通信,当sip消息超过mtu时,会出现拆包的情况,这里整理下sip消息拆包原理及组包流程。
一、拆包的原理
简单来说:拆包的原因是,sip消息过长,超过mtu值。
具体原理可以参考《TCP/IP详解 卷2:实现》第10章 : IP的分片与重装
这里贴下拆包的示意图:
二、生成sip拆包的pcap文件
1、让sip消息超过mtu值
这里列举两种方法让sip消息超过mtu值,具体如下:
1) 添加sip消息内容,超出默认mtu值
该方法和真实场景比较贴合,建议使用,可以通过在orginate时添加自定义sip头实现,具体操作步骤获取途径:
关注微信公众号(聊聊博文,文末可扫码)后回复 20230402 获取。
2)设置网卡的mtu为比较小的值
一般网卡默认的mut值是 1500 ,可以通过以下命令修改:
ifconfig enp0s3 mtu 500up
其中,500是新的mtu值,具体效果如下:
2、抓包获取pcap文件
为了方便起见,这里以修改mtu值的方式演示下。
这里使用tcpdump进行抓包,具体如下:
tcpdump -i enp0s3 udp -w sipTest1-mtu.pcap
具体效果如下:
上图的INVITE消息已经拆包了。
组包时,需要看ip头里面的 More fragments 标识,拆包的数据Identification字段一致,在本示例里面是 22448 这个值。
三、sip消息组包
由于拆包是IP层的行为,sip消息大多基于udp实现,拆包的数据包里面可能没有端口信息(端口数据在udp里面定义的),解析之前需要先进行组包,这里以python为例进行演示。
python版本:python 3.9
libpcap版本:1.11.0b7
python3如何使用libpcap的具体讲解,可从如下途径获取:
关注微信公众号(聊聊博文,文末可扫码)后回复 2022102901 获取。
1、基于udp实现的sip协议数据报文结构
完整的sip消息的IP数据报有IP首部、UDP首部、UDP数据组成,具体如下:
其中IP首部为20字节,结构如下:
UDP首部为8字节,结构如下:
2、解析IP首部及UDP首部
ip首部解析如下:
ipHdr = struct.unpack('!BBHHHBBH4s4s',bytes(p[14:34])) ver = (ipHdr[0] & 0xF0) >> 4
udp首部解析如下:
udpHdr = struct.unpack('!HHHH',bytes(p[34:42])) srcPort,dstPort = udpHdr[0],udpHdr[1]
3、拼接SIP消息
解析过程大概分为以下几个步骤:
1)解析ip头及udp头;
2)判断ip头是否有moreFrag标识,如果有,则进行特殊标记处理;
3)根据数据包标识拼接sip消息,然后解析;
运行效果如下:
拼接效果如下:
示例代码如下:
四、资源获取
本文涉及文件和完整python示例代码从如下途径获取:
关注微信公众号(聊聊博文,文末可扫码)后回复 20230408 获取。