操作系統 :CentOS 7.6_x64 freeswitch版本 :1.10.9 sofia-sip版本: sofia-sip-1.13.14 freeswitch使用sip協議進行通信,當sip消息超過mtu時,會出現拆包的情況,這裡整理下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) >> 4udp首部解析如下:
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 獲取。
