3. SIP协议基础:SIP消息结构、请求与响应、会话建立流程
好,咱们进入正题。SIP协议,说白了就是通信网络里的“信令语言”。它负责告诉网络:谁要打电话、打给谁、怎么打。我刚开始接触IMS时,觉得SIP就是个文本协议,没啥了不起。后来被信令风暴折腾过几次,才明白——越是简单的东西,出起问题来越要命。
3.1 SIP消息结构:你得看懂“信封”和“信纸”
SIP消息分两种:请求和响应。但它们的结构是一样的,都包含三部分——起始行、消息头、消息体。我习惯把起始行比作“信封”,消息头是“邮戳”,消息体才是“信纸”。
核心要点:SIP消息是文本格式,基于UTF-8编码。这意味着你可以直接用Wireshark抓包看,不用解码。但这也意味着,攻击者可以轻易伪造消息。
来看一个典型的INVITE请求:
INVITE sip:alice@example.com SIP/2.0
Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK74b43
Max-Forwards: 70
From: <sip:bob@example.com>;tag=1928301774
To: <sip:alice@example.com>
Call-ID: a84b4c76e66710@192.168.1.100
CSeq: 314159 INVITE
Contact: <sip:bob@192.168.1.100>
Content-Type: application/sdp
Content-Length: 142
v=0
o=bob 2890844526 2890844526 IN IP4 192.168.1.100
s=-
c=IN IP4 192.168.1.100
t=0 0
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
嗯,这里要注意几个关键字段:
- Via:记录消息经过的每一跳。我排查信令风暴时,第一件事就是看Via头有没有异常增长。
- Call-ID:全局唯一标识一个会话。同一个会话的所有消息,Call-ID必须一致。
- CSeq:序列号,用于保证消息顺序。攻击者经常乱改这个值,导致会话混乱。
- Content-Type:消息体类型。IMS里最常见的是SDP,描述媒体信息。
避坑指南:我曾经遇到过一个案例,某个网元老是丢消息。查了半天,发现是Content-Length字段写错了,比实际消息体长度少了几个字节。接收方一直等后续数据,结果超时了。所以,写代码时一定要严格校验Content-Length。
3.2 SIP请求与响应:六种方法和六类状态码
SIP定义了六种基本请求方法。你不需要全记住,但INVITE、ACK、BYE、CANCEL、REGISTER、OPTIONS这六个必须烂熟于心。我面试新人时,第一个问题就是“SIP有哪几种请求方法?”答不上来的,基本可以pass了。
| 方法 | 用途 | 我在项目中踩过的坑 |
|---|---|---|
| INVITE | 发起或修改会话 | 重传风暴的罪魁祸首,后面会细讲 |
| ACK | 确认最终响应 | 很多人忘了ACK只用于2xx和3xx-6xx |
| BYE | 终止会话 | 漏发BYE会导致计费异常 |
| CANCEL | 取消未完成的请求 | 和BYE的区别,很多人搞混 |
| REGISTER | 注册用户位置 | 注册风暴,运营商最头疼的问题之一 |
| OPTIONS | 查询能力 | 常被用于探测存活状态 |
响应码呢,分六类。我总结了一个口诀:1xx在努力,2xx成功了,3xx要重定向,4xx你错了,5xx我错了,6xx全局失败。
重点记忆:1xx是临时响应,不会触发ACK。2xx是最终成功响应,必须ACK。3xx-6xx也是最终响应,同样需要ACK。这个逻辑在信令风暴里特别重要——如果网络丢包导致ACK没收到,发送方会重传INVITE,形成风暴。
3.3 会话建立流程:三步握手,但比TCP复杂多了
SIP的会话建立,本质上是三次握手:INVITE → 1xx → 2xx → ACK。但实际流程里,中间会穿插很多临时响应和媒体协商。
我画了一张流程图,帮你理清逻辑:
这个流程看起来简单,但实际部署时,每个环节都可能出问题。我举个例子:
实战案例:有一次,某省运营商反馈用户呼叫成功率骤降。我抓包一看,发现大量INVITE重传。原因是代理服务器处理200 OK时,响应太慢,导致主叫超时重传INVITE。而代理收到重传的INVITE后,又创建了新的会话分支。结果一个呼叫产生了多个会话,最终全部超时。解决方案很简单——优化代理的200 OK处理逻辑,把超时时间从2秒改成5秒。
3.4 关键细节:事务与对话
搞懂SIP,必须分清两个概念:事务和对话。
- 事务:一次请求-响应的完整交换。比如INVITE + 最终响应 + ACK,就是一个事务。
- 对话:端到端的SIP关系,由Call-ID、From tag、To tag唯一标识。一个对话可以包含多个事务。
为什么这个重要?因为信令风暴往往发生在事务层面。比如,某个网元收到INVITE后,没有及时回复100 Trying,发送方就会重传INVITE。如果网络延迟大,重传次数会指数级增长,最终形成风暴。
我的经验:排查信令风暴时,我习惯先看事务层的重传率。如果重传率超过5%,基本可以断定有问题。然后看是哪个方法重传最多——如果是INVITE,大概率是响应超时;如果是BYE,可能是会话释放逻辑有bug。
3.5 媒体协商:SDP的“讨价还价”
SIP负责建立信令连接,但真正的媒体通信靠SDP。SDP描述了你支持哪些编解码、IP地址、端口号等信息。双方通过SDP协商,找到共同支持的媒体格式。
一个典型的SDP协商过程:
- 主叫在INVITE中携带SDP offer,列出支持的编解码(比如PCMU、PCMA、G.729)
- 被叫在200 OK中返回SDP answer,选择其中一个编解码(比如PCMU)
- 双方开始RTP通信
这里有个坑:如果主叫的SDP offer里包含多个编解码,但被叫一个都不支持,就会返回488 Not Acceptable Here。我见过一个案例,某个终端只支持AMR编解码,但网络侧只支持PCMU,结果呼叫一直失败。最后在SBC上做了编解码转换才解决。
安全提醒:SDP中的IP地址和端口是明文传输的。攻击者可以截获这些信息,直接向媒体端口发起RTP flood攻击。所以,IMS网络里一定要用IPSec或TLS加密SIP信令。
好了,SIP协议基础就讲到这里。记住:消息结构是骨架,请求响应是动作,会话建立是流程。这三者构成了IMS信令的基石。后面讲信令风暴时,你会反复用到这些知识。