3. SDP协议基础:SDP协议概述、SDP会话描述结构、SDP媒体协商过程
各位同学,今天我们聊聊SDP。全称是Session Description Protocol,会话描述协议。
说实话,这玩意儿本身不负责传输数据。它就是个“说明书”。
你想想看,两个设备要打电话,总得先告诉对方:我能支持什么编码?我用什么端口?IP地址是多少?SDP就是干这个的。
3.1 SDP协议概述
SDP最早是IETF在RFC 2327里定义的,后来更新到RFC 4566。我入行那会儿,还在用老版本的RFC,踩过不少坑。
它的核心作用就三个:
- 描述会话:告诉对方这个通话叫什么、谁发起的、什么时候有效。
- 描述媒体:音频还是视频?用什么编码?端口号多少?
- 支持协商:双方交换SDP,最终达成一致。
重点理解:SDP不是传输协议,它只是文本格式的描述。真正传输SDP的是SIP、RTSP这些协议。
我个人习惯把SDP比作“菜单”。你拿着菜单点菜,服务员(SIP)帮你传话,厨房(媒体流)按单做菜。嗯,这个比喻挺形象的。
3.2 SDP会话描述结构
SDP的结构是文本行,每行一个字段。格式很简单:<类型>=<值>。
我刚开始逆向分析IMS信令时,看到一堆a=、m=、c=,头都大了。后来发现,记住几个关键字段就够了。
下面这张图是我自己整理的SDP结构关系,你看一眼就明白了:
你看,会话级描述是全局的,媒体级描述可以覆盖会话级的设置。比如c=字段,媒体级可以单独指定IP地址。
3.3 关键字段详解
咱们挑几个最常用的字段说说。做逆向分析时,这些字段你几乎天天见。
| 字段 | 含义 | 示例 | 我的经验 |
|---|---|---|---|
| v= | 协议版本 | v=0 | 目前只有0,没见过别的 |
| o= | 会话发起者 | o=- 123456 789 IN IP4 10.0.0.1 | 用户名常用“-”,别奇怪 |
| s= | 会话名称 | s=VoIP Session | 有些设备乱填,不影响功能 |
| c= | 连接信息 | c=IN IP4 10.0.0.1 | 注意媒体级可以覆盖 |
| m= | 媒体描述 | m=audio 5004 RTP/AVP 0 8 | 端口、协议、编码格式 |
| a= | 属性行 | a=rtpmap:0 PCMU/8000 | 最灵活,也最复杂 |
小技巧:做逆向时,重点关注a=行。很多私有扩展、特殊参数都藏在这里。我曾经在某个厂商的IMS设备里,发现a=行里塞了自定义的加密参数,折腾了两天才搞清楚。
3.4 SDP媒体协商过程
媒体协商,说白了就是“讨价还价”。
主叫方说:我能支持PCMU、PCMA、G.729,你选一个。被叫方说:我用PCMU。
就这么简单。但实际场景里,要考虑的东西多得多。
标准的协商流程是这样的:
- Offer:主叫方发送SDP,列出所有支持的媒体类型、编码、参数。
- Answer:被叫方回复SDP,从Offer里选一个,也可以修改参数。
- 确认:双方确认后,开始传输媒体流。
我遇到过最头疼的情况是什么?
有一次,某个设备发的Offer里写了支持G.729,但Answer回复了PCMU。按理说没问题。结果媒体流就是不通。抓包一看,Answer里把端口号改了,但防火墙没开那个端口。嗯,这种问题排查起来特别费时间。
避坑指南:我曾经在分析一个IMS呼叫失败案例时,发现Offer和Answer的c=字段IP地址不一致。主叫在内网,被叫在外网,NAT没处理好。记住:c=字段的IP必须是对方能访问到的。
3.5 Offer/Answer模型详解
Offer/Answer模型是SDP协商的核心。RFC 3264专门讲这个。
我个人的理解是:Offer是“我能做什么”,Answer是“我要什么”。
举个实际例子:
// Offer (主叫)
v=0
o=alice 2890844526 2890844526 IN IP4 10.0.0.1
s=-
c=IN IP4 10.0.0.1
t=0 0
m=audio 49170 RTP/AVP 0 8 101
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=sendrecv
// Answer (被叫)
v=0
o=bob 2890844527 2890844527 IN IP4 10.0.0.2
s=-
c=IN IP4 10.0.0.2
t=0 0
m=audio 49172 RTP/AVP 0 101
a=rtpmap:0 PCMU/8000
a=rtpmap:101 telephone-event/8000
a=sendrecv
你看,被叫从Offer的三个编码里选了PCMU(编码0),保留了telephone-event(编码101)。端口也换成了自己的49172。
这里有个细节:编码编号必须一致。Offer里PCMU是0,Answer里也得是0。如果Answer里写a=rtpmap:0 G.729/8000,那就乱套了。
3.6 实际项目中的注意事项
做IMS逆向分析这几年,我总结了几条经验:
- 端口别搞错:m=行里的端口是RTP端口,RTCP默认是端口+1。有些设备不按规矩来,你得看a=rtcp字段。
- 编码顺序有讲究:Offer里排在前面的编码,通常是首选。被叫一般会选第一个能支持的。
- 属性行别漏了:a=fmtp里可能藏着关键参数,比如G.729的静音检测、AMR的模式设置。
- 方向属性要匹配:sendrecv、sendonly、recvonly、inactive,双方得能对上。我曾经见过一个设备发了sendonly,对方回了sendrecv,结果媒体流只有单向。
核心要点:SDP协商的本质是“匹配”。编码匹配、端口匹配、IP匹配、方向匹配。任何一个不匹配,媒体流就起不来。
好了,SDP的基础就讲到这里。下一节我们会深入分析SDP在IMS网络中的实际应用,包括如何抓包分析SDP消息、常见问题排查等。
公众号:蓝海资料掘金营,微信deep3321