简介:七号信令(SS7)是电信网呼叫建立、路由与计费的核心协议栈,这份资料面向通信工程师、协议开发人员及高校相关专业学生,帮助系统理解MTP三层结构、SCCP面向连接服务、TCAP事务处理机制以及信令点(SP)与转接点(STP)组成的网络架构。压缩包共收录607个文件,以465张jpg示意图和138个htm文档为主,另有少量html与txt说明,整体仅3.43MB;图片适合快速查看信令流程与消息格式,htm网页文档便于按章节离线学习与检索。内容除了协议分层、信令数据单元与路由方式,还涉及SS7与IP网融合、智能网应用及安全防护等实践议题,并配有实例分析,能够帮助读者从原理到应用建立完整认知。目前已有373人学习,对于从事通信网络运维、协议研发或相关课题研究的读者,是低成本入门与进阶的好材料,尤其适合通信课程设计、资格认证或技术调研场景。
1. 一张异常话单背后:为什么还要懂SS7七号信令
一张话单对不上账,通常先怀疑计费系统,再怀疑中继,最后才想到信令。可实际排查里,七号信令(SS7)往往是那个藏在黑匣子里的变量:IAM 消息没到对端,批价就无从谈起;SCCP 的全局标题翻译错了,短信中心就收不到下一跳。SS7.rar 这类名字的压缩包,经常就是信令工程师从局方环境导出的解析工具、离线 pcap 和说明文档的合集。下面用五章把它拆开:先立分层认知,再跑通最小解析链路,然后讲几个高频坑,最后给出两个能验证“我没解析错”的办法。适合做协议开发、话单核对和信令链路运维的从业者,也适合刚接手 SS7 测试系统的新人。
2. 看懂SS7协议栈:MTP、SCCP、TCAP的分层逻辑与必调参数
2.1 分层结构:把SS7消息当快递包裹看
只要是第一次接触 SS7 的人,都会先被 MTP1、MTP2、MTP3、SCCP、TCAP 这一串缩写吓住。把它当快递包裹看就顺了:MTP1 是运输车辆,负责把物理信号送到相邻节点;MTP2 是装卸工,解决一条链路上的差错重传和定位;MTP3 是分拨中心,看目的信令点编码把包裹往哪个方向送;SCCP 是填写收件人手机号,负责从信令点找到具体业务子系统;TCAP 是快递员,承载一次完整的业务操作会话,比如位置更新、短消息、智能网触发。
解析一条 SS7 消息时,我更关心每一层暴露出来的“可读字段”:
| 协议层 | 职责 | 解析时重点看的字段 |
|---|---|---|
| MTP2 | 链路级可靠传输 | BSN、FSN、LI、CRC |
| MTP3 | 信令网路由 | SIO、DPC、OPC、SLS |
| SCCP | 端到端寻址 | Called/Calling Party Address、GT、SSN |
| TCAP | 业务操作会话 | Transaction ID、Opcode、Dialogue ID |
很多新手喜欢直接翻到 ISUP 层看 CIC,或者翻到 TCAP 层看操作码,这没有错,但路由出了问题你会傻眼:MTP3 的 DPC 指错了局,ISUP 层看到的就全是“对端不存在”;SCCP 的 GT 翻译配错,TCAP 层干脆一条消息都看不到。所以做信令解析的第一步,不是急着读业务字段,而是先把层与层之间的“路由索引”对清楚。
MTP2 的长度指示 LI 也是经常被误解的字段。它在 MSU 里表示后面 SIF 的 16 位字数,不是字节数。解析时如果不乘 2,后面所有字段都会偏移,这个在第 4 章还会专门展开。MTP3 的 SIO 字节里有业务指示语,0x03 通常是 SCCP,0x05 通常是 ISUP,看到这个值你就能判断这条 MSU 里装的是什么业务。
2.2 寻址与路由参数:DPC、OPC、SLS、CIC谁决定一条消息
MTP3 的路由标签是 SS7 网络里的“门牌号”。DPC 是目的信令点编码,OPC 是源信令点编码,SLS 是链路选择码,用来在多条链路之间做负荷分担。ISUP 里还有一个 CIC,是电路识别码,用来关联一条具体的话路。它们的分工差异很大,翻车的方式也完全不同:
| 参数 | 含义 | 常见误用 |
|---|---|---|
| DPC | 目的信令点编码 | 不区分 14/24 位格式,导致值对不上 |
| OPC | 源信令点编码 | 把 OPC/DPC 填反,路由链路直接不通 |
| SLS | 链路选择码 | 以为是随机数,其实同一业务常常固定 |
| CIC | 电路识别码 | 同一个中继群内重复,话路串线 |
拿到一个 pcap 的第一件事,我会先用 tshark 确认 MTP3 层是不是真的被解析出来了:
tshark -r ss7_workspace/trace.pcap -Y "mtp3" -T fields \ -e mtp3.dpc -e mtp3.opc -e mtp3.sls \ -E header=y -E separator=, | head -20这个命令的关键在-Y "mtp3":只有 Wireshark 把报文识别成 MTP3 之后,mtp3.dpc、mtp3.opc这些字段才有值。如果输出只有表头没有数据,说明抓包点不在 MTP3 层,或者报文被当成了别的协议——最常见的是 Sigtran 环境里被识别成 SCTP/M3UA,需要用-d参数强制解码,这个坑在第 4 章详细讲。
-E header=y会输出首行字段名,-E separator=,把分隔符设成逗号,方便直接贴进表格工具。用head -20限制行数,先看前 20 条消息的分布,别一上来就全量导。
信令点编码还有一个隐蔽问题:ITU-T 标准是 14 位点编码,ANSI 和中国国内规范多用 24 位点编码。14 位和 24 位的位段排布不同,同一个十六进制字节,按 14 位拆和按 24 位拆出来的 DPC/OPC 完全不是一回事。很多解析工具默认 ITU-T,拿国内 24 位的抓包去喂就会得到一堆莫名其妙的数字。
提示:开始解析前,先确认这份 pcap 来自哪种点编码格式,再决定后续所有字段解析的宽度。这一步错了,后面全是白干。
SLS 在一个呼叫里通常是固定的,但在负荷分担场景下,同一条话路的 ISUP 消息可能经由不同链路到达,抓包顺序不代表发送顺序。做性能分析时,我会同时抓两条链路的 pcap,再按 CIC 和事务 ID 合并排序,而不是只看单一链路的顺序。
3. 从压缩包到可读报文:解析七号信令的最小工具链与脚本
3.1 解开SS7.rar:先看包内文件清单,别急着双击
这类工程压缩包不管叫什么名字,第一步永远是先看里面有什么。有的包里是 Wireshark 插件,有的是 Python 脚本,有的是抓包说明文档和 pcap 样例。用 7-Zip 列出内容是很常见的做法,7-Zip 照常能解开 rar 格式,不一定非得装专门的 rar 解压软件:
7z l SS7.rar 7z x SS7.rar -o./ss7_workspace7z l只列清单不释放文件,适合先确认包内目录结构;7z x会保留压缩包内的目录层级。注意-o后面不要加空格,直接跟目标路径,这个参数一旦写成-o ./workspace就会路径不生效,算是个老坑。解压之后先找说明文档,重点看两件事:抓包点的信令点编码格式是 14 位还是 24 位;抓包环境是 TDM E1 还是 Sigtran over IP。这两项直接决定后面所有解析脚本怎么写。
常见压缩包里一般会有三类文件:抓包/回放脚本、字段说明文档、离线 pcap 样例。说明文档比代码更值得先读,因为它写的是现场配置。代码插件只是工具,配置错了工具也会给你错误答案。
3.2 用tshark把原始帧变成字段表
离线 pcap 最方便的输出方式是用 tshark 直接抽字段。相比打开图形界面一条消息点过去,命令行方式适合批量核对:
tshark -r ss7_workspace/trace.pcap \ -Y "mtp3 || sccp || tcap" \ -T fields \ -e frame.number \ -e mtp3.opc -e mtp3.dpc -e mtp3.sls \ -e sccp.called_party -e tcap.opcode \ -E header=y -E separator=, \ -2参数的作用分别是:-r指定 pcap;-Y做显示过滤,mtp3 || sccp || tcap表示只要这三层有任意一层就会被保留;-T fields进入字段输出模式;-e指定要打印的字段;-2表示做两遍解析,Wireshark 的 SS7 dissector 经常需要依赖后续层才能反推前面的协议边界,不加-2会有一批消息显示为 malformed。
如果tcap.opcode一列为空,说明该条消息不是 TCAP 承载的业务,也可能是 SCCP 层没被正确识别。前者是正常的,比如 ISUP 消息本来就不走 TCAP;后者需要检查 SCCP 是否被错误解码成了其他协议。
要快速看一个呼叫的基本流程是否完整,我会用另一种统计方式:
tshark -r trace.pcap -Y "isup" -T fields -e isup.message_type \ | sort | uniq -c | sort -rn输出会统计 IAM、ACM、ANM、REL、RLC 各出现多少次。一个正常结束的呼叫,IAM 和 RLC 的数量应该接近;如果 RLC 明显少于 REL,说明很多释放消息没有收到释放完成确认,这就是一条值得往下查的线索。注意这只是数量级判断,不是绝对结论,真实网络里还有互放、久叫不应等分支。
3.3 自己用Python解析一条IAM:手写解析器的最小实现
tshark 能告诉你怎么看,但如果你要做自动核对或接进自己的平台,还是需要一段可控的解析代码。下面这段代码处理从 SIO 开始的 MSU 正文,假设它是 ITU-T 14 位点编码的路由标签布局:
import struct ISUP_MSG = {1: "IAM", 6: "ACM", 7: "ANM", 12: "REL", 16: "RLC"} def parse_mtp3_label(sio_and_label: bytes): # sio_and_label 长度至少 5:1 字节 SIO + 4 字节路由标签 # 14 位点编码的路由标签是 32 位:DPC 高 14 位,OPC 中间 14 位,SLS 低 4 位 label = struct.unpack(">I", sio_and_label[1:5])[0] dpc = (label >> 18) & 0x3FFF opc = (label >> 4) & 0x3FFF sls = label & 0x0F return dpc, opc, sls def parse_isup(sio_and_label_and_isup: bytes): dpc, opc, sls = parse_mtp3_label(sio_and_label_and_isup) isup = sio_and_label_and_isup[5:] cic = struct.unpack(">H", isup[:2])[0] mtype = isup[2] return dpc, opc, sls, cic, ISUP_MSG.get(mtype, hex(mtype)) # 用你 pcap 里复制的 MSU 十六进制替换这一行 raw_msg = bytes.fromhex("01 05 12 34 56 78 00 01 06".replace(" ", "")) dpc, opc, sls, cic, type_name = parse_isup(raw_msg) print(f"OPC={opc} DPC={dpc} SLS={sls} CIC={cic} TYPE={type_name}")这段代码先读 MTP3 路由标签:struct.unpack(">I", ...)按大端取出 4 字节整数,(label >> 18) & 0x3FFF取高 14 位作为 DPC,(label >> 4) & 0x3FFF取中间 14 位作为 OPC,label & 0x0F取低 4 位作为 SLS。0x3FFF 是 14 位掩码,0x0F 是 4 位掩码,如果你要适配 24 位点编码,这里的位置必须重排。
ISUP 部分从 MTP3 之后的第 5 个字节开始:CIC 占 2 字节,消息类型占 1 字节。IAM、ACM、ANM、REL、RLC 这些消息类型都有数值对应,代码里用字典转成可读名字。如果你解析到未知类型,会输出十六进制值,这时候先别急着当成垃圾消息,查一下是不是新规范或厂商私有扩展。真实解析里,IAM 的被叫号码还要继续解析 BCD 编码的号码字段,这段先用消息类型验证解析通路,号码字段交给 Wireshark 的isup.called_party_number去提取更稳妥。
4. 解析七号信令的常见问题排查:点编码、长度与SCCP的5个坑
4.1 过滤条件筛了半天,一张表是空的
现象:拿到一份 Sigtran 环境的 pcap,用-Y "ss7"过滤,结果一条消息都没有。
原因:SS7 过滤器只匹配 MTP 层,而 Sigtran 抓包里的信令载荷是被封装在 SCTP 里的 M3UA 消息。Wireshark 默认不会把它当 M3UA 解析,而是当成普通 SCTP 数据块,看不到 DPC/OPC 自然什么都筛不出来。
解决:先用-d指定端口对应的协议,常见 M3UA 端口是 2905:
tshark -r sigtran.pcap -d tcp.port==2905,m3ua \ -Y "m3ua || mtp3" \ -T fields -e m3ua.protocol_data.opc -e m3ua.protocol_data.dpc \ -E header=y-d tcp.port==2905,m3ua是强制解码规则,让 Wireshark 把该端口流量按 M3UA 处理。强制解码之后,M3UA 里的协议数据字段才会暴露出来。如果端口不是 2905,先看 pcap 里 SCTP 实际目的端口再改。图形界面里对应的操作是右键“Decode As”,命令行里就是-d。
4.2 长度指示不当字节算,字段一路越界
现象:解析脚本报“长度字段越界”,或者打印出来的被叫号码里全是奇怪的 ASCII 字符,和 Wireshark 里看到的不一致。
原因:MTP2 的 LI 字段单位是 16 位字,不是字节。很多第一次写解析器的人拿到 LI 直接用LI + 3当 SIF 长度,结果每一条消息的接口都偏了。FISU 的 LI 是 0,LSSU 是 1 或 2,MSU 从 2 往上,但表示的是后面 SIF 的字数。
解决:先把 LI 字段乘 2 转成字节数再做切片。校验方法很简单:取一条消息,LI=5,按 5×2=10 字节切 SIF,如果后续字段能正常对齐到 IAM、ACM 的消息类型,说明宽度对了。解析失败时,不要盯着字段值改掩码,先回过来看 LI 的换算。
4.3 14位和24位点编码混用,DPC/OPC全对不上
现象:Wireshark 里显示的信令点编码是一串很长的数字,你解析脚本里出来的却是一个小得多的数;或者同一个 pcap,两个工具读出的 DPC 完全不同。
原因:国内规范常见的 24 位点编码和 ITU-T 的 14 位点编码排布不同。14 位编码的路由标签是 DPC 14 位+OPC 14 位+SLS 4 位;24 位编码不是简单把 14 加 10,而是有自己的位段布局。用 14 位的解析逻辑去读 24 位的报文,拆出来的值自然不是本来的点编码。
解决:解析之前先确定点编码格式。在 Wireshark 里通过协议首选项设置信令点编码格式,自写脚本时按对应格式设计位段。解析结果最好和 Wireshark 对拍一次,对不上就先排查点编码格式再排查位操作。这一步错了,后面所有按 DPC 分表的统计都不可信。
4.4 SCCP的GT和SSN标志位没置位,TCAP业务全看不见
现象:明明有大量 SCCP 消息,但 TCAP 层一张空表。检查 SCCP 的 Called Party 字段时,GT 和 SSN 显示为空。
原因:SCCP 被叫地址字段的地址指示语里,用 bit 标记后面是否包含 GT、是否包含 SSN、是否包含路由。如果这些标志位没有正确置位,即使载荷里有地址内容,解析器也不会去读。另一个常见原因是 SSN 子系统号没配置,消息只能到信令点,不能继续路由到 HLR、MSC 这类业务节点。
解决:看 SCCP 消息时先解析地址指示语字节,确认 Called Party Address 里的 GT 类型、编号计划、翻译类型和 SSN 都有值。GT 的存在价值是解决跨网寻址,如果对端只需要 DPC 寻址,那 GT 为空是正常的;但凡是跨信令点的业务寻址,GT 和 SSN 必须一起出现。调试时可以先用 Wireshark 的sccp.called_party字段确认地址结构,再回头改解析器。
4.5 同一CIC的消息乱序,统计结果忽好忽坏
现象:单独看每一条 ISUP 消息都正常,但解析呼叫流程时发现 ACM 出现在 IAM 之前,或者 REL 之后没有再等到 RLC。
原因:同一对信令点之间存在多条链路,SLS 决定消息走哪条链路。负荷分担下,同一次呼叫的消息可能分散到不同链路,抓包只抓了其中一条,序列自然对不上。链路倒换发生时,SLS 的映射关系还会临时变化,让问题更隐蔽。
解决:做流程核对时,按 CIC 和 TCAP 事务 ID 对消息重新排序,不要依赖抓包顺序。测试环境里可以固定链路选择策略,让同一 CIC 始终走同一链路,能省掉大量排序的麻烦。
5. 验证SS7解析结果:两个可复现的字段自检技巧
5.1 字段级对拍:tshark结果和自己解析器逐字段diff
解析器写完,最怕出“看起来对但字段错了”的问题。我会把 tshark 的输出和自己脚本的输出各导成一份 CSV,用 diff 做字段级对拍:
tshark -r trace.pcap -Y "isup" -T fields \ -e frame.number -e mtp3.dpc -e isup.message_type \ -E header=y > tshark_out.csv python my_parser.py trace.pcap > my_out.csv diff <(cut -d, -f1-3 tshark_out.csv) <(cut -d, -f1-3 my_out.csv) | head -20diff 没有输出,说明至少 frame.number、DPC、消息类型这三列完全一致。如果只有少数行不一致,优先看点编码格式;如果大量不一致,多半是 MTP3 层就开始错位了。Windows 环境没有进程替换的话,先把两份 CSV 存成文件再 diff,道理一样。
5.2 状态机验收:一条完整呼叫必须走通IAM→ACM→ANM→REL→RLC
字段对拍通过之后,再做一次流程级验证。固定一个 CIC,检查同一通话的消息序列是否符合预期:
expected = ["IAM", "ACM", "ANM", "REL", "RLC"] actual = extract_messages("trace.pcap", cic=0x1234) for step, name in enumerate(expected): if actual[step] != name: print(f"第{step+1}条期望{name},实际{actual[step]}") break else: print("呼叫流程五步齐全")注意这个验收只适用于固定 CIC 的单通话测试场景。真实网络里有后向释放、早期 ACM、互放等分支,消息顺序不是教科书式的,所以代码里我用了逐步比对并输出第一个不匹配的字段,而不是要求全表完全等于 expected。验证目的是发现解析器有没有漏消息、字段有没有错位,不是为了证明网络符合理想流程。
我以前在这个环节吃过亏:写解析器时拿一段 Wireshark 的导出数据做样本,字段全对,没想到换了 pcap 就翻车。后来养成习惯,每接一份新抓包先做tshark + 自己脚本的对拍,再跑一次流程验收,两关都过了才把结果交给下游。这个习惯帮我在后面处理 SCCP 和 TCAP 业务解析时省了很多返工,希望帮到你。
本文还有配套的精品资源,点击获取