<!-- title: 5G漫游引导SoR机制全链拆解 -->
<!-- domain: security -->

# 5G漫游引导（SoR）安全保护机制全链拆解

## 一、为什么需要SoR：一个被"中间人"威胁的漫游决策

在5G漫游场景中，UE的PLMN选择（驻留哪个运营商网络）直接决定漫游结算收益归属。归属网络（HPLMN）希望把漫游用户"引导"到自己签约的、资费更优的合作伙伴网络上；而拜访网络（VPLMN）出于自身利益，有强烈动机篡改甚至伪造"优选PLMN列表"，让UE长期驻留在能给自己带来分成的网络上。在没有完整性保护的时代，这种"漫游引导"（Steering of Roaming，**SoR**）实际上是可以被VPLMN中间人攻击的——它篡改下发给UE的列表，UE无从分辨真伪。

3GPP在TS 33.501中专门为这个问题设计了独立的安全机制（§6.14），其核心思想只有一句话：**只有真正持有用户长期密钥的归属网络（AUSF），才能为SoR列表"盖章"（MAC），UE只认这个章，拜访网络只能当透明的"快递员"。** 本文基于TS 33.501 V18.10.0（Release 18）、TS 24.501、TS 23.122与TS 23.502，逐条拆解这套机制的密钥推演、信令流程、IE结构与抓包排错要点。

值得一提的是，SoR与另一组机制UPU（UE Parameters Update，§6.15）是一对"姊妹"设计：UPU-MAC的KDF结构与SoR完全同构（Annex A.19/A.20对应A.17/A.18），只是UPU用于推送UE参数更新（如路由指示、默认配置的NSSAI），SoR用于推送漫游优选列表。理解了SoR，UPU也就通了。

## 二、为什么用K_AUSF而不是K_SEAF——机制设计的灵魂

要理解SoR，必须先看懂它的密钥选择。5G主认证后建立的密钥层级是：

```
K(永久) → K_AUSF → K_SEAF → K_AMF → {K_NAS_int, K_NAS_enc, K_gNB ...}
```

关键点在于**密钥的可见性边界**：
- **K_AUSF**：仅在UE与归属网络的AUSF之间共享。
- **K_SEAF / K_AMF**：在漫游时由AUSF下发给**拜访网络的SEAF/AMF**，即VPLMN完全掌握。

如果把SoR的MAC用K_AMF或K_SEAF来算，那么掌握这些密钥的VPLMN就能自己伪造一个合法的MAC——这正是要防的攻击！所以SoR刻意选用**K_AUSF**：这是密钥层级中"拜访网络永远摸不到"的最高一级密钥。于是：

- AUSF用K_AUSF算出 `SoR-MAC-I_AUSF`，VPLMN无密钥、无法伪造；
- UE本地也持有K_AUSF（主认证时与AUSF同步建立），可独立验算。

这就是SoR安全性的根基：**用密钥的"不可见性"换取"不可伪造性"**。下面所有KDF细节都围绕K_AUSF展开。

## 三、密钥推演：Annex A.17 / A.18 的精确KDF

5G KDF基于HMAC-SHA-256（TS 33.501 Annex B.2），输入串 `S = FC || P0 || L0 || P1 || L1 || ...`，取输出的相应低位作为派生密钥/MAC。

### 3.1 下行MAC：SoR-MAC-I_AUSF（Annex A.17）

这是AUSF为下发列表盖的"章"，UE据此验真：

| 参数 | 取值 | 说明 |
|------|------|------|
| 输入密钥 KEY | **K_AUSF** | 拜访网络不可见 |
| FC | **0x77** | SoR-MAC-I_AUSF 的固定区分符 |
| P0 | SoR header | A.17中的SoR头（含List type/ACK指示等） |
| L0 | length of SoR header | |
| P1 | Counter_SoR | 16位新鲜性计数器 |
| L1 | length of Counter_SoR | |
| P2 | SOR transparent container中"第22字节之后"的内容 | 见TS 24.501 §9.11.3.51 |
| L2 | P2中list数据的长度 | |
| 输出 | **输出的128个最低有效位** | 即16字节MAC |

