尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

七号信令SS7协议栈解析:从MTP到ISUP的抓包实战

七号信令SS7协议栈解析:从MTP到ISUP的抓包实战 简介这份关于SS7七号信令协议的完整资料包专为通信网络工程师、协议开发人员及电信专业研究者整理内容从电话网呼叫建立、路由选择与计费等基础场景切入系统讲解消息传递部分MTP的三层结构、信令连接控制部分SCCP的面向连接服务以及事务处理应用部分TCAP的复杂事务支撑并深入讨论信令点与信令转接点组网、信令数据单元SDU与信息元素格式、拥塞控制、安全漏洞与防护以及SS7与IP网络融合等专题兼顾原理与工程实践。资源包内共607个文件其中465张图片用于直观展示信令流程、协议栈层次与网络拓扑138个HTML文件构成多章节的知识文档另辅以少量文本说明整体压缩后约3.43MB便于离线查阅与按需检索。已有371人浏览学习内容由浅入深从协议背景到具体应用均有涉及适合需要系统掌握七号信令原理并解决实际网络问题的读者作为重要参考资料。1. SS7 协议包里的七号信令一套让交换机互报底细的底层规则干过核心网或信令监控的工程师都明白拨一通跨局电话最难的不是拨号而是两台交换机之间怎么互相说清楚“我这边来了个呼叫被叫是谁主叫是谁走哪条电路”。SS7七号信令就是这套底规则它不负责传语音只负责让交换机、HLR、SCP 这些网元用统一语言交换控制信息。很多人第一次接触七号信令拿到的就是一个 SS7 协议压缩包里面堆满 PDF 规范、抓包样例和零散的笔记真要用它把一条链路跑起来、把一条 ISUP 消息解出来还是得从头搭一套认知。这套协议解决的是信令怎么编、怎么传、怎么选路、怎么确认的问题。适合三类人核心网运维要定位跨局呼叫失败通信软件开发者要做信令解析或模拟网元以及做网络协议分析的人想搞懂电信网里最基础的信令骨架。下面按协议栈、抓包解析、呼叫流程、落地坑位这条线往下讲。2. 拆开 SS7 协议栈MTP 三层与 ISUP、SCCP、TCAP 各管哪一段2.1 三种信令单元MSU、LSSU、FISU 分别是谁在说话MTP2 这一层在链路上传的东西叫信令单元Signal Unit。抓一条 SS7 链路的包满屏都是三类信令单元新手最先要做的就是分清它们。FISU填充信令单元的作用是链路空闲时持续填帧让对端知道自己还活着同时在 MTP2 层做接收序号确认。LSSU链路状态信令单元只在链路激活、恢复、忙等状态切换时出现比如对端发来 SIO失去同步表示它那边链路状态不对。MSU消息信令单元才是真正干活儿的MTP3 管理消息、ISUP 呼叫消息、SCCP 业务消息全都装在 MSU 里。判断依据是长度指示LI字段LI0 是 FISULI1 或 2 是 LSSULI3 说明这是一个 MSU。信令单元LI 值主要用途出现时机FISU0填充链路、确认对端序号链路空闲时持续发送LSSU1 / 2表达链路状态失步、忙、紧急链路激活、故障恢复、过载MSU3承载 MTP3/ISUP/SCCP/TCAP 消息有实际信令业务时排除链路问题时先看 LSSU 的状态字再看 FISU 是否连续最后才查 MSU 内容。顺序反了经常会在一个根本不存在的业务消息里浪费半天。2.2 MTP2 保链路、MTP3 选路由14 位点编码与 SIO 的读法MTP3 管的是“消息从哪个信令点来、到哪个信令点去”。每个信令点有一个点编码ITU-T 规范里通常用 14 位能编 16384 个信令点。国内很多现网用的是 24 位变体所以解析之前必须先确认这条链路采用哪种点编码格式位宽不一样路由标记从头到尾全对不上。路由标记是 SIF业务信息字段的开头部分按位看是 DPC目的点编码 OPC源点编码 SLS信令链路选择码。SIO业务信息八位组紧跟在 MTP2 头之后低 4 位才是业务标识0 表示信令网管理消息3 表示 SCCP5 表示 ISUP。高 4 位是子服务字段用于区分国内网和国际网这一位经常被忽略但很多链路激活失败就是它跟对端不匹配。下面这段 Python 把一个 MSU 的路由标记和 ISUP 消息类型拆出来前提是你已经从抓包里拿到了 SIO 和 SIF 的原始字节。# 解析 MTP3 MSU 路由标记与 ISUP 消息类型ITU-T 14 位点编码为例 def bits_from_bytes(data): return .join(f{b:08b} for b in data) def parse_mtp3_msu(sio: int, sif: bytes): service sio 0x0F # 取低 4 位业务标识 bits bits_from_bytes(sif[:4]) # 路由标记占前 4 字节 # ITU-T 路由标记DPC 14bit | OPC 14bit | SLS 4bit dpc int(bits[0:14], 2) opc int(bits[14:28], 2) sls int(bits[28:32], 2) print(fDPC{dpc} (0x{dpc:04x}) OPC{opc} (0x{opc:04x}) SLS{sls}) print(fService Indicator {service}) if service 5: # ISUP 消息 rest bits_from_bytes(sif[4:7]) # CIC 12bit 消息类型 8bit cic int(rest[0:12], 2) msg_type int(rest[12:20], 2) isup_type_map { 0x01: IAM(初始地址), 0x02: ACM(地址全), 0x03: ANM(应答), 0x04: REL(释放), 0x0C: RLC(释放完成), } print(fCIC{cic} ISUP消息{isup_type_map.get(msg_type, f未知(0x{msg_type:02x}))})逻辑说明SIO 低 4 位决定上层用 ISUP 还是 SCCPSIF 前 4 字节按位切出 DPC、OPC、SLS。CIC 从 SIF 第 4 字节之后开始占 12 位ISUP 消息类型紧跟其后占 8 位。参数说明14 位点编码能覆盖常规局点24 位变体需要把前两段改成 24 位、SLS 改成 8 位后面 CIC 的偏移也要跟着加长 4 个 bit。2.3 ISUP 管呼叫、SCCP 管寻址、TCAP/MAP 管业务别把这三种业务混在一层SS7 协议栈最大的误解就是把 ISUP、SCCP、MAP 当成同层级的东西。ISUP 负责电路交换呼叫它直接跑在 MTP3 上业务标识为 5靠 CIC 关联到某条物理电路。SCCP 跑在 MTP3 之上业务标识为 3它解决的是“信令点找到了但点里哪个子系统要用这条消息”的问题所以引入了全局码GT和子系统号SSN。TCAP 和 MAP 都承载在 SCCP 之上智能网和移动业务查询走的是这一层。举一个最常见的场景HLR 查询。MTP3 把消息送到 HLR 所在的信令点但信令点里有多个应用SCCP 的 Called Party Address 里的 SSN 才能把消息递给 MAP 子系统。ISUP 没有这个能力它绑定的是电路不可能去寻址一个软件子系统。做协议解析时看到 SIO3 就不要再往 ISUP 的字段表里套直接切到 SCCP 的 Called Party Address 解析否则后面 GT 号码全拆错。3. 用 tshark 和 Python 解析一条 SS7 消息最小可复现步骤3.1 抓包前提TDM 链路怎么进 Wireshark先确认哪几件事SS7 最初跑在 TDM 链路上最常见的是 2M E1 的一个时隙承载一条信令链路。抓包有两种常见做法用带 SS7 采集卡的服务器接 E1 高阻跨接或者用信令综合测试仪直接导出 pcap。不管哪种方式落到 Wireshark 里能看到 MTP2 帧前提是抓包工具把 E1 时隙和 SS7 链路配置对了。开始解析之前先确认三件事点编码是 14 位还是 24 位SIO 里的网络指示是国内还是国际抓包方向是否包含了主备两条链路。这三项没确认后面所有解析结果都可能整体错位。一个常用的经验是先抓 5 分钟纯业务时段的链路统计 MSU 里 SIO 的分布看 ISUP 和 SCCP 的比例是否跟这个局点的业务类型对得上对不上说明时隙接错了。3.2 从 pcap 里导出 ISUP 字段tshark 一条命令做到位Wireshark 对 SS7 协议栈的支持已经很完整直接用 tshark 把关心的字段导成 CSV比对着原始字节手工拆高效得多。下面这条命令把 ISUP 消息的路由标记、CIC、消息类型全部导出来。# 从 SS7 抓包里导出所有 ISUP 消息的关键字段 tshark -r ss7_trace.pcap -Y mtp3 isup -T fields \ -e mtp3.opc -e mtp3.dpc -e mtp3.sls \ -e isup.message_type -e isup.cic \ -E headery -E separator, ss7_isup.csv逻辑说明-Y 过滤条件是 mtp3 且 isup确保只留下 MSU 里业务标识为 ISUP 的消息-T fields 指定按字段名输出-e 参数后面的字段名可以在 Wireshark 的协议详情里右键复制也可以直接跑 tshark -G fields 查。参数说明-E separator, 让结果变成逗号分隔方便下一段脚本直接读不要把 -Y 写成 -Y ss7过滤条件太宽会把底层维护消息也带进来统计时会混入噪声。拿到 CSV 之后用一段 Python 统计消息类型分布快速判断这段抓包里有没有完整的呼叫流程。import csv from collections import Counter # 读取 tshark 导出的 ISUP 字段 CSV统计消息类型分布 with open(ss7_isup.csv, newline, encodingutf-8) as f: rows list(csv.DictReader(f)) mt_counter Counter(r[isup.message_type] for r in rows) for mt, cnt in mt_counter.most_common(): print(f{mt}: {cnt})逻辑说明tshark 输出的 isup.message_type 是文本别名比如 IAM、ACM、ANM、REL、RLC不是十六进制数字所以 Counter 统计出来的分布能直接看出业务形态。参数说明如果某个局点是纯转接局IAM 和 REL 的消息数会明显多如果是端局ACM、ANM 的比例应该和 IAM 接近差距过大说明抓包丢帧或时隙接错。3.3 对照 tshark -V 输出核对你的解析结果字段导出方式解析很快但有一个隐患某个字段如果 Wireshark 解析错了你拿到的是错的别名自己却不知道。所以关键消息一定要回原始字节对照。# 查看第一条 IAM 消息的完整协议树 tshark -r ss7_trace.pcap -Y isup.message_type IAM -V | head -100-V 参数会把 MTP2、MTP3、ISUP 每一层完整展开。看的时候先核对 MTP3 里的 DPC、OPC 是否和现网规划一致再看 ISUP 层里的 CIC 和 Called Party Number。如果 -V 输出的点编码和你预期的差很远第一件事不是怀疑交换机而是确认 Wireshark 的 SS7 点编码解析设置是不是按 24 位格式配的很多时候问题是出在解析配置而不是现网数据。4. ISUP 呼叫流程实战IAM 到 RLC 的五个信令与时序参数4.1 IAM 最少要填哪些字段NCI、FCI、CPC、TMR 与被叫号码IAM初始地址消息是主叫侧交换机发出的第一个 ISUP 消息它相当于把“我要建立一个呼叫”的请求完整描述出来。IAM 里必选字段不少但绝大多数排障场景只关心五个NCI自然连接指示描述这条呼叫要不要卫星电路、是否连续性检验FCI前向呼叫指示描述端到端方法、互通条件CPC主叫类别区分普通用户、话务员、测试呼叫TMR传输介质要求说明这条呼叫需要语音、64k 数据还是其他承载被叫号码是判断呼叫路由最直接的字段。排查“号码不存在”或“路由错号”这类问题时直接导出每个 IAM 的被叫号码和目的点编码比在交换机里翻配置快得多。下面这条 tshark 命令把每个 IAM 的主叫侧点编码和被叫号码拉出来按呼叫建立顺序看一遍基本能定位路由配置错误。# 导出每个呼叫的 IAM 关键信息源点编码、目的点编码、被叫号码 tshark -r ss7_trace.pcap -Y isup.message_type IAM \ -T fields -e frame.number -e mtp3.opc -e mtp3.dpc \ -e isup.called_party_number -E headery逻辑说明called_party_number 字段输出的是按协议规范解码后的号码串如果显示为空或者只有奇数位通常是对端填充了奇怪的长度指示或者这条消息根本不是 IAM。参数说明frame.number 保留是为了回头在 pcap 里定位原始帧排障时“第几帧出问题”是和其他网元对时间的锚点。4.2 ACM、ANM、REL、RLC四种后续消息与时序位置一次正常的局间呼叫ISUP 层面只走五个关键消息。IAM 发出后被叫侧交换机如果找到了被叫用户并开始振铃回 ACM地址全消息被叫摘机回 ANM应答消息任何一方挂机发起方发 REL释放消息并带原因值对端处理完释放回 RLC释放完成消息。消息方向含义常见原因值IAM主叫局 → 被叫局请求建立呼叫无ACM被叫局 → 主叫局地址已收到开始振铃无ANM被叫局 → 主叫局被叫应答无REL任意一侧发起请求释放呼叫16 正常 / 17 用户忙等RLC对侧应答确认释放完成无用 Python 按 CIC 把消息串成一条呼叫记录可以很直观地看出一通呼叫卡在哪一步。import csv from collections import defaultdict # 按 CIC 分组重建每条电路的 ISUP 消息时序 calls defaultdict(list) with open(ss7_isup.csv, newline, encodingutf-8) as f: for row in csv.DictReader(f): cic row[isup.cic] mt row[isup.message_type] calls[cic].append(mt) for cic, msgs in calls.items(): # 只打印包含完整呼叫的消息链 if IAM in msgs: print(fCIC{cic}: - .join(msgs))逻辑说明CIC 是电路标识同一通呼叫的 IAM、ACM、ANM、REL、RLC 都落在同一个 CIC 上所以按 CIC 分组就能还原一条电路的呼叫过程。参数说明如果打印出来只有 IAM 没有后续消息说明对端没有回任何确认问题大概率在链路层或对端局向配置如果只有 IAM 和 REL说明呼叫被快速拒绝要看 REL 的原因值。4.3 从抓包里定位呼叫失败REL 的 cause value 是第一个线索REL 消息里带的原因值是整个 ISUP 排障里最直接的线索。常见原因值不多但每个都指向不同的排障方向1 表示未分配号码17 表示用户忙18 表示无用户响应27 表示目的地址不可达28 表示号码格式无效34 表示无电路/信道可用。原因值 34 出现时优先查中继电路和 CIC 配置原因值 1 和 28 出现时优先查号码变换和路由数据。在 tshark 里直接过滤 REL 的原因值字段把同一条中继里失败呼叫的原因值汇总很快就能看出故障是集中型的还是分散型的。集中在一个原因值基本可以锁定一个配置点分散多个原因值则要往上层业务或对端局整体状态去排查。5. 七号信令落地避坑链路失效、点编码错位、GT 超时的 5 条血泪记录5.1 链路激活类收了一整天 FISU链路就是起不来现象抓包软件里链路始终显示失去同步或未激活MTP2 层只能看到持续的 FISU偶发 LSSU但 MSU 一条都没有。原因最常见的是两侧对 SIO 高 4 位子服务字段的约定不一致。你的信令点按国内网配置对端按国际网配置MTP2 能收到帧但 MTP3 不会认为这条链路可以承载业务于是永远停在链路激活确认阶段。解决在抓包里对比两侧发出的 LSSU 状态字和 SIO 子服务字段两边必须一致才能进入激活态。改完本端配置后先看 LSSU 是否从“失去同步”切到“正常”切换成功再查 MSU。链路激活这种问题百分之八十出在这一个字节上。5.2 路由标记类OPC/DPC 写反消息被交换机静默丢弃现象消息发出来了对端也收到了但从头到尾不回任何响应。tcpdump 或 Wireshark 里能看到 MSU 持续出现业务却一点反应没有。原因路由标记里的 DPC 和 OPC 填反了。接收方检查源点编码时发现这个信令点编码和实际来源不符直接丢弃而且丢弃通常是静默的不会给你回任何错误信令。解决用上面那段 Python 脚本把每条 MSU 的 OPC、DPC 打印出来对照交换机里的信令点编码表。发现 OPC 和 DPC 恰好互换了说明是路由标记组装处的位序写反CIC 部分的错位往往也是同一个原因带出来的。5.3 位宽错位24 位点编码按 14 位拆CIC 全乱现象解析出来的 DPC、OPC 看起来像无规律数字CIC 也不是预期范围ISUP 消息类型偶尔能对上但字段全错。原因现网用 24 位点编码解析脚本按 14 位拆路由标记后面所有字段的 bit 偏移全部错了 10 位CIC 和消息类型从错误的位置截取。解决解析脚本里把点编码位宽做成参数默认从抓包文件或配置读取。同时校验规则要跟上DPC 和 OPC 必须在已知信令点编码表里CIC 必须落在中继电路范围内。只要这两个校验有一个不过就停止解析并报“编码格式疑似不匹配”而不是继续输出错误结果。5.4 业务寻址类SCCP 的 GT 寻址超时MAP 业务一直无响应现象SCCP 消息发出后没有收到任何响应定时器超时上层 MAP 业务反复报 no response。抓包看消息已经送到了对端信令点但对端就是不回。原因SCCP 的 Called Party Address 里Translation Type 和全局码编码格式不匹配对端配置。比如 TT 填了 0 表示按 GT 直接翻译对端却期望 TT 指向某个特定的号码分析配置消息进了交换机但找不到翻译规则。解决把 SCCP 消息里的 Called Party Address 逐字段导出重点核对 TT、NP号码方案、AI编码指示和 GT 解析出的号码。GT 的奇偶指示ODD/EVEN是另一个高频踩坑点号码位数为奇数时填充规则写错GT 解析出来就多一位或少一位对端匹配不上。5.5 排查习惯类抓包没留够时间事后没有后悔药现象呼叫故障已经发生想定位却找不到那个时间点的抓包。手里只有一段 3 分钟的 pcap里面全是链路空闲的 FISU关键呼叫一条都没抓到。原因信令跟踪开得太晚或者抓包工具只按需启停没有做成常驻采集。SS7 链路不像 IP 网络可以随时 tcpdump信令链路很多时候要从 E1 采集设备上回放数据采集没开回放无从谈起。解决凡是跑 ISUP 和 SCCP 业务的链路建立常置信令跟踪至少保留 24 小时原始 pcap并确保每一帧带绝对时间戳。排查的时候先按时间窗口定位再按 CIC 或 GT 过滤。信令侧的这种数据是典型的“平时不觉得有用、出事才知道值钱”没有后悔药。6. 用两个独立解析器互相验证让七号信令的解析结果不再玄学6.1 字段级 difftshark 和自写脚本对照同一批包信令解析有过一个很深的教训自写脚本顺着规范推字段结果推出来和交换机实际行为完全相符但和 Wireshark 解析结果差了两位数。最后发现是点编码位宽的认知错了——以为现场按 14 位编码实际按 24 位跑。从那以后养成的习惯是同一批 pcap至少跑两套独立解析逐字段 diff。做法是先用 tshark 导出参考结果再用自写脚本导出同样字段两个文件按行比对。# 导出 tshark 的 ISUP 解析结果作为参考 tshark -r ss7_trace.pcap -Y isup -T fields \ -e mtp3.opc -e mtp3.dpc -e isup.cic \ -e isup.message_type -E separator, ref.txt # 自写脚本输出同样格式到 out.txt然后按列对比 diff ref.txt out.txtdiff 干净不代表绝对正确但任何一列不一致都值得停下检查到底是脚本切错了位还是 tshark 的 SS7 配置默认值和现网不一致。两套解析器同时在同一条链路判断上出错的可能性远低于一套解析器默默带偏。6.2 留一个原始字节导出习惯能救回很多疑难杂症字段级解析快但遇到边缘情况比如被叫号码携带奇怪填充位、optional 参数带错指针还是要回到最原始的字节。推荐一个习惯排障阶段对每条异常消息用 tshark 把 MTP3 以上部分以 hex 形式导出存成独立文件连同解析脚本一起归档。如果换了工具、换了配置之后解析结果变了至少还有一份原始字节可以重新拆。做七号信令这些年最值钱的一条经验是永远别在没抓包的时候改配置也永远别只信单一解析器的输出。协议栈层次多一个 bit 的偏移错误就能让后续所有字段全部错位而两套解析器互相验证是成本最低的兜底手段。希望这些拆包和排障的思路帮到你少踩几个已经有人替你踩过的坑。本文还有配套的精品资源点击获取
返回列表