最近在捣鼓5G核心网,把Open5GS在Ubuntu 22.04上完整跑通了一遍。从源码编译、MongoDB初始化到gNB模拟接入,整个过程踩了一堆坑,也把核心网各个网元之间的信令流程理了一遍。这篇东西就直接把我最后验证可用的部署过程、配置思路和排障记录写出来,给同样在做5G核心网研究或者实验环境搭建的朋友做个参考。
我把整套东西定位成“能跑通、能调通、能看懂”的实战记录,而不是单纯贴一堆命令。你照着做可以起一套完整体验5G核心网的实验环境,适合跑RAN模拟器、接真实gNB做联调、测试用户面转发,也适合做网络切片和边缘计算相关实验的前置基础。
1. 整体设计与方案选型
1.1 为什么选Open5GS
5G核心网的开源方案里,现在能完整实现5G SA架构(服务化架构SBA)的主要就是Open5GS和free5GC这两个。两者我都试过,最终在Ubuntu 22.04上选Open5GS的原因挺直接的:首先是版本迭代频率高,社区活跃度明显更好,遇到问题能找到的讨论也多;其次是它把原有4G EPC和5G Core统一到了一套代码框架里,如果你后续想研究4G/5G互操作,在同一套系统里就能搞定,不用维护两套独立的核心网;最后就是它对硬件要求非常友好,跑在一台4核8G的虚拟机上就很稳,做实验完全够用。
对比一下两个主流方案的差异:
| 对比维度 | Open5GS | free5GC |
|---|---|---|
| 架构实现 | 4G/5G统一框架 | 纯5G Core |
| 版本迭代 | 持续更新,v2.7.x为主 | 更新节奏偏慢 |
| 资源占用 | 轻量,虚拟机可跑 | 相对较重 |
| 文档完备度 | 官方文档较全 | 依赖第三方教程 |
| 周边生态 | 支持UERANSIM模拟器多版本 | 同样支持,但适配版本较旧 |
| Web管理台 | 自带WebUI | 需要单独部署 |
选型的时候有个很实际的考量:Open5GS自带的Web管理台可以直接管理用户订阅信息,在跑实验的时候能省很多事。比如你要给100个测试终端批量开户,在Web界面操作比命令行一条条敲高效得多。
1.2 网络架构和部署形态设计
这次部署我采用的是单机全合一架构,就是把所有核心网网元装在同一台Ubuntu 22.04服务器上。虽然生产环境肯定不会这么干,但做实验和功能验证这是最简单直接的方式。
核心网各网元之间的接口关系大概是这样的:
- AMF负责接入管理,处理终端的注册、鉴权和移动性管理,对外的N1/N2接口连gNB。
- SMF管会话管理,负责PDU会话的建立、修改和释放,N4接口连UPF。
- UPF是用户面网元,所有业务数据流量都经过它转发。
- UDM存用户签约数据和鉴权参数,AUSF负责鉴权计算。
- NRF是所有服务化接口的注册中心,各网元启动后都要向NRF注册自己。
部署形态确定后,还要规划一下IP地址。这里强烈建议用独立的实验网段,避免和生产网络冲突。我这次用的是192.168.20.0/24网段,核心网各网元监听在192.168.20.129上,这个地址是可配置的,你完全可以根据自己环境调整。
安装方式上,我选择用源码编译而不是直接apt安装。为什么?因为Ubuntu官方源里的Open5GS版本往往偏旧,可能缺少一些新特性,而且有些最新版的UERANSIM和旧版Open5GS之间的兼容性会有问题。源码编译虽然多花十几分钟时间,但能保证版本配对没问题,后面联调时能少很多麻烦。
2. 环境准备与依赖安装
2.1 Ubuntu 22.04系统初始化
无论你是用物理机还是云服务器,建议都从最小化安装开始,不要带桌面环境,省下的资源都留给核心网跑信令。服务器版Ubuntu Server 22.04 LTS是最干净的起点。
系统装好后,首先做三件事:换源、更新、装基础工具。国内网络环境下,把apt源换成镜像源能快不少。基础工具包里build-essential和git是必须的,后面编译源码要用。
sudo apt update && sudo apt upgrade -y sudo apt install -y build-essential git curl wget gnupg这里有个细节需要注意:系统更新这一步别跳过。Open5GS对内核和系统库有一定要求,更新后的系统能保证依赖库版本比较新,减少编译时出现“找不到某某库”的概率。我最初在新装的系统上直接编译,就遇到过因为libssl-dev版本过旧导致的编译失败。
如果你打算在虚拟机上装,记得把虚拟机的网络模式调成桥接模式,这样核心网IP可以直接暴露在局域网里,后面接真实gNB时网络更顺畅。NAT模式下做纯模拟联调没问题,但一旦涉及真实硬件接入,NAT端口映射会把你折磨疯的。
2.2 MongoDB和依赖库安装
Open5GS使用MongoDB作为用户订阅信息的数据库,所以要提前把MongoDB装好。Ubuntu 22.04官方软件源里自带MongoDB,但版本比较旧。我这里直接用官方源安装最新稳定版。
sudo apt install -y mongodb sudo systemctl enable mongodb sudo systemctl start mongodb装完确认一下状态:
systemctl status mongodb看到active (running)就说明MongoDB已经正常工作了。这里提醒一下,如果之前装过MongoDB且配置过认证,要先确认认证配置是否正确,否则后面Open5GS连不上数据库,核心网各网元都启动不了。
接下来安装其他依赖库。Open5GS编译依赖不少东西,包括libssl、libsctp、libyaml、libmicrohttpd等。一条命令全部解决:
sudo apt install -y libssl-dev libsctp-dev libyaml-dev libmicrohttpd-dev \ libmongoc-dev libbson-dev libcurl4-openssl-dev libnghttp2-dev \ libidn11-dev libgnutls28-dev libgcrypt-dev libtalloc-dev \ libpcsclite-dev libc-ares-dev meson ninja-build有一个比较容易漏的依赖是libdw-dev,这是编译某些调试功能模块时需要的。如果编译过程中报错,提示找不到某些头文件,基本就是缺依赖库,用apt search找到对应的-dev包装上就行。
3. 核心网编译安装与网元配置
3.1 源码编译安装流程
依赖装好后,开始拉源码编译。选用官方GitHub仓库,拉取最新的稳定分支:
cd ~ git clone --recursive https://github.com/open5gs/open5gs.git cd open5gs meson build --prefix=/opt/open5gs ninja -C build--recursive参数很重要,Open5GS引用了子模块,如果漏了它,有些依赖代码拉不完整,编译时会出现一堆莫名其妙的错误。--prefix指定安装路径,我习惯单独装到/opt/open5gs,和系统自带软件隔离,方便以后整目录删除或升级。
编译过程快的话几分钟,慢的话十几分钟,取决于CPU性能。编译完成后执行安装:
sudo ninja -C build install装完后,配置一下动态链接库路径,否则运行时可能报找不到so文件的错误:
sudo ldconfig头文件和pkg-config路径也要配置一下,/etc/ld.so.conf.d/下面新建一个open5gs.conf,写入/opt/open5gs/lib,然后执行sudo ldconfig刷新。
3.2 核心网网元配置文件修改
安装完成后,Open5GS的配置文件默认在/opt/open5gs/etc/open5gs/目录下。每个网元都有一个独立的配置文件,比如amf.yaml、smf.yaml、upf.yaml等。默认配置绑定的IP地址是127.0.0.1,单机测试没问题,但如果你要把核心网暴露出去给远程gNB接入,就需要改成实际IP。
以AMF配置为例,核心改动是NGAP监听地址,这个地址是给gNB连接用的:
amf: serving: - plmn_id: mcc: 001 mnc: 01 tai: plmn_id: mcc: 001 mnc: 01 tac: 1 nssai: - sst: 1 ngap: - addr: 192.168.20.129PLMN(Public Land Mobile Network,公共陆地移动网络)编号这块,很多人刚开始不注意,直接用默认值也没问题,但如果你有自己测试用的PLMN,提前改好,后面的终端和基站模拟器都要保持一致。MCC(Mobile Country Code)是移动国家码,MNC(Mobile Network Code)是移动网络码,这套组合在全球范围内标识一个运营商网络。
SMF和UPF的配置重点在于N4接口地址必须互相能通。N4是SMF控制UPF的接口,这个断了对端到端的数据面路径是致命的。配置片段如下:
smf: pfcp: - addr: 192.168.20.129 gtpc: - addr: 192.168.20.129UPF侧对应配置:
upf: pfcp: - addr: 192.168.20.129 gtpu: - addr: 192.168.20.129修改完所有配置后,有一个非常重要的检查项:确保核心网各网元监听的端口没有被防火墙拦截。Ubuntu默认可能开着ufw防火墙,最好先放行这些端口,或者干脆直接在测试环境关闭防火墙:
sudo ufw disable如果不想关防火墙,就必须放行以下端口:AMF的NGAP端口38412(SCTP)、SMF的PFCP端口8805、UPF的GTPU端口2152、HTTP/2服务化接口端口80(或自定义端口)。SCTP协议不是所有防火墙都识别,建议测试期间直接关闭防火墙,等联调稳定后再按需放行。
3.3 启动核心网服务
Open5GS装完后会注册系统服务。启动全部网元可以用:
sudo systemctl start open5gs-mmed open5gs-sgwd open5gs-smfd open5gs-amfd open5gs-nrfd open5gs-ausfd open5gs-udmd open5gs-pcrfd open5gs-nssfd open5gs-upfd不过在实验环境里,我更喜欢用前台模式启动单个网元做调试。比如单独启动AMF:
sudo /opt/open5gs/bin/open5gs-amfd前台模式的好处是日志直接打在终端上,错误信息一目了然。调试确认没问题后,再切回systemd方式后台运行。
用systemd方式启动后,查看所有服务状态:
systemctl status open5gs-*关键是要看NRF的状态,因为5G核心网是服务化架构,AMF、SMF、UDM等网元启动后都要向NRF注册。如果NRF挂了,其他网元即使起来了也会报注册失败。我之前调试时NRF的配置没改对,其他网元纷纷报“NRF registration failure”。
这里建议大家按顺序启动:先NRF和AUSF/UDM,再AMF和SMF,最后UPF,这也是各网元依赖关系的自然顺序。
4. 用户签约配置与UERANSIM模拟基站接入
4.1 WebUI开户和命令行配置
核心网起来了,但没有用户签约信息的话,终端根本没法注册。Open5GS自带Web管理台,默认端口9999。启动WebUI:
sudo systemctl start open5gs-webui浏览器访问http://192.168.20.129:9999,默认账号密码是admin/admin,进去后可以配置用户和订阅信息。不过命令行也能搞定同样的事,更适合批量操作,语法是这样的:
curl -X POST http://192.168.20.129:3000/api/subscriber \ -H "Content-Type: application/json" \ -d '{ "imsi": "001010000000001", "subscriberStatus": "1", "security": { "k": "465B5CE8B199B49FAA5F0A2EE238A6BC", "opc": "E8ED289DEBA952E4283B54E88E6183CA", "amf": "8000", "sqn": "000000000000" }, "ambr": { "downlink": "1Gbps", "uplink": "1Gbps" }, "slice": [{ "sst": "1", "sd": "010203" }] }'IMSI的格式要和AMF配置里的PLMN保持一致。比如AMF里配的MCC=001、MNC=01,那IMSI开头就是00101。K和OPc参数是终端的鉴权密钥,后面UERANSIM的配置里也要用同一套,这个不能有不一致。
再来解释一下各个参数的含义。k是128位根密钥,opc是运营商密钥,这两者和终端的USIM信息对应。amf是鉴权管理字段,sqn是序列号。ambr是聚合最大比特率,相当于给这个用户设定带宽上限。slice(网络切片)里sst是切片类型,sd是切片区分符。
如果想让核心网在用户注册时自动执行某些操作,比如在UPF上自动下发规则,那需要配合SMF的流量控制功能。这个后面有时间单独讲,这次部署先保证注册和数据面跑通。
4.2 UERANSIM编译和配置
UERANSIM是开源5G UE和gNB模拟器,用来模拟手机和基站,是测试核心网的主力工具。下载编译:
cd ~ git clone https://github.com/aligung/UERANSIM cd UERANSIM make编译UERANSIM需要g++和make,大部分情况下前面装的build-essential就够了。编译产物在build目录下,主要是nr-gnb和nr-ue两个可执行文件。
UERANSIM的gNB配置在config/open5gs-gnb.yaml,需要把ngap地址指向核心网AMF:
mcc: '001' mnc: '01' amfConfigs: - address: 192.168.20.129 port: 38412 sdrConfigs: - address: 192.168.20.131 port: 58101这里有几个坑我得说一下。mcc和mnc必须和核心网AMF配置一致,否则NG建立会被拒绝。amfConfigs里的address要和AMF监听的NGAP地址一致。sdrConfigs这里其实不是软件无线电,它是UERANSIM自己定义的N2接口监听配置。有时编译出来的UERANSIM版本不同,配置字段可能有差异,具体以你的版本为例。
UE配置在config/open5gs-ue.yaml:
supi: 'imsi-001010000000001' mcc: '001' mnc: '01' key: '465B5CE8B199B49FAA5F0A2EE238A6BC' opc: 'E8ED289DEBA952E4283B54E88E6183CA' amf: '8000' sqn: '000000000000' sessions: - type: 'IPv4' apn: 'internet' slice: sst: 1 sd: 010203注意这里supi格式里IMSI带imsi-前缀,key和opc必须和核心网里给这个用户设置的完全一致,连大小写都得一致。apn字段是和SMF里配置的数据网络名称对应的,Open5GS默认配置的数据网络名是internet,所以这里保持一致就行。
4.3 模拟接入验证信令流程
全部配置完成后,开始模拟接入。先启动gNB:
cd ~/UERANSIM ./build/nr-gnb -c config/open5gs-gnb.yaml看到类似NG Setup procedure is successful的日志,说明gNB已经和核心网AMF建立连接了。这一步如果卡住,多半是IP地址不通,或者SCTP端口被防火墙挡了。
然后启动UE:
./build/nr-ue -c config/open5gs-ue.yamlUE启动后会自动执行注册流程,如果一切正常,你会看到PDU session establishment is successful的日志。到这步说明5G核心网的信令面已经通了:UE成功经过gNB接入AMF,完成鉴权,建立了PDU会话。
验证数据面是否真正打通,在UE模拟器里ping一个外部地址:
./build/nr-cli imsi-001010000000001 --exec "ping 8.8.8.8"如果能ping通,说明UPF的数据转发路径没问题。我实测时在这个环节被卡了很久,现象是注册成功但ping不通,后来排查发现是UPF的NAT配置没开。Open5GS的UPF默认不带NAT转发功能,需要在系统层面开启IP转发并配置iptables规则。如果你和我一样只跑单机实验,可以给UPF所在的主机开启IP转发:
sudo sysctl -w net.ipv4.ip_forward=1 sudo iptables -t nat -A POSTROUTING -s 192.168.20.0/24 -o ens33 -j MASQUERADEens33要替换成你实际的出口网卡名。这样UE分配到的内部IP在访问外网时就会被NAT成宿主机的IP,数据包就能正常出去了。
5. 常见问题与排障技巧
5.1 网元启动失败类问题
这类问题最常见的就是端口被占用。比如AMF启动时报“Cannot bind to port 38412”,说明有残留进程占着端口。可以用ss -lntp | grep 38412查是什么进程占用的,杀掉即可。如果是升级重装的情况,老版本网元可能还在运行,我来回折腾的时候经常遇到这问题,后来养成习惯了,重装前先pkill open5gs。
另一个常见问题是配置文件里写了两个重复的网元地址,比如AMF配置同时出现了addr: 127.0.0.1和addr: 192.168.20.129就会报错。Open5GS不支持同一个网元同时监听多个IP的情况,至少在默认配置下不行。要改,就必须把所有地址字段统一替换。
5.2 终端注册失败类问题
UE注册失败最典型的表现是gNB有日志,但UE一直卡在Requesting registration阶段。这种情况大概率是PLMN不一致。检查AMF配置、UERANSIM gnb配置、UE配置三处的MCC/MNC是否完全一致,只要有一个地方不一样,注册就过不去。
还有一种是鉴权失败。如果日志里出现Authentication failure,说明K/OPc参数不匹配。你可以检查一下核心网里Open5GS订阅数据和UE配置文件里的key、opc是不是完全相同。很多人会在WebUI开户时敲错OPc的某一位十六进制字符,这种错误最隐蔽,我建议用命令行开户加复制粘贴的方式,减少手输错误。
5.3 数据面不通类问题
注册成功后ping不通外网,最常见的几个原因,我已经在4.3节里提到了NAT的问题。另外还要检查UPF的GTP-U隧道是否建立成功,可以用ip tunnel或tcpdump抓包确认GTP-U封装是否正常。如果抓包看到GTP-U报文但外面ping不通,那大概率是路由问题,需要在UPF所在主机加一条路由指向UE网段。
我在历次搭建中总结的经验是,先抓包看信令、再抓包看数据面,在UPF主机上执行:
sudo tcpdump -i any host 192.168.20.131 and port 2152如果看不到任何GTP-U流量,说明UPF的转发规则没下发成功。检查一下SMF和UPF之间的PFCP(包转发控制协议)关联是否正常。PFCP是SMF控制UPF的关键协议,如果PFCP关联断了,UPF就不知道该把数据包转发到哪里去,用户面的隧道自然建立不起来。
排查PFCP关联的常见方法:
- 在SMF上检查PFCP会话,看会话是
ACTIVE还是INACTIVE。 - 抓UPF主机的8805端口,看PFCP心跳报文是否正常。
- 如果PFCP关联频繁中断,检查SMF和UPF之间的N4地址是否互通。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查命令或方法 |
|---|---|---|
| AMF启动报端口占用 | 残留进程未清理 | ss -lntp | grep 38412 |
| UE一直注册中 | PLMN不一致 | 对比三处配置的MCC/MNC |
| 鉴权失败 | K/OPc参数不匹配 | 核对十六进制字符串 |
| gNB连不上AMF | IP不通或防火墙拦截 | ping+ 检查SCTP 38412端口 |
| PDU会话建立失败 | SMF/UPF的PFCP通道问题 | 检查PFCP关联状态 |
| 注册成功但ping不通 | 缺少NAT或路由 | 开启IP转发 + iptables规则 |
| WebUI打不开 | 服务未启动或端口占用 | systemctl status open5gs-webui |
6. 真实联调体会
这套环境我在Ubuntu 22.04上前后装过不下五次,每次踩的坑都不太一样。从最开始纯粹跟着网上教程走,到后来自己梳理整条信令链路,最大的体会是:如果你只是想跑起来,照着命令敲一遍,大概一小时就完事;但如果你想真正理解5G核心网在做什么,还是得把每个网元的职责和接口关系弄清楚,之后出任何问题你都会有排查思路。
还有一个建议,Ubuntu 22.04是目前Open5GS支持比较好的发行版,不建议用更老的版本去实践。我早期在20.04上尝试过一次,MongoDB版本、openssl版本都有各种小问题,浪费时间。如果你本来就打算长期做5G核心网相关实验,可以在一台专用虚拟机上把Open5GS、UERANSIM、WebUI都配好,然后做一次快照。后面不管怎么折腾配置,都能快速回滚到干净状态。
Open5GS官方的文档更新得很快,新版本经常会加一些功能或改一些默认行为,如果你发现某个配置项在你这版里不存在,不用怀疑,查一下对应版本的变更记录,答案都在里面。