注意一个精妙设计：P2取的是"容器第22字节之后"的部分。这是因为容器前22字节是固定的元信息（IEI/长度/SoR header/MAC/Counter），真正可变的有效载荷（优选PLMN列表或secured packet）从第23字节开始，所以MAC只对"业务内容"做保护，同时header和Counter单独作为P0/P1计入——既避免冗余，又把所有影响UE决策的字段都覆盖到。

### 3.2 上行MAC：SoR-MAC-I_UE（Annex A.18）

UE成功验证并应用列表后，要给网络一个"我确实收到了"的回执，回执里也带一个MAC，由UE用K_AUSF算出：

| 参数 | 取值 | 说明 |
|------|------|------|
| 输入密钥 KEY | **K_AUSF** | |
| FC | **0x78** | 与0x77区分方向 |
| P0 | **0x01** | 固定值，含义"SoR Acknowledgement: Verified the Steering of Roaming Information successfully" |
| L0 | **0x00 0x01** | 长度=1 |
| P1 | Counter_SoR | 与下行同一个Counter |
| L1 | length of Counter_SoR | |
| 输出 | **输出的128个最低有效位** | 16字节 |

网络侧（AUSF）用同样输入算出 `SoR-XMAC-I_UE` 与UE上报的 `SoR-MAC-I_UE` 比对，确认UE真的处理了这份列表。这解决了"列表到底有没有生效"的可观测性问题——运营商可以据此计费/审计引导成功率。

## 四、防重放：16位Counter_SoR（§6.14.2.3）

光有MAC还不够。设想VPLMN截获一份历史上合法的SoR列表（带合法MAC），日后反复重放给UE——只要MAC不变，UE就会一直接受过时列表。Counter_SoR就是为此设计的"新鲜性令牌"：

- AUSF与UE为**每个K_AUSF**绑定一个**16位**计数器；
- UE在新K_AUSF生成存储时初始化为 `0x00 0x00`；AUSF在控制面SoR方案下新K_AUSF存储时初始化为 `0x00 0x01`；
- AUSF**每计算一次**新SoR-MAC-I_AUSF就把Counter**加1**；
- Counter_SoR作为P1参与KDF，所以改Counter就改MAC，无法复用旧MAC；
- UE**只接受严格大于已存储值**的Counter；
- **只有当MAC验证成功后，UE才存储新Counter**——防止攻击者用大Counter"毒化"UE状态机导致后续合法列表被拒；
- UE生成上行SoR-MAC-I_UE时，使用从HPLMN收到的（已验证存储的）Counter。

这一组规则构成一个简洁的单调递增状态机：合法列表的Counter必然递增，重放的Counter必然≤已存值而被拒，且即便攻击失败也不会污染UE的计数器。16位计数器对K_AUSF生命周期（一次主认证周期）内的SoR更新次数绰绰有余。

## 五、完整信令时序图

SoR有两条下发路径：**注册期**（在REGISTRATION ACCEPT中捎带）和**注册后**（DL NAS TRANSPORT独立下发）。下图合并展示主流的"注册期下发+注册后更新"双路径与回执链路。

