1. 项目概述为什么NAS层安全与合规性验证如此重要在5G网络里NAS层也就是非接入层是终端和核心网之间进行“高层对话”的协议层。它负责处理像注册、鉴权、会话管理这些关键信令。你可以把它想象成手机和网络大脑之间进行身份确认和业务请求的“加密电话”。这个“电话”的内容如果被窃听或篡改后果不堪设想——你的位置可能被跟踪通信可能被劫持甚至整个网络都可能受到攻击。因此3GPP标准对NAS层的安全性尤其是信令的加密和完整性保护有着极其严格的规定。终端厂商、芯片厂商和测试机构必须确保他们生产的每一台5G设备其NAS层的加密实现都100%符合标准。这不仅是技术问题更是合规性要求是产品上市前的“必答题”。传统的验证方法往往依赖昂贵的专用测试仪表和封闭的测试环境流程长、成本高、灵活性差。而开源代码的出现为我们提供了一把“手术刀”让我们能以更低的成本、更高的透明度深入解剖和验证终端NAS层的加密合规性。这个项目就是探讨如何利用开源工具和代码搭建一套实战化的验证环境亲手验证你的5G终端比如一部5G手机或一个CPE设备是否真的“守规矩”。2. 核心需求与开源方案选型解析2.1 明确验证目标我们要验证什么在动手之前我们必须把目标拆解清楚。NAS层安全合规性验证核心是验证终端在NAS信令交互中是否正确实现了3GPP TS 33.501等标准中定义的安全算法和流程。具体来说主要包括算法套件支持验证终端是否支持标准强制要求的加密和完整性保护算法如5G核心的NEA0/128-NEA1/128-NEA2/128-NEA3 NIA0/128-NIA1/128-NIA2/128-NIA3。这里NEA是加密算法NIA是完整性算法。密钥派生验证终端能否根据核心网下发的密钥材料如K~ASME~ SUPI正确派生出用于NAS加密和完整性保护的密钥K~NASenc~ K~NASint~。这是安全的基础密钥错了一切皆错。加密/解密过程验证对于一条具体的NAS信令例如Registration Request终端能否使用正确的密钥和算法生成与标准预期完全一致的密文反之当收到核心网的加密消息时终端能否正确解密完整性保护验证终端能否为NAS信令生成正确的消息认证码MAC-I并且能验证核心网下发的消息的完整性验证XMAC-I是否匹配我们的开源验证方案就是要能模拟核心网的这部分安全功能与真实终端进行交互或离线分析从而完成上述验证。2.2 开源工具链选型与考量完全从零开始实现5G协议栈和安全算法是不现实的。幸运的是开源社区已经为我们打下了坚实的基础。以下是经过实战检验的选型组合核心协议栈与模拟器srsRAN Project这是我们的基石。srsRAN特别是其srsepc和srsenb组件提供了一个功能相对完整的开源5G核心网5GC和基站gNB实现。我们可以把它部署在一台Linux服务器上搭建一个私有的、可控的5G测试网络。选择它的理由很充分活跃的社区、清晰的代码结构、对最新协议的支持持续更新并且它内置了NAS消息的构造、解析以及安全上下文管理功能是我们与终端交互的“操作台”。协议分析利器Wireshark 5G DissectorWireshark是网络分析的瑞士军刀。其强大的5G协议解析插件dissector可以让我们在空口如果抓取到或网络接口上清晰地看到每条NAS消息的明文结构。这对于我们理解终端实际发送了什么、预期应该是什么至关重要。我们需要确保Wireshark更新到较新版本并启用对NR5G和NAS-5GS协议的支持。安全算法实现开源加密库如OpenSSL, libcrypto虽然srsRAN内部实现了部分算法但为了更透明、更底层地进行验证我们可能需要直接调用或参考标准的加密库。例如128-NEA2算法本质上就是AES-128-CTR128-NIA2是AES-128-CMAC。OpenSSL库提供了成熟、高效的实现。对于中国商用密码算法SM系列如果涉及则需要寻找对应的开源实现如GMSSL。这里有一个关键考量我们必须确保使用的开源算法实现与标准文档TS 33.501 Annex中的测试向量Test Vector完全匹配这是验证我们工具链自身正确性的“黄金标准”。辅助开发与脚本语言PythonPython是我们的“粘合剂”和“自动化工具”。我们将用Python来编写主控脚本用于控制srsRAN的启动、配置和日志收集。解析Wireshark抓包文件pcapng提取关键的NAS信令和安全参数。调用加密库函数独立计算密钥、生成MAC-I或进行加解密与终端的行为进行比对。生成结构化的测试报告。选型背后的逻辑这个组合覆盖了从“网络环境模拟”srsRAN到“数据捕获分析”Wireshark再到“核心安全运算验证”Python加密库的完整闭环。它成本极低几乎为零灵活性极高代码完全可控并且过程透明每一个步骤都可以被审查和复现这正是合规性验证所需要的特质。注意使用srsRAN搭建的网络是用于研发测试的切勿将其与运营商网络连接也避免使用真实的用户SIM卡应使用测试卡或配置的假数据。3. 实战环境搭建与核心配置3.1 硬件与基础软件准备你需要准备以下环境一台性能尚可的Linux PC/服务器推荐Ubuntu 20.04 LTS或22.04 LTS。作为我们的核心网、基站和测试控制中心。建议配备至少4核CPU、8GB内存。如果需要连接真实的射频前端如USRP则需要更强大的CPU和PCIe接口。待测5G终端一部支持SA独立组网模式的5G手机或CPE设备。确保其可以进入“开发者模式”并允许设置手动选网这对于连接到我们私有的测试网络至关重要。软件依赖安装# 更新系统并安装基础工具 sudo apt update sudo apt upgrade -y sudo apt install git cmake build-essential libfftw3-dev libsctp-dev libssl-dev libyaml-cpp-dev libboost-all-dev -y # 安装Wireshark用于抓包分析 sudo apt install wireshark -y # 将当前用户加入wireshark组以便非root抓包 sudo usermod -aG wireshark $USER # 需要重新登录生效 # 安装Python3及必要库 sudo apt install python3 python3-pip -y pip3 install pyyaml pyshark cryptography scapy3.2 编译与部署srsRAN测试网络这是搭建环境的核心步骤。# 1. 克隆srsRAN项目代码 git clone https://github.com/srsran/srsRAN_Project.git cd srsRAN_Project # 2. 创建构建目录并编译 mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelWithDebInfo make -j$(nproc) # 使用多核加速编译 # 3. 配置核心网(EPC)和基站(eNB/gNB) # 首先配置核心网复制示例配置文件并修改 cd .. sudo cp srsEPC/epc.conf.example /etc/srsran/epc.conf sudo cp srsEPC/user_db.csv.example /etc/srsran/user_db.csv sudo cp srsEPC/mbms.conf.example /etc/srsran/mbms.conf # 编辑用户数据库文件添加一个测试用户 sudo vim /etc/srsran/user_db.csv # 文件内容示例添加一行 # 001010123456789, 00112233445566778899aabbccddeeff, 0x10, 0x20, 0x30, 0x40 # 这分别代表IMSI, K, OP/OPc, AMF, SQN # 其中K是密钥需要与后续终端配置匹配。这是一个测试值切勿用于生产。接下来我们需要配置基站的参数使其与我们的测试频段和终端能力匹配。由于我们可能没有真实的射频硬件srsRAN支持在“无射频”的模拟模式下运行这对于协议栈和NAS层测试完全足够。# 复制基站配置文件 sudo cp srsENB/enb.conf.example /etc/srsran/enb.conf sudo cp srsENB/rr.conf.example /etc/srsran/rr.conf sudo cp srsENB/sib.conf.example /etc/srsran/sib.conf sudo cp srsENB/drb.conf.example /etc/srsran/drb.conf # 关键修改enb.conf中的射频和小区参数 sudo vim /etc/srsran/enb.conf在enb.conf中找到并修改以下关键部分[rf] # 驱动设置为“none”以使用模拟射频避免硬件依赖 driver none # 设置一个虚拟的频点号例如n78频段的某个值 dl_earfcn 629000 [rat.eutra] # 由于是5G SA我们实际上需要配置gNB。但srsRAN的演进版本中配置方式可能有所不同。 # 更现代的配置是直接使用srsgnb和srsepc的5G SA配置文件。 # 这里以较新的srsRAN Project 5G SA配置为例你需要查看项目文档。 # 通常会有gnb.conf和amf.conf、smf.conf、upf.conf等。重要提示srsRAN项目正在快速向原生5G SA架构演进。对于5G NAS测试更推荐使用其5G SA模式的配置。你需要查阅项目最新文档配置gnb.conf基站、amf.conf核心网接入与移动性管理功能等文件。核心思路是配置一个虚拟的PLMN公共陆地移动网络如“00101”、TAC跟踪区码以及网络切片信息S-NSSAI。同时确保在amf.conf中配置的安全算法优先级与待测终端支持的能力相匹配例如# 在amf.conf或类似的安全策略部分 security: integrity_protection_order: - NIA2 - NIA1 - NIA0 ciphering_protection_order: - NEA2 - NEA1 - NEA0这个顺序告诉核心网优先与终端协商使用AES算法NIA2/NEA2。3.3 终端侧的关键配置要让终端连接到我们的测试网络需要在终端上进行手动网络选择。在终端手机的“设置” - “网络和互联网” - “移动网络”中进入“高级”或“运营商”设置。关闭“自动选择网络”。手动搜索网络你应该能搜索到我们srsRAN基站广播的PLMN例如“00101”。选择该网络进行注册。对于深度测试你可能需要配置终端的APN接入点名称或者在开发者选项中开启“始终显示5G图标”等调试选项以观察更详细的状态。最重要的是如果终端要求输入PIN码或进行其他鉴权我们需要确保在核心网的用户数据库user_db.csv或5G的UDM配置中配置的密钥K与终端SIM卡或测试配置文件中的根密钥一致。对于测试通常使用一组已知的测试密钥。4. 合规性验证实操流程与核心环节环境就绪后我们就可以开始真正的验证工作了。整个过程是一个“捕获-分析-计算-比对”的循环。4.1 步骤一触发注册流程并捕获NAS信令启动测试网络在服务器上按顺序启动5G核心网功能和基站功能。根据你的srsRAN版本命令可能类似# 终端1启动核心网功能AMF, SMF, UPF等可能有单独的进程或一个整合进程 ./build/srsepc/src/srsepc # 或者对于更新的5G SA架构 ./build/srsgnb/src/srsgnb --config gnb.conf # 在另一个终端启动AMF ./build/sramf/src/sramf --config amf.conf开始抓包在服务器上启动Wireshark选择正确的网络接口通常是lo回环接口或者srsRAN创建的虚拟隧道接口如srs_spgw_sgi或tun_srsue。设置过滤器为nas-5gs以便只显示NAS层信令。触发终端注册在手机上执行“手动选网”并选择我们的测试PLMN。终端会发起5G注册请求Registration Request。保存关键日志同时保存srsRAN各个进程的控制台输出日志。这些日志里通常包含更详细的协议解析信息特别是安全相关的参数如ngKSI密钥集标识符、ABBA参数、以及核心网下发的Authentication Request消息中的RAND随机数和AUTN认证令牌。4.2 步骤二提取关键安全参数从Wireshark抓包文件或srsRAN日志中我们需要提取出后续计算所必需的“原料”SUCI/SUPI用户的隐藏或永久标识符。在初始注册请求中终端可能发送SUCI。服务网络名称SNN由PLMN和网络切片标识符S-NSSAI组成。RAND和AUTN来自核心网的认证请求消息。这是5G AKA鉴权的核心。RES* 和RES*终端对认证请求的响应。我们需要终端的RES*来计算后续的密钥。ngKSI标识本次安全上下文的密钥集ID。ABBA参数防止重放攻击的额外参数。选择的加密和完整性算法标识符在Security Mode Command消息中核心网会通知终端使用哪种算法如NEA2 NIA2。实操技巧使用Python的pyshark库可以编程式地解析pcapng文件自动提取这些字段极大提高效率。例如import pyshark cap pyshark.FileCapture(nas_capture.pcapng, display_filternas-5gs) for pkt in cap: if hasattr(pkt, nas_5gs): msg_type getattr(pkt.nas_5gs, nas_5gs_mm_message_type, None) if msg_type 0x41: # Registration Request print(fSUCI or SUPI: {getattr(pkt.nas_5gs, nas_5gs_mm_5gs_mobile_identity, N/A)}) elif msg_type 0x56: # Authentication Request rand getattr(pkt.nas_5gs, nas_5gs_mm_rand, None) autn getattr(pkt.nas_5gs, nas_5gs_mm_autn, None) print(fRAND: {rand}, AUTN: {autn})4.3 步骤三独立进行密钥派生与安全算法计算这是验证的核心。我们将不依赖终端或核心网的黑盒而是根据3GPP标准文档TS 33.501描述的算法用Python和加密库自己算一遍。计算CK‘, IK‘ 和 K~AUSF~使用提取的RAND、AUTN以及我们知道的用户根密钥K来自测试用户数据库实现5G AKA算法基于Milenage算法验证AUTN是否正确并计算出RES*、CK‘、IK‘。然后根据SNN等参数通过KDF密钥派生函数计算出K~AUSF~。# 伪代码示例展示流程 from cryptography.hazmat.primitives import hashes, hmac from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF import os # 假设我们已经有了以下输入 K bytes.fromhex(00112233445566778899aabbccddeeff) # 测试密钥 RAND bytes.fromhex(rand_hex_from_packet) SNN b5G:mnc001.mcc001.3gppnetwork.org # 示例 # 步骤1: 实现Milenage算法计算OPc, RES, CK, IK, AK... # (此处省略Milenage算法的详细实现需参考TS 35.206) OPc ... # 根据K和OP计算得出 RES, CK, IK, AK milenage_f1_f2345(K, OPc, RAND, SQN, AMF) # 步骤2: 计算CK‘, IK‘ (对CK和IK进行转换) CK_prime CK[8:16] CK[0:8] CK[24:32] CK[16:24] IK_prime IK[8:16] IK[0:8] IK[24:32] IK[16:24] # 步骤3: 计算K_ausf S b6B CK_prime IK_prime SNN b\x00\x00\x00\x10 # 0x10是K_ausf的FC值 kdf X963KDF(algorithmhashes.SHA256(), length32, sharedinfoS, backenddefault_backend()) K_ausf kdf.derive(b) # 输入密钥材料为空因为S包含了所有信息派生K~NASenc~ 和 K~NASint~从K~AUSF~出发继续使用KDF派生出口令加密和完整性保护所需的密钥。# 派生K_nasenc S_enc b15 K_ausf algorithm_type_distinguisher algorithm_identity b\x00\x00\x00\x01 kdf_enc X963KDF(algorithmhashes.SHA256(), length16, sharedinfoS_enc, backenddefault_backend()) K_nasenc kdf_enc.derive(b) # 派生K_nasint (类似FC值不同) S_int b16 K_ausf algorithm_type_distinguisher algorithm_identity b\x00\x00\x00\x01 kdf_int X963KDF(algorithmhashes.SHA256(), length16, sharedinfoS_int, backenddefault_backend()) K_nasint kdf_int.derive(b)验证加密与完整性加密验证选择一条终端发送的、已加密的NAS消息如Security Mode Complete。使用我们计算出的K~NASenc~和协商的算法如NEA2/AES-CTR结合消息中的COUNT计数器、BEARER承载ID和DIRECTION方向生成的IV初始化向量尝试解密这条消息。如果解密后的明文符合NAS消息的TLV类型-长度-值结构并且内容合理例如包含预期的消息类型则说明终端的加密过程符合标准。完整性验证对于一条需要完整性保护的NAS消息如初始的Registration Request终端会计算MAC-I并包含在消息中。我们使用计算出的K~NASint~和相同的算法如NIA2/AES-CMAC按照标准规定的输入消息、COUNT、BEARER、DIRECTION等重新计算一次MAC-I。将我们计算出的XMAC-I与消息中携带的MAC-I进行逐位比对。如果一致则完整性保护验证通过。4.4 步骤四结果比对与报告生成将我们独立计算的结果与观察到的网络行为进行比对直接比对对于完整性验证直接比对MAC-I。对于加密验证比对解密后的明文是否可读、结构是否正确。间接验证观察整个流程。如果终端能够成功完成注册、安全模式激活并且后续的信令交互如PDU会话建立正常这本身就是一个强有力的间接证据表明基本的密钥协商和安全流程是通的。但直接的计算比对才是合规性验证的“铁证”。生成报告编写Python脚本将上述提取的参数、计算过程、中间结果、最终比对结果自动整理成一份结构化的报告如JSON或Markdown格式。报告应清晰列出测试项如“NEA2加密验证”、“NIA2完整性验证”、输入参数、预期结果、实际结果来自终端/网络和验证结论通过/失败。5. 常见问题排查与实战心得在实际操作中你几乎一定会遇到各种问题。以下是一些典型问题及排查思路5.1 终端无法注册到测试网络现象手机搜索不到网络或选择网络后一直显示“正在注册”然后失败。排查检查PLMN配置确保srsgnb和sramf配置文件中广播的PLMNMCCMNC与终端手动选择的网络一致。终端通常只显示MCC和MNC。检查频段配置确保基站配置的dl_arfcn或nr_dl_arfcn在终端支持的频段范围内。对于5G常见的测试频段是n783500MHz。在模拟模式下频点号更多是一个逻辑标识但需确保协议栈内一致。检查核心网进程状态使用ps aux | grep srs查看所有srsRAN进程是否都在运行并查看其日志是否有错误。特别是AMF和UPF进程。检查网络命名空间和路由srsRAN可能会创建虚拟网络设备并修改路由。使用ip addr show和ip route show检查是否有异常。有时需要手动添加路由或防火墙规则。终端日志如果终端有工程模式或可以抓取Android日志adb logcat | grep -i rild或adb logcat | grep -i EMM查看终端的NAS层日志通常会有详细的失败原因代码。5.2 安全模式协商失败现象注册请求后网络下发了Security Mode Command但终端回复了Security Mode Reject或者流程中断。排查算法优先级不匹配这是最常见的原因。检查核心网AMF配置的ciphering_protection_order和integrity_protection_order。终端在Security Capability信息元素中会上报自己支持的算法。网络下发的Security Mode Command里选择的算法必须是终端支持列表中的第一个按网络优先级。实操心得为了测试可以在AMF配置中只保留一种终端肯定支持的算法如NEA2/NIA2避免协商复杂度。密钥问题终端计算出的密钥与网络侧不一致导致无法解密或验证完整性。务必确保终端使用的根密钥K、OPc参数与核心网用户数据库UDM中配置的完全一致。对于测试强烈建议使用3GPP标准文档附录C或D中提供的标准测试向量Test Vector来配置K和OPc这样可以排除参数错误。ABBA参数确保Security Mode Command消息中的ABBA参数与之前Authentication Request中下发的ABBA参数一致。5.3 抓包看不到预期的NAS消息或消息不完整现象Wireshark中过滤器nas-5gs没有数据或者消息显示为“Malformed Packet”。排查抓包接口错误srsRAN的用户面和控制面数据可能通过不同的虚拟接口传输。尝试在Wireshark中捕获所有接口any或者使用命令ip link show查看所有接口寻找名称中包含srs、tun、gtp的接口进行捕获。协议版本确保Wireshark更新到最新版本至少3.6以上并启用了“3GPP NAS-5GS”协议解析器。旧版本可能无法正确解析5G NAS消息。加密导致如果安全模式已激活后续的NAS消息会被加密。Wireshark默认无法解密。你需要将密钥导入Wireshark。在Wireshark的编辑 - 首选项 - 协议 - 5G NAS中可以添加解密密钥。但这需要你知道K~NASenc~这正是我们验证过程要计算的东西。因此对于加密后的消息验证我们主要依赖自己的Python脚本进行离线解密分析。5.4 自主计算的结果与抓包/日志不一致现象自己算出来的MAC-I或解密后的明文与预期不符。排查字节序问题这是最大的坑3GPP标准中很多参数如RAND、AUTN在空口传输时是字节流但在计算时可能需要考虑字节序大端序/小端序。黄金法则严格按照标准文档TS 33.501中给出的算法描述和示例输入输出进行验证。用一个已知的、简单的测试向量例如所有输入都为0来验证你的算法实现每一步的输出是否正确。输入参数错误确认用于计算的每一个输入参数都提取自正确的消息并且格式正确。例如COUNT值是一个复杂的结构包含NAS OVERFLOW、NAS SQN和5-bit的备用位需要从协议中精确还原。算法实现细节例如AES-CMAC用于NIA2和AES-CTR用于NEA2的模式、填充方式、初始向量的构造方式必须与标准完全一致。建议使用成熟的加密库如cryptography中经过验证的函数而不是自己从头实现AES。KDF输入串构造错误KDF的输入串S的构造非常严格包括FC值、P0、L0、P1、L1等的拼接顺序和长度编码。对照TS 33.501 Annex A.7的示例一个字节一个字节地检查你的S字符串。终极调试技巧实施“分步验证”。不要试图一次性验证整个流程。先写一个脚本用3GPP标准文档里的测试向量验证你的Milenage算法实现是否正确。再验证你的KDF函数是否正确。最后用你从真实抓包中提取的参数代入已验证正确的函数中计算。这样当最终结果不符时你可以快速定位问题出在参数提取阶段还是计算阶段。通过这套开源方案你不仅能够验证合规性更能深刻理解5G NAS安全机制的血肉与脉络。当你能亲手复现出与终端行为完全一致的安全参数时那种对技术的确信感是任何黑盒测试报告都无法给予的。这或许就是开源与实战的魅力所在。
基于开源工具链的5G NAS层安全合规性验证实战指南
1. 项目概述为什么NAS层安全与合规性验证如此重要在5G网络里NAS层也就是非接入层是终端和核心网之间进行“高层对话”的协议层。它负责处理像注册、鉴权、会话管理这些关键信令。你可以把它想象成手机和网络大脑之间进行身份确认和业务请求的“加密电话”。这个“电话”的内容如果被窃听或篡改后果不堪设想——你的位置可能被跟踪通信可能被劫持甚至整个网络都可能受到攻击。因此3GPP标准对NAS层的安全性尤其是信令的加密和完整性保护有着极其严格的规定。终端厂商、芯片厂商和测试机构必须确保他们生产的每一台5G设备其NAS层的加密实现都100%符合标准。这不仅是技术问题更是合规性要求是产品上市前的“必答题”。传统的验证方法往往依赖昂贵的专用测试仪表和封闭的测试环境流程长、成本高、灵活性差。而开源代码的出现为我们提供了一把“手术刀”让我们能以更低的成本、更高的透明度深入解剖和验证终端NAS层的加密合规性。这个项目就是探讨如何利用开源工具和代码搭建一套实战化的验证环境亲手验证你的5G终端比如一部5G手机或一个CPE设备是否真的“守规矩”。2. 核心需求与开源方案选型解析2.1 明确验证目标我们要验证什么在动手之前我们必须把目标拆解清楚。NAS层安全合规性验证核心是验证终端在NAS信令交互中是否正确实现了3GPP TS 33.501等标准中定义的安全算法和流程。具体来说主要包括算法套件支持验证终端是否支持标准强制要求的加密和完整性保护算法如5G核心的NEA0/128-NEA1/128-NEA2/128-NEA3 NIA0/128-NIA1/128-NIA2/128-NIA3。这里NEA是加密算法NIA是完整性算法。密钥派生验证终端能否根据核心网下发的密钥材料如K~ASME~ SUPI正确派生出用于NAS加密和完整性保护的密钥K~NASenc~ K~NASint~。这是安全的基础密钥错了一切皆错。加密/解密过程验证对于一条具体的NAS信令例如Registration Request终端能否使用正确的密钥和算法生成与标准预期完全一致的密文反之当收到核心网的加密消息时终端能否正确解密完整性保护验证终端能否为NAS信令生成正确的消息认证码MAC-I并且能验证核心网下发的消息的完整性验证XMAC-I是否匹配我们的开源验证方案就是要能模拟核心网的这部分安全功能与真实终端进行交互或离线分析从而完成上述验证。2.2 开源工具链选型与考量完全从零开始实现5G协议栈和安全算法是不现实的。幸运的是开源社区已经为我们打下了坚实的基础。以下是经过实战检验的选型组合核心协议栈与模拟器srsRAN Project这是我们的基石。srsRAN特别是其srsepc和srsenb组件提供了一个功能相对完整的开源5G核心网5GC和基站gNB实现。我们可以把它部署在一台Linux服务器上搭建一个私有的、可控的5G测试网络。选择它的理由很充分活跃的社区、清晰的代码结构、对最新协议的支持持续更新并且它内置了NAS消息的构造、解析以及安全上下文管理功能是我们与终端交互的“操作台”。协议分析利器Wireshark 5G DissectorWireshark是网络分析的瑞士军刀。其强大的5G协议解析插件dissector可以让我们在空口如果抓取到或网络接口上清晰地看到每条NAS消息的明文结构。这对于我们理解终端实际发送了什么、预期应该是什么至关重要。我们需要确保Wireshark更新到较新版本并启用对NR5G和NAS-5GS协议的支持。安全算法实现开源加密库如OpenSSL, libcrypto虽然srsRAN内部实现了部分算法但为了更透明、更底层地进行验证我们可能需要直接调用或参考标准的加密库。例如128-NEA2算法本质上就是AES-128-CTR128-NIA2是AES-128-CMAC。OpenSSL库提供了成熟、高效的实现。对于中国商用密码算法SM系列如果涉及则需要寻找对应的开源实现如GMSSL。这里有一个关键考量我们必须确保使用的开源算法实现与标准文档TS 33.501 Annex中的测试向量Test Vector完全匹配这是验证我们工具链自身正确性的“黄金标准”。辅助开发与脚本语言PythonPython是我们的“粘合剂”和“自动化工具”。我们将用Python来编写主控脚本用于控制srsRAN的启动、配置和日志收集。解析Wireshark抓包文件pcapng提取关键的NAS信令和安全参数。调用加密库函数独立计算密钥、生成MAC-I或进行加解密与终端的行为进行比对。生成结构化的测试报告。选型背后的逻辑这个组合覆盖了从“网络环境模拟”srsRAN到“数据捕获分析”Wireshark再到“核心安全运算验证”Python加密库的完整闭环。它成本极低几乎为零灵活性极高代码完全可控并且过程透明每一个步骤都可以被审查和复现这正是合规性验证所需要的特质。注意使用srsRAN搭建的网络是用于研发测试的切勿将其与运营商网络连接也避免使用真实的用户SIM卡应使用测试卡或配置的假数据。3. 实战环境搭建与核心配置3.1 硬件与基础软件准备你需要准备以下环境一台性能尚可的Linux PC/服务器推荐Ubuntu 20.04 LTS或22.04 LTS。作为我们的核心网、基站和测试控制中心。建议配备至少4核CPU、8GB内存。如果需要连接真实的射频前端如USRP则需要更强大的CPU和PCIe接口。待测5G终端一部支持SA独立组网模式的5G手机或CPE设备。确保其可以进入“开发者模式”并允许设置手动选网这对于连接到我们私有的测试网络至关重要。软件依赖安装# 更新系统并安装基础工具 sudo apt update sudo apt upgrade -y sudo apt install git cmake build-essential libfftw3-dev libsctp-dev libssl-dev libyaml-cpp-dev libboost-all-dev -y # 安装Wireshark用于抓包分析 sudo apt install wireshark -y # 将当前用户加入wireshark组以便非root抓包 sudo usermod -aG wireshark $USER # 需要重新登录生效 # 安装Python3及必要库 sudo apt install python3 python3-pip -y pip3 install pyyaml pyshark cryptography scapy3.2 编译与部署srsRAN测试网络这是搭建环境的核心步骤。# 1. 克隆srsRAN项目代码 git clone https://github.com/srsran/srsRAN_Project.git cd srsRAN_Project # 2. 创建构建目录并编译 mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelWithDebInfo make -j$(nproc) # 使用多核加速编译 # 3. 配置核心网(EPC)和基站(eNB/gNB) # 首先配置核心网复制示例配置文件并修改 cd .. sudo cp srsEPC/epc.conf.example /etc/srsran/epc.conf sudo cp srsEPC/user_db.csv.example /etc/srsran/user_db.csv sudo cp srsEPC/mbms.conf.example /etc/srsran/mbms.conf # 编辑用户数据库文件添加一个测试用户 sudo vim /etc/srsran/user_db.csv # 文件内容示例添加一行 # 001010123456789, 00112233445566778899aabbccddeeff, 0x10, 0x20, 0x30, 0x40 # 这分别代表IMSI, K, OP/OPc, AMF, SQN # 其中K是密钥需要与后续终端配置匹配。这是一个测试值切勿用于生产。接下来我们需要配置基站的参数使其与我们的测试频段和终端能力匹配。由于我们可能没有真实的射频硬件srsRAN支持在“无射频”的模拟模式下运行这对于协议栈和NAS层测试完全足够。# 复制基站配置文件 sudo cp srsENB/enb.conf.example /etc/srsran/enb.conf sudo cp srsENB/rr.conf.example /etc/srsran/rr.conf sudo cp srsENB/sib.conf.example /etc/srsran/sib.conf sudo cp srsENB/drb.conf.example /etc/srsran/drb.conf # 关键修改enb.conf中的射频和小区参数 sudo vim /etc/srsran/enb.conf在enb.conf中找到并修改以下关键部分[rf] # 驱动设置为“none”以使用模拟射频避免硬件依赖 driver none # 设置一个虚拟的频点号例如n78频段的某个值 dl_earfcn 629000 [rat.eutra] # 由于是5G SA我们实际上需要配置gNB。但srsRAN的演进版本中配置方式可能有所不同。 # 更现代的配置是直接使用srsgnb和srsepc的5G SA配置文件。 # 这里以较新的srsRAN Project 5G SA配置为例你需要查看项目文档。 # 通常会有gnb.conf和amf.conf、smf.conf、upf.conf等。重要提示srsRAN项目正在快速向原生5G SA架构演进。对于5G NAS测试更推荐使用其5G SA模式的配置。你需要查阅项目最新文档配置gnb.conf基站、amf.conf核心网接入与移动性管理功能等文件。核心思路是配置一个虚拟的PLMN公共陆地移动网络如“00101”、TAC跟踪区码以及网络切片信息S-NSSAI。同时确保在amf.conf中配置的安全算法优先级与待测终端支持的能力相匹配例如# 在amf.conf或类似的安全策略部分 security: integrity_protection_order: - NIA2 - NIA1 - NIA0 ciphering_protection_order: - NEA2 - NEA1 - NEA0这个顺序告诉核心网优先与终端协商使用AES算法NIA2/NEA2。3.3 终端侧的关键配置要让终端连接到我们的测试网络需要在终端上进行手动网络选择。在终端手机的“设置” - “网络和互联网” - “移动网络”中进入“高级”或“运营商”设置。关闭“自动选择网络”。手动搜索网络你应该能搜索到我们srsRAN基站广播的PLMN例如“00101”。选择该网络进行注册。对于深度测试你可能需要配置终端的APN接入点名称或者在开发者选项中开启“始终显示5G图标”等调试选项以观察更详细的状态。最重要的是如果终端要求输入PIN码或进行其他鉴权我们需要确保在核心网的用户数据库user_db.csv或5G的UDM配置中配置的密钥K与终端SIM卡或测试配置文件中的根密钥一致。对于测试通常使用一组已知的测试密钥。4. 合规性验证实操流程与核心环节环境就绪后我们就可以开始真正的验证工作了。整个过程是一个“捕获-分析-计算-比对”的循环。4.1 步骤一触发注册流程并捕获NAS信令启动测试网络在服务器上按顺序启动5G核心网功能和基站功能。根据你的srsRAN版本命令可能类似# 终端1启动核心网功能AMF, SMF, UPF等可能有单独的进程或一个整合进程 ./build/srsepc/src/srsepc # 或者对于更新的5G SA架构 ./build/srsgnb/src/srsgnb --config gnb.conf # 在另一个终端启动AMF ./build/sramf/src/sramf --config amf.conf开始抓包在服务器上启动Wireshark选择正确的网络接口通常是lo回环接口或者srsRAN创建的虚拟隧道接口如srs_spgw_sgi或tun_srsue。设置过滤器为nas-5gs以便只显示NAS层信令。触发终端注册在手机上执行“手动选网”并选择我们的测试PLMN。终端会发起5G注册请求Registration Request。保存关键日志同时保存srsRAN各个进程的控制台输出日志。这些日志里通常包含更详细的协议解析信息特别是安全相关的参数如ngKSI密钥集标识符、ABBA参数、以及核心网下发的Authentication Request消息中的RAND随机数和AUTN认证令牌。4.2 步骤二提取关键安全参数从Wireshark抓包文件或srsRAN日志中我们需要提取出后续计算所必需的“原料”SUCI/SUPI用户的隐藏或永久标识符。在初始注册请求中终端可能发送SUCI。服务网络名称SNN由PLMN和网络切片标识符S-NSSAI组成。RAND和AUTN来自核心网的认证请求消息。这是5G AKA鉴权的核心。RES* 和RES*终端对认证请求的响应。我们需要终端的RES*来计算后续的密钥。ngKSI标识本次安全上下文的密钥集ID。ABBA参数防止重放攻击的额外参数。选择的加密和完整性算法标识符在Security Mode Command消息中核心网会通知终端使用哪种算法如NEA2 NIA2。实操技巧使用Python的pyshark库可以编程式地解析pcapng文件自动提取这些字段极大提高效率。例如import pyshark cap pyshark.FileCapture(nas_capture.pcapng, display_filternas-5gs) for pkt in cap: if hasattr(pkt, nas_5gs): msg_type getattr(pkt.nas_5gs, nas_5gs_mm_message_type, None) if msg_type 0x41: # Registration Request print(fSUCI or SUPI: {getattr(pkt.nas_5gs, nas_5gs_mm_5gs_mobile_identity, N/A)}) elif msg_type 0x56: # Authentication Request rand getattr(pkt.nas_5gs, nas_5gs_mm_rand, None) autn getattr(pkt.nas_5gs, nas_5gs_mm_autn, None) print(fRAND: {rand}, AUTN: {autn})4.3 步骤三独立进行密钥派生与安全算法计算这是验证的核心。我们将不依赖终端或核心网的黑盒而是根据3GPP标准文档TS 33.501描述的算法用Python和加密库自己算一遍。计算CK‘, IK‘ 和 K~AUSF~使用提取的RAND、AUTN以及我们知道的用户根密钥K来自测试用户数据库实现5G AKA算法基于Milenage算法验证AUTN是否正确并计算出RES*、CK‘、IK‘。然后根据SNN等参数通过KDF密钥派生函数计算出K~AUSF~。# 伪代码示例展示流程 from cryptography.hazmat.primitives import hashes, hmac from cryptography.hazmat.primitives.kdf.x963kdf import X963KDF import os # 假设我们已经有了以下输入 K bytes.fromhex(00112233445566778899aabbccddeeff) # 测试密钥 RAND bytes.fromhex(rand_hex_from_packet) SNN b5G:mnc001.mcc001.3gppnetwork.org # 示例 # 步骤1: 实现Milenage算法计算OPc, RES, CK, IK, AK... # (此处省略Milenage算法的详细实现需参考TS 35.206) OPc ... # 根据K和OP计算得出 RES, CK, IK, AK milenage_f1_f2345(K, OPc, RAND, SQN, AMF) # 步骤2: 计算CK‘, IK‘ (对CK和IK进行转换) CK_prime CK[8:16] CK[0:8] CK[24:32] CK[16:24] IK_prime IK[8:16] IK[0:8] IK[24:32] IK[16:24] # 步骤3: 计算K_ausf S b6B CK_prime IK_prime SNN b\x00\x00\x00\x10 # 0x10是K_ausf的FC值 kdf X963KDF(algorithmhashes.SHA256(), length32, sharedinfoS, backenddefault_backend()) K_ausf kdf.derive(b) # 输入密钥材料为空因为S包含了所有信息派生K~NASenc~ 和 K~NASint~从K~AUSF~出发继续使用KDF派生出口令加密和完整性保护所需的密钥。# 派生K_nasenc S_enc b15 K_ausf algorithm_type_distinguisher algorithm_identity b\x00\x00\x00\x01 kdf_enc X963KDF(algorithmhashes.SHA256(), length16, sharedinfoS_enc, backenddefault_backend()) K_nasenc kdf_enc.derive(b) # 派生K_nasint (类似FC值不同) S_int b16 K_ausf algorithm_type_distinguisher algorithm_identity b\x00\x00\x00\x01 kdf_int X963KDF(algorithmhashes.SHA256(), length16, sharedinfoS_int, backenddefault_backend()) K_nasint kdf_int.derive(b)验证加密与完整性加密验证选择一条终端发送的、已加密的NAS消息如Security Mode Complete。使用我们计算出的K~NASenc~和协商的算法如NEA2/AES-CTR结合消息中的COUNT计数器、BEARER承载ID和DIRECTION方向生成的IV初始化向量尝试解密这条消息。如果解密后的明文符合NAS消息的TLV类型-长度-值结构并且内容合理例如包含预期的消息类型则说明终端的加密过程符合标准。完整性验证对于一条需要完整性保护的NAS消息如初始的Registration Request终端会计算MAC-I并包含在消息中。我们使用计算出的K~NASint~和相同的算法如NIA2/AES-CMAC按照标准规定的输入消息、COUNT、BEARER、DIRECTION等重新计算一次MAC-I。将我们计算出的XMAC-I与消息中携带的MAC-I进行逐位比对。如果一致则完整性保护验证通过。4.4 步骤四结果比对与报告生成将我们独立计算的结果与观察到的网络行为进行比对直接比对对于完整性验证直接比对MAC-I。对于加密验证比对解密后的明文是否可读、结构是否正确。间接验证观察整个流程。如果终端能够成功完成注册、安全模式激活并且后续的信令交互如PDU会话建立正常这本身就是一个强有力的间接证据表明基本的密钥协商和安全流程是通的。但直接的计算比对才是合规性验证的“铁证”。生成报告编写Python脚本将上述提取的参数、计算过程、中间结果、最终比对结果自动整理成一份结构化的报告如JSON或Markdown格式。报告应清晰列出测试项如“NEA2加密验证”、“NIA2完整性验证”、输入参数、预期结果、实际结果来自终端/网络和验证结论通过/失败。5. 常见问题排查与实战心得在实际操作中你几乎一定会遇到各种问题。以下是一些典型问题及排查思路5.1 终端无法注册到测试网络现象手机搜索不到网络或选择网络后一直显示“正在注册”然后失败。排查检查PLMN配置确保srsgnb和sramf配置文件中广播的PLMNMCCMNC与终端手动选择的网络一致。终端通常只显示MCC和MNC。检查频段配置确保基站配置的dl_arfcn或nr_dl_arfcn在终端支持的频段范围内。对于5G常见的测试频段是n783500MHz。在模拟模式下频点号更多是一个逻辑标识但需确保协议栈内一致。检查核心网进程状态使用ps aux | grep srs查看所有srsRAN进程是否都在运行并查看其日志是否有错误。特别是AMF和UPF进程。检查网络命名空间和路由srsRAN可能会创建虚拟网络设备并修改路由。使用ip addr show和ip route show检查是否有异常。有时需要手动添加路由或防火墙规则。终端日志如果终端有工程模式或可以抓取Android日志adb logcat | grep -i rild或adb logcat | grep -i EMM查看终端的NAS层日志通常会有详细的失败原因代码。5.2 安全模式协商失败现象注册请求后网络下发了Security Mode Command但终端回复了Security Mode Reject或者流程中断。排查算法优先级不匹配这是最常见的原因。检查核心网AMF配置的ciphering_protection_order和integrity_protection_order。终端在Security Capability信息元素中会上报自己支持的算法。网络下发的Security Mode Command里选择的算法必须是终端支持列表中的第一个按网络优先级。实操心得为了测试可以在AMF配置中只保留一种终端肯定支持的算法如NEA2/NIA2避免协商复杂度。密钥问题终端计算出的密钥与网络侧不一致导致无法解密或验证完整性。务必确保终端使用的根密钥K、OPc参数与核心网用户数据库UDM中配置的完全一致。对于测试强烈建议使用3GPP标准文档附录C或D中提供的标准测试向量Test Vector来配置K和OPc这样可以排除参数错误。ABBA参数确保Security Mode Command消息中的ABBA参数与之前Authentication Request中下发的ABBA参数一致。5.3 抓包看不到预期的NAS消息或消息不完整现象Wireshark中过滤器nas-5gs没有数据或者消息显示为“Malformed Packet”。排查抓包接口错误srsRAN的用户面和控制面数据可能通过不同的虚拟接口传输。尝试在Wireshark中捕获所有接口any或者使用命令ip link show查看所有接口寻找名称中包含srs、tun、gtp的接口进行捕获。协议版本确保Wireshark更新到最新版本至少3.6以上并启用了“3GPP NAS-5GS”协议解析器。旧版本可能无法正确解析5G NAS消息。加密导致如果安全模式已激活后续的NAS消息会被加密。Wireshark默认无法解密。你需要将密钥导入Wireshark。在Wireshark的编辑 - 首选项 - 协议 - 5G NAS中可以添加解密密钥。但这需要你知道K~NASenc~这正是我们验证过程要计算的东西。因此对于加密后的消息验证我们主要依赖自己的Python脚本进行离线解密分析。5.4 自主计算的结果与抓包/日志不一致现象自己算出来的MAC-I或解密后的明文与预期不符。排查字节序问题这是最大的坑3GPP标准中很多参数如RAND、AUTN在空口传输时是字节流但在计算时可能需要考虑字节序大端序/小端序。黄金法则严格按照标准文档TS 33.501中给出的算法描述和示例输入输出进行验证。用一个已知的、简单的测试向量例如所有输入都为0来验证你的算法实现每一步的输出是否正确。输入参数错误确认用于计算的每一个输入参数都提取自正确的消息并且格式正确。例如COUNT值是一个复杂的结构包含NAS OVERFLOW、NAS SQN和5-bit的备用位需要从协议中精确还原。算法实现细节例如AES-CMAC用于NIA2和AES-CTR用于NEA2的模式、填充方式、初始向量的构造方式必须与标准完全一致。建议使用成熟的加密库如cryptography中经过验证的函数而不是自己从头实现AES。KDF输入串构造错误KDF的输入串S的构造非常严格包括FC值、P0、L0、P1、L1等的拼接顺序和长度编码。对照TS 33.501 Annex A.7的示例一个字节一个字节地检查你的S字符串。终极调试技巧实施“分步验证”。不要试图一次性验证整个流程。先写一个脚本用3GPP标准文档里的测试向量验证你的Milenage算法实现是否正确。再验证你的KDF函数是否正确。最后用你从真实抓包中提取的参数代入已验证正确的函数中计算。这样当最终结果不符时你可以快速定位问题出在参数提取阶段还是计算阶段。通过这套开源方案你不仅能够验证合规性更能深刻理解5G NAS安全机制的血肉与脉络。当你能亲手复现出与终端行为完全一致的安全参数时那种对技术的确信感是任何黑盒测试报告都无法给予的。这或许就是开源与实战的魅力所在。