```text
sequenceDiagram
    autonumber
    participant UE
    participant AMF as AMF (VPLMN)
    participant UDM as UDM (HPLMN)
    participant AUSF as AUSF (HPLMN)

    Note over UE,AUSF: 前置：主认证完成，UE与AUSF共享K_AUSF
    UDM->>AUSF: Nausf_SoRProtection_Get<br/>(SoR header, 优选PLMN列表, ACK指示)
    AUSF->>AUSF: Counter_SoR++ ; KDF(K_AUSF, FC=0x77, ...)<br/>生成 SoR-MAC-I_AUSF
    AUSF-->>UDM: SoR-MAC-I_AUSF, Counter_SoR
    UDM->>AMF: Nudm_SDM_Get / N1N2MessageTransfer<br/>(SOR transparent container, 透传)
    AMF->>UE: REGISTRATION ACCEPT<br/>(Payload container = SOR transparent container)

    UE->>UE: KDF(K_AUSF, FC=0x77) 算 XMAC<br/>校验 Counter_SoR>已存 且 MAC相等
    Note over UE: 验证通过→应用优选列表(TS 23.122)<br/>存储Counter_SoR
    UE->>UE: KDF(K_AUSF, FC=0x78) 算 SoR-MAC-I_UE
    UE->>AMF: REGISTRATION COMPLETE<br/>(上行SOR transparent container = 回执MAC)
    AMF->>UDM: N1MessageNotify (回执)
    UDM->>AUSF: Nausf_SoRProtection_Verify
    AUSF->>AUSF: 算 SoR-XMAC-I_UE 比对
    AUSF-->>UDM: 验证结果(引导是否生效)

    Note over UE,UDM: ——注册后更新（独立路径）——
    UDM->>AUSF: Nausf_SoRProtection_Get (新列表)
    AUSF-->>UDM: 新 SoR-MAC-I_AUSF + 新Counter_SoR
    UDM->>AMF: Namf_Communication_N1N2MessageTransfer(N1消息)
    AMF->>UE: DL NAS TRANSPORT (Payload container=SOR container)
    UE->>AMF: UL NAS TRANSPORT (上行回执MAC)
    AMF->>UDM: 回执转发
```

几个关键节点说明：
- **第2步**UDM是"请求方NF"（requester NF），SoR header可由UDM构造、也可由AUSF根据收到的ACK指示与列表自行构造（A.17原文）。
- **第4步**AMF对容器内容**完全不理解、不解析、不修改**——它只是按Payload container的"container type=SOR transparent container"原样搬运。这正是安全边界：AMF即使想篡改也无能为力，因为篡改后MAC对不上。
- **第6步**UE的验算与第3步AUSF的计算使用完全相同的输入（K_AUSF、FC=0x77、header、Counter、列表字节），故XMAC与MAC必相等——这是HMAC-SHA-256的确定性保证。
- **第8-10步**回执链路让HPLMN获得"引导成功"的确认，可对接计费/分析系统。

## 六、SOR transparent container 的字节级结构（TS 24.501 §9.11.3.51）

该IE是**type 6**信息元素（长度可变，带2字节长度域），**最小长度20字节**。其经典布局（List type=1，承载PLMN/access technology列表）如下：

```mermaid
flowchart TB
    subgraph CT["SOR transparent container (TS 24.501 §9.11.3.51)"]
        direction TB
        O1["octet 1<br/>SOR transparent container IEI"]
        O23["octet 2-3<br/>Length of contents"]
        O4["octet 4<br/>SoR header<br/>(List type / SOR data type / ACK指示 / 各SI标志位)"]
        O520["octet 5-20<br/>SoR-MAC-I<sub>AUSF</sub> (16字节=128bit)"]
        O2122["octet 21-22<br/>Counter<sub>SoR</sub> (16bit)"]
        O23n["octet 23* - m*<br/>Length + PLMN ID and access technology list<br/>(或 secured packet，List type=0时)"]
        Oo["octet o* ...<br/>(可选) SOR-CMCI / SOR-SNPN-SI / SOR-SNPN-SI-LS"]
    end
    style O520 fill:#ffd6d6,stroke:#b30000
    style O2122 fill:#fff2cc,stroke:#bf9000
    style O4 fill:#d9ead3,stroke:#38761d
```

对应的IE参数说明表：

| 字段（字节位置） | 含义 | 取值/说明 |
|---|---|---|
| IEI（octet 1） | 信息元素标识 | 标识"这是SOR transparent container" |
| Length（octet 2-3） | 内容长度 | type 6 IE固定2字节长度域 |
| SoR header（octet 4） | 头部比特域 | List type（0=secured packet，1=PLMN/接入技术列表）、SOR data type、ACK指示、及新版本SOR-CMCI/SOR-SNPN-SI等标志位 |
| SoR-MAC-I_AUSF（octet 5-20） | 下行MAC | AUSF用K_AUSF、FC=0x77算出，128bit |
| Counter_SoR（octet 21-22） | 新鲜性计数器 | 16bit单调递增，防重放 |
| 有效载荷（octet 23*-m*） | 优选列表/secured packet | List type=1时为"长度+PLMN ID与接入技术优先级列表"；List type=0时为secured packet |
| 可选扩展（octet o*+） | SOR-CMCI 等 | R17+扩展：公共凭证标识、SNPN相关引导信息 |

注意上行（回执）容器更精简：只含IEI/长度/header/**SoR-MAC-I_UE**（FC=0x78算出的回执MAC），不再带列表。

## 七、UE验证与应用的状态机

UE收到容器后的处理是一个明确的判定流程，下图给出其决策路径（结合§6.14.2.3的Counter规则）：

```mermaid
flowchart TD
    A["收到 REGISTRATION ACCEPT / DL NAS TRANSPORT<br/>含 SOR transparent container"] --> B{"Counter_SoR > 已存值?"}
    B -- 否 --> R1["拒绝（疑似重放）<br/>不更新，不上报回执"]
    B -- 是 --> C["用本地 K_AUSF、FC=0x77 算 XMAC"]
    C --> D{"XMAC == 收到的 SoR-MAC-I_AUSF?"}
    D -- 否 --> R2["验证失败：丢弃<br/>不存储Counter，不上报回执"]
    D -- 是 --> E["存储新 Counter_SoR<br/>（仅验签成功才存）"]
    E --> F["按 TS 23.122 应用优选PLMN/接入技术列表"]
    F --> G["FC=0x78 算 SoR-MAC-I_UE"]
    G --> H["发 REGISTRATION COMPLETE / UL NAS TRANSPORT 带回执"]
    style R1 fill:#f4cccc
    style R2 fill:#f4cccc
    style E fill:#d9ead3
    style F fill:#d9ead3
```

设计意图小结：步骤B（先比Counter）和步骤E（验签成功才存Counter）联合起来，把"重放"和"状态毒化"两类攻击都堵死——即便攻击者伪造一个超大Counter，由于没有K_AUSF算不出正确MAC，会在步骤D失败，UE也不会存储这个大Counter，下次真正合法的列表仍能被接受。

## 八、与相关机制/方案的对比

| 维度 | SoR（漫游引导） | 传统EHPLMN/EPLMN/UEL优先级 | UPU（UE参数更新） | NCCoC/Network Configuration |
|---|---|---|---|---|
| 规范 | TS 33.501 §6.14 + A.17/A.18 | TS 23.122 / USIM文件 | TS 33.501 §6.15 + A.19/A.20 | TS 31.102/31.111 |
| 下发内容 | 优选PLMN/接入技术列表 | UE/USIM预置，静态 | 路由指示、默认NSSAI等UE参数 | 网络配置数据 |
| 安全密钥 | **K_AUSF**（拜访网不可见） | 无密码学保护 | **K_AUSF**（与SoR同构） | 依赖secured packet/USIM |
| 防重放 | 16位Counter_SoR单调递增 | 无 | 16位Counter_UPU | 视实现 |
| 触发时机 | 注册期/注册后均可 | 仅UE本地选择 | 注册期/注册后 | OTA/管理面 |
| 设计目标 | 防VPLMN篡改引导，保护HPLMN结算收益 | 简单优先级，无防篡改 | 安全推送UE运行参数 | 灵活配置 |

一个常被忽略的对比是**为何SoR不用secured packet（USIM OTA式）而要新建机制**：secured packet依赖USIM与HPLMN间的长期密钥、走SIM卡应用层，更新慢、且依赖USIM能力；而SoR走5G NAS层、用主认证刚建立的K_AUSF，**注册后即可立即生效、无需USIM OTA往返**，更适合"实时引导漫游"这种对时延敏感的商业场景。

## 九、抓包识别：如何在报文里找到SoR

在Wireshark/TShark中（5G NAS dissector）识别SoR流程：

1. **下行（网络→UE）**：找 `Registration accept` 或 `DL NAS TRANSPORT` 消息；
2. 展开 `Payload container` → `Payload container type` 应为 **"SOR transparent container"**（区别于N1 SM info、UE parameters update等）；
3. 展开该container，可见：
   - `SOR-MAC-I`（16字节）、`Counter`（2字节）、`List type`、`SOR data type`、`ACK` 指示位；
   - 若List type=1，后面跟着 `Length of PLMN ID and access technology list` 与各 `PLMN ID + Access technology` 条目（MCC/MNC + 接入技术标识）。
4. **上行（UE→网络）**：找 `Registration complete` 或 `UL NAS TRANSPORT`，其 `Payload container type = SOR transparent container`，内含 `SOR-MAC-I` 回执（FC=0x78计算），通常不含列表。

快速TShark过滤示例：

```bash
# 抓取所有承载SOR透明容器的NAS消息
tshark -i <iface> -Y "nas_5gs.payload_container_type == 4" -V
# （注：container type 4 在多数版本dissector中映射为SOR，5为UPU；以实际版本为准）
```

识别要点：SoR消息**总是出现在N1（NAS）层**、**总是封装在Payload container里**、**AMF侧不解析内容**——所以你在N2（NGAP）或N11（AMF-UDM SBI）上看到的是"透传"形态。

## 十、常见故障点与排错思路

**故障1：UE不应用新SoR列表（引导失效）。**
最常见原因是**MAC验证失败**。排查方向：
- 用抓包确认下行容器完整传输（未在SBI/N2被截断）；
- 核对AUSF侧K_AUSF是否与UE一致（若中间发生再认证、K_AUSF更新但Counter未同步，会失配）；
- 检查AUSF的Counter_SoR与UE已存值：若因掉电、双注册等原因UE的Counter"超前"（大于AUSF），则AUSF后续列表Counter恒≤UE，UE会一直拒绝——需触发重新主认证重置K_AUSF+Counter。

**故障2：Counter回卷/重置后列表被持续拒绝。**
按§6.14.2.3，Counter绑定K_AUSF生命周期。新主认证→新K_AUSF→Counter重置（UE为0x0000，AUSF控制面为0x0001）后应恢复正常。若仍拒绝，检查UE是否把Counter存到了**非易失**存储（规范要求：支持5G扩展存储的USIM存USIM，否则存ME非易失内存）——存到易失内存会在重启后回零，造成与网络不同步。

**故障3：组合注册时延异常增大（约数十秒）。**
GSMA IR.73实测指出：**在组合注册（Combined Registration）上叠加SoR流程，会带来约75秒量级的注册时延**。根因是SoR回执要等REGISTRATION COMPLETE，而组合注册的EPS/5GS协调拉长了窗口。优化建议：把SoR放到**注册后**用DL NAS TRANSPORT下发，避免阻塞初始注册；或调整ACK指示策略（不强求每次都回ACK）。

**故障4：VPLMN漫游引导"看起来生效但资费仍是旧伙伴"。**
这是经典的**VPLMN侧篡改未遂但UE仍按本地EHPLMN/EPLMN旧优先级选网**的情况。需确认UE是否真的收到了带合法MAC的新列表（看抓包），并核对UE侧SoR列表在TS 23.122选择逻辑中的优先级位置——SoR列表仅在自动选网模式且满足条件时才"覆盖"部分本地列表，并非无条件最高优先。

**故障5：AMF透传失败导致容器丢失。**
AMF若因不支持（旧版本）或Payload container处理Bug而丢弃该IE，UE收不到列表。表现为抓包里**只有N11（UDM→AMF）有容器、N1（AMF→UE）没有**。检查AMF版本是否支持TS 24.501 §9.11.3.51及对应Payload container type。
## 常见问题

**Q1：SoR用的K_AUSF，UE每次注册都换吗？会否导致Counter频繁重置？**
A：K_AUSF在每次5G主认证（5G AKA或EAP-AKA'）时重新派生，所以重新认证会重置Counter（UE置0x0000）。常态下不会频繁触发——只要不重新认证，K_AUSF与Counter在整个注册周期内保持，SoR可多次增量下发。

**Q2：SoR-MAC-I_AUSF和SoR-MAC-I_UE为什么FC不同（0x77 vs 0x78）？**
A：KDF要求派生结果与用途严格绑定。下行（网络盖章给UE）和上行（UE回执给网络）虽都用K_AUSF，但语义相反，用不同FC（0x77/0x78）隔离，避免上下行消息在KDF层面产生可关联/可伪造的交叉，是标准的"用途分离"安全工程实践。

**Q3：拜访网络能不能伪造一个Counter很大的容器来"毒化"UE？**
A：不能造成持久危害。伪造大Counter但没有K_AUSF→算不出正确MAC→UE在第D步验签失败→**不存储该Counter**（§6.14.2.3明确"仅在MAC验证成功后才存储Counter"）。所以UE状态机不受污染，后续HPLMN的合法列表仍被正常接受。

**Q4：SoR和UPU到底什么关系？**
A：架构上同源、KDF同构。SoR（§6.14，A.17/A.18）推漫游优选列表，UPU（§6.15，A.19/A.20）推UE运行参数（路由指示、默认配置NSSAI等）。两者都用K_AUSF、都有16位单调Counter、都走NAS的Payload container、都有下行MAC+上行回执MAC。掌握其一即通其二。

**Q5：如果UE处于手动选网模式，SoR还有效吗？**
A：SoR列表影响的是**自动选网模式**下的PLMN优先级（TS 23.122）。手动模式下用户指定网络，SoR列表不强制改写用户选择，但其安全验证（MAC/Counter）仍会执行并存储，等切回自动模式时生效。

## 参考来源

1. [3GPP TS 33.501 V18.10.0 — Security architecture and procedures for the 5G System](https://www.etsi.org/deliver/etsi_ts/133500_133599/133501/18.10.00_60/ts_133501v181000p.pdf) — §6.14 Steering of roaming security mechanism，§6.14.2.3 SoR Counter，Annex A.17/A.18 KDF
2. [TS 33.501 §6.14 — Steering of roaming security mechanism（在线版）](https://itecspec.com/spec/3gpp-33-501-6-14-steering-of-roaming-security-mechanism/) — 6.14.2.1/6.14.2.2/6.14.2.3 子节索引
3. [TS 33.501 Annex A.17 — SoR-MAC-I_AUSF generation function](https://itecspec.com/3gpp/33.501/s/a.17) — FC=0x77，KEY=K_AUSF，P0/P1/P2参数定义
4. [3GPP TS 24.501 — NAS protocol for 5GS](https://www.3gpp.org/deliver/3gpp_ts/24.501/) — §9.11.3.51 SOR transparent container IE，§8.2.8.2 回执处理
5. [GSMA IR.73 — Steering of Roaming Implementation Guidelines V10.0](https://www.gsma.com/newsroom/wp-content/uploads/IR.73-v10.0.pdf) — 组合注册叠加SoR导致约75秒注册时延的实测与商业指引
6. [3GPP TS 23.122 — NAS functions related to Mobile Station](https://www.3gpp.org/deliver/3gpp_ts/23.122/) — SoR列表在自动PLMN选择中的优先级应用规则

---
> 本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵**爱卫生**（微信ID: gprshome201101）维护，聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。
> 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
