06_lab_5g_sa_docker
Part 6: Docker Lab - 5G SA Core with UERANSIM
Learning Objective: Build a working 5G Standalone (SA) core network with Open5GS and simulate gNB/UE with UERANSIM on Docker. Then explore SBI traffic, NF service discovery, network slicing, and NF resilience.
Table of Contents
- Prerequisites
- Lab Architecture
- Docker Network Design
- Step 1: Project Setup
- Step 2: Docker Compose Configuration
- Step 3: Open5GS NF Configurations
- Step 4: UERANSIM Configuration
- Step 5: Launch the Core
- Step 6: Register a Subscriber
- Step 7: Connect gNB and UE
- Step 8: Verify Connectivity
- Packet Capture with tcpdump
- Deep Dive: SBA Service Discovery
- Deep Dive: SBI Traffic Analysis
- Deep Dive: Network Slicing — Add URLLC Slice
- Deep Dive: NF Resilience Testing
- Deep Dive: Metrics and Monitoring
- Troubleshooting
- Summary
Prerequisites
Software
docker --version
# Docker version 24.0.0 or higher
docker compose version
# Docker Compose version v2.20.0 or higher
Disk Space
- ~5GB for Docker images
- ~2GB for logs and data
Docker Images Used
| Component | Image | Source |
|---|---|---|
| MongoDB | mongo:6.0 |
Official MongoDB |
| Open5GS NFs | borieher/open5gs-<nf>:v2.7.6 |
docker-open5gs |
| Open5GS WebUI | borieher/open5gs-webui:v2.7.6 |
docker-open5gs |
| UERANSIM gNB | louisroyer/ueransim-gnb:latest |
louisroyer Docker Hub |
| UERANSIM UE | louisroyer/ueransim-ue:latest |
louisroyer Docker Hub |
Unlike Part 4 (4G EPC) which uses a monolithic gradiant/open5gs image, the 5G SA lab uses per-NF images from borieher/open5gs-<nf>. These images contain only 5G SA network functions (NRF, SCP, AMF, SMF, UPF, AUSF, UDM, UDR, PCF, NSSF, BSF). 4G-specific daemons (MME, HSS, PCRF, SGW-C, SGW-U) are not included in these images.
Lab Architecture
graph TB
subgraph "Docker Host (Mac)"
subgraph "SBI Network (172.22.0.0/24)"
MongoDB[(MongoDB
172.22.0.2)]
WebUI[WebUI
172.22.0.3
:9999]
NRF[NRF
172.22.0.10]
SCP[SCP
172.22.0.11]
AMF[AMF
172.22.0.20]
SMF[SMF
172.22.0.21]
AUSF[AUSF
172.22.0.13]
UDM[UDM
172.22.0.14]
UDR[UDR
172.22.0.15]
PCF[PCF
172.22.0.16]
NSSF[NSSF
172.22.0.17]
BSF[BSF
172.22.0.18]
end
subgraph "RAN Network (172.23.0.0/24)"
UPF[UPF
172.23.0.10]
gNB[UERANSIM gNB
172.23.0.2]
UE[UERANSIM UE
172.23.0.3]
end
end
Internet[Internet
via ogstun]
UE <-->|RRC| gNB
gNB <-->|N2 NGAP| AMF
gNB <-->|N3 GTP-U| UPF
AMF <-->|SBI| NRF
SMF <-->|SBI| NRF
AUSF <-->|SBI| NRF
SMF <-->|N4 PFCP| UPF
UPF <-->|N6 ogstun| Internet
WebUI <-->|HTTP| MongoDB
UDR <-->|MongoDB| MongoDB
style MongoDB fill:#f9f
style WebUI fill:#9ff
style AMF fill:#fcc
style UPF fill:#cfc
style NRF fill:#ff9Docker Network Design
| Network | Subnet | Purpose |
|---|---|---|
| open5gs_sbi | 172.22.0.0/24 | SBI (HTTP/2) between NFs, MongoDB, WebUI |
| open5gs_ran | 172.23.0.0/24 | N2/N3 between AMF/UPF and UERANSIM |
Comparison with 4G EPC (Part 4): The 5G SA core uses SBI (HTTP/2, port 7777) for all inter-NF communication, replacing the Diameter (port 3868) and GTP-C (port 2123) signaling used in 4G. The RAN connects via NGAP (port 38412) instead of S1AP (port 36412).
Step 1: Project Setup
mkdir -p ~/open5gs_5g_lab/{config,ueransim,log}
cd ~/open5gs_5g_lab
Step 2: Docker Compose Configuration
Create docker-compose.yml:
version: '3.8'
services:
# === Infrastructure ===
mongodb:
image: mongo:6.0
container_name: open5gs_mongodb
networks:
open5gs_sbi:
ipv4_address: 172.22.0.2
volumes:
- mongodb_data:/data/db
restart: unless-stopped
webui:
image: borieher/open5gs-webui:v2.7.6
container_name: open5gs_webui
networks:
open5gs_sbi:
ipv4_address: 172.22.0.3
ports:
- "9999:9999"
environment:
- DB_URI=mongodb://172.22.0.2/open5gs
depends_on:
- mongodb
restart: unless-stopped
# === 5G Core NFs ===
nrf:
image: borieher/open5gs-nrf:v2.7.6
container_name: open5gs_nrf
volumes:
- ./config/nrf.yaml:/etc/open5gs/nrf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.10
restart: unless-stopped
scp:
image: borieher/open5gs-scp:v2.7.6
container_name: open5gs_scp
volumes:
- ./config/scp.yaml:/etc/open5gs/scp.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.11
depends_on:
- nrf
restart: unless-stopped
ausf:
image: borieher/open5gs-ausf:v2.7.6
container_name: open5gs_ausf
volumes:
- ./config/ausf.yaml:/etc/open5gs/ausf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.13
depends_on:
- nrf
restart: unless-stopped
udm:
image: borieher/open5gs-udm:v2.7.6
container_name: open5gs_udm
volumes:
- ./config/udm.yaml:/etc/open5gs/udm.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.14
depends_on:
- nrf
restart: unless-stopped
udr:
image: borieher/open5gs-udr:v2.7.6
container_name: open5gs_udr
volumes:
- ./config/udr.yaml:/etc/open5gs/udr.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.15
depends_on:
- mongodb
- nrf
restart: unless-stopped
pcf:
image: borieher/open5gs-pcf:v2.7.6
container_name: open5gs_pcf
volumes:
- ./config/pcf.yaml:/etc/open5gs/pcf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.16
depends_on:
- nrf
restart: unless-stopped
nssf:
image: borieher/open5gs-nssf:v2.7.6
container_name: open5gs_nssf
volumes:
- ./config/nssf.yaml:/etc/open5gs/nssf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.17
depends_on:
- nrf
restart: unless-stopped
bsf:
image: borieher/open5gs-bsf:v2.7.6
container_name: open5gs_bsf
volumes:
- ./config/bsf.yaml:/etc/open5gs/bsf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.18
depends_on:
- nrf
restart: unless-stopped
amf:
image: borieher/open5gs-amf:v2.7.6
container_name: open5gs_amf
volumes:
- ./config/amf.yaml:/etc/open5gs/amf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.20
open5gs_ran:
ipv4_address: 172.23.0.20
depends_on:
- nrf
cap_add:
- NET_ADMIN
restart: unless-stopped
smf:
image: borieher/open5gs-smf:v2.7.6
container_name: open5gs_smf
volumes:
- ./config/smf.yaml:/etc/open5gs/smf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.21
depends_on:
- nrf
restart: unless-stopped
upf:
image: borieher/open5gs-upf:v2.7.6
container_name: open5gs_upf
volumes:
- ./config/upf.yaml:/etc/open5gs/upf.yaml
networks:
open5gs_sbi:
ipv4_address: 172.22.0.30
open5gs_ran:
ipv4_address: 172.23.0.10
cap_add:
- NET_ADMIN
privileged: true
sysctls:
- net.ipv4.ip_forward=1
restart: unless-stopped
# === UERANSIM ===
ueransim_gnb:
image: louisroyer/ueransim-gnb:latest
container_name: ueransim_gnb
volumes:
- ./ueransim/gnb.yaml:/config/gnb.yaml
networks:
open5gs_ran:
ipv4_address: 172.23.0.2
cap_add:
- NET_ADMIN
depends_on:
- amf
- upf
restart: unless-stopped
ueransim_ue:
image: louisroyer/ueransim-ue:latest
container_name: ueransim_ue
volumes:
- ./ueransim/ue.yaml:/config/ue.yaml
networks:
open5gs_ran:
ipv4_address: 172.23.0.3
cap_add:
- NET_ADMIN
privileged: true
depends_on:
- ueransim_gnb
restart: unless-stopped
networks:
open5gs_sbi:
driver: bridge
ipam:
config:
- subnet: 172.22.0.0/24
open5gs_ran:
driver: bridge
ipam:
config:
- subnet: 172.23.0.0/24
volumes:
mongodb_data:
Mac Docker Note: The privileged: true flag on UPF and UE is needed for TUN device creation (ogstun / uesimtun0). On Linux hosts you can use devices: [/dev/net/tun] instead, but Mac Docker Desktop runs containers inside a Linux VM where /dev/net/tun access requires privileged mode.
Step 3: Open5GS NF Configurations
Create each config file in config/:
NRF (config/nrf.yaml)
logger:
level: info
nrf:
serving:
- plmn_id:
mcc: 001
mnc: 01
sbi:
server:
- address: 172.22.0.10
port: 7777
SCP (config/scp.yaml)
logger:
level: info
scp:
sbi:
server:
- address: 172.22.0.11
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
AMF (config/amf.yaml)
logger:
level: info
amf:
sbi:
server:
- address: 172.22.0.20
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
ngap:
server:
- address: 172.23.0.20
guami:
- plmn_id:
mcc: 001
mnc: 01
amf_id:
region: 2
set: 1
tai:
- plmn_id:
mcc: 001
mnc: 01
tac: 1
plmn_support:
- plmn_id:
mcc: 001
mnc: 01
s_nssai:
- sst: 1
security:
integrity_order: [NIA2, NIA1, NIA0]
ciphering_order: [NEA2, NEA1, NEA0]
Notice ciphering_order puts NEA2 first (AES-128). Never put NEA0 (null cipher) first in production — that's the downgrade attack from Part 9.
SMF (config/smf.yaml)
logger:
level: info
smf:
sbi:
server:
- address: 172.22.0.21
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
pfcp:
server:
- address: 172.22.0.21
client:
upf:
- address: 172.22.0.30
subnet:
- addr: 10.45.0.1/16
dnn: internet
dns:
- 8.8.8.8
- 8.8.4.4
UPF (config/upf.yaml)
logger:
level: info
upf:
pfcp:
server:
- address: 172.22.0.30
gtpu:
server:
- address: 172.23.0.10
subnet:
- addr: 10.45.0.1/16
dnn: internet
AUSF (config/ausf.yaml)
logger:
level: info
ausf:
sbi:
server:
- address: 172.22.0.13
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
UDM (config/udm.yaml)
logger:
level: info
udm:
sbi:
server:
- address: 172.22.0.14
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
UDR (config/udr.yaml)
logger:
level: info
udr:
sbi:
server:
- address: 172.22.0.15
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
db_uri: mongodb://172.22.0.2/open5gs
PCF (config/pcf.yaml)
logger:
level: info
pcf:
sbi:
server:
- address: 172.22.0.16
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
db_uri: mongodb://172.22.0.2/open5gs
NSSF (config/nssf.yaml)
logger:
level: info
nssf:
sbi:
server:
- address: 172.22.0.17
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
nsi:
- addr: 172.22.0.20
port: 7777
s_nssai:
sst: 1
BSF (config/bsf.yaml)
logger:
level: info
bsf:
sbi:
server:
- address: 172.22.0.18
port: 7777
client:
nrf:
- uri: http://172.22.0.10:7777
scp:
- uri: http://172.22.0.11:7777
Step 4: UERANSIM Configuration
gNB (ueransim/gnb.yaml)
mcc: '001'
mnc: '01'
nci: '0x000000010'
idLength: 32
tac: 1
linkIp: 172.23.0.2
ngapIp: 172.23.0.2
gtpIp: 172.23.0.2
amfConfigs:
- address: 172.23.0.20
port: 38412
slices:
- sst: 1
ignoreStreamIds: true
UERANSIM gNB connects via NGAP (N2, port 38412) to AMF. This is a 5G SA connection. Compare this to the 4G S1AP interface (port 36412) used in Part 4's EPC lab.
UE (ueransim/ue.yaml)
supi: 'imsi-001010000000001'
mcc: '001'
mnc: '01'
routingIndicator: '0000'
# No SUCI encryption (null scheme for lab)
protectionScheme: 0
homeNetworkPublicKey: ''
homeNetworkPublicKeyId: 1
# Security keys (must match WebUI registration)
key: '465B5CE8B199B49FAA5F0A2EE238A6BC'
op: 'E8ED289DEBA952E4283B54E88E6183CA'
opType: 'OPC'
gnbSearchList:
- 172.23.0.2
sessions:
- type: 'IPv4'
apn: 'internet'
slice:
sst: 1
integrity:
IA1: true
IA2: true
IA3: true
ciphering:
EA1: true
EA2: true
EA3: true
Step 5: Launch the Core
# Start infrastructure first
docker compose up -d mongodb
sleep 3
# Start NRF (service registry must be up before other NFs)
docker compose up -d nrf
sleep 2
# Start all other NFs
docker compose up -d scp ausf udm udr pcf nssf bsf amf smf upf webui
# Verify all containers are running
docker compose ps
Check NRF registrations
docker compose logs nrf | grep -i "registered"
Expected output:
NF registered: AMF (172.22.0.20)
NF registered: SMF (172.22.0.21)
NF registered: AUSF (172.22.0.13)
NF registered: UDM (172.22.0.14)
NF registered: PCF (172.22.0.16)
Step 6: Register a Subscriber
- Open browser: http://localhost:9999
- Login:
- Username:
admin - Password:
1423
- Username:
- Click Subscribers -> + (Add)
- Fill in subscriber details:
- IMSI:
001010000000001 - K:
465B5CE8B199B49FAA5F0A2EE238A6BC - OPc:
E8ED289DEBA952E4283B54E88E6183CA - APN/DNN:
internet - SST:
1
- IMSI:
- Click SAVE
The K/OPc values in the WebUI must exactly match the values in ue.yaml. A single character mismatch causes authentication failure (check AMF logs for MAC failure).
Step 7: Connect gNB and UE
Start gNB:
docker compose up -d ueransim_gnb
docker compose logs -f ueransim_gnb
Expected output:
[sctp] [info] Trying to establish SCTP connection... (172.23.0.20:38412)
[sctp] [info] SCTP connection established
[ngap] [info] NG Setup procedure is successful
Start UE:
docker compose up -d ueransim_ue
docker compose logs -f ueransim_ue
Expected output:
[nas] [info] UE switches to state [MM-REGISTERED/NORMAL-SERVICE]
[nas] [info] PDU Session establishment is successful PSI[1]
[app] [info] Connection setup for PDU session[1] is successful, TUN interface[uesimtun0, 10.45.0.2] is up.
Step 8: Verify Connectivity
Check UE Interface
docker exec -it ueransim_ue ip addr show uesimtun0
Output:
5: uesimtun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1400
inet 10.45.0.2/32 scope global uesimtun0
Ping Test
docker exec -it ueransim_ue ping -I uesimtun0 -c 4 8.8.8.8
Output:
PING 8.8.8.8 (8.8.8.8) from 10.45.0.2 uesimtun0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=12.3 ms
Your 5G SA core is working end-to-end.
Packet Capture with tcpdump
Capture NGAP (N2 Control Plane)
docker exec -it open5gs_amf tcpdump -i any -w /tmp/ngap.pcap sctp
# Copy out: docker cp open5gs_amf:/tmp/ngap.pcap .
Wireshark filter: ngap
Capture GTP-U (N3 User Plane)
docker exec -it open5gs_upf tcpdump -i any -w /tmp/gtpu.pcap udp port 2152
# Copy out: docker cp open5gs_upf:/tmp/gtpu.pcap .
Wireshark filter: gtp
Capture SBI (HTTP/2 between NFs)
docker exec -it open5gs_amf tcpdump -i any -w /tmp/sbi.pcap tcp port 7777
# Copy out: docker cp open5gs_amf:/tmp/sbi.pcap .
Wireshark filter: http2
Deep Dive: SBA Service Discovery
Watch NRF Registrations
# See all NF registrations in real-time
docker compose logs -f nrf 2>&1 | grep -i "register\|profile\|discover"
Query NRF via API
The NRF exposes a REST API. From any container on the SBI network:
# List all registered NFs
docker exec -it open5gs_amf curl -s http://172.22.0.10:7777/nnrf-nfm/v1/nf-instances | python3 -m json.tool
# Discover SMF instances
docker exec -it open5gs_amf curl -s \
"http://172.22.0.10:7777/nnrf-disc/v1/nf-instances?target-nf-type=SMF" | python3 -m json.tool
What You'll See
{
"nfInstances": [
{
"nfInstanceId": "e8c835a4-...",
"nfType": "SMF",
"nfStatus": "REGISTERED",
"ipv4Addresses": ["172.22.0.21"],
"sNssais": [{"sst": 1}],
"nfServices": [
{
"serviceName": "nsmf-pdusession",
"versions": [{"apiVersionInUri": "v1"}],
"scheme": "http"
}
]
}
]
}
This is exactly how AMF discovers SMF during PDU session setup — it queries NRF's Nnrf_NFDiscovery API. In the Part 9 threat model, we discuss how an attacker could poison NRF by registering a rogue NF.
Comparison with 4G: In the 4G EPC (Part 4), there is no NRF. All peer addresses are hardcoded in config files (e.g., MME knows SGW-C's IP directly). SBA service discovery is a 5G SA innovation.
Deep Dive: SBI Traffic Analysis
Capture SBI between AMF and SMF
# Capture HTTP/2 traffic on the SBI network
docker exec -it open5gs_amf tcpdump -i any -w /tmp/sbi_amf.pcap tcp port 7777
# In another terminal, trigger a new PDU session by restarting UE
docker compose restart ueransim_ue
# Wait 10 seconds, then Ctrl+C the tcpdump
# Copy the capture out
docker cp open5gs_amf:/tmp/sbi_amf.pcap .
Wireshark Analysis
Open the pcap in Wireshark and look for:
| Filter | What You'll See |
|---|---|
http2 |
SBI API calls between NFs |
http2 && http2.header.name == ":path" |
API endpoints called |
json |
Request/response payloads |
Key SBI Calls to Find
POST /nsmf-pdusession/v1/sm-contexts <- AMF asks SMF to create session
POST /nudm-sdm/v1/{supi}/sm-data <- SMF asks UDM for subscription data
POST /npcf-smpolicycontrol/v1/sm-policies <- SMF asks PCF for QoS policy
POST /nausf-auth/v1/ue-authentications <- AMF asks AUSF to authenticate UE
Comparison with 4G: In Part 4, you captured Diameter on port 3868 (S6a, Gx) and GTP-C on port 2123 (S11, S5-C). Here, all equivalent signaling flows over SBI HTTP/2 on port 7777. This consolidation is a defining feature of 5G SA's Service Based Architecture.
Deep Dive: Network Slicing — Add URLLC Slice
Step 1: Update AMF Config
Add SST=2 to the plmn_support in config/amf.yaml:
plmn_support:
- plmn_id:
mcc: 001
mnc: 01
s_nssai:
- sst: 1 # eMBB (existing)
- sst: 2 # URLLC (new)
Step 2: Update SMF Config
Add a second subnet for the URLLC slice in config/smf.yaml:
subnet:
- addr: 10.45.0.1/16
dnn: internet
s_nssai:
sst: 1
- addr: 10.46.0.1/16
dnn: iot
s_nssai:
sst: 2
Step 3: Update UPF Config
Add the second subnet in config/upf.yaml:
subnet:
- addr: 10.45.0.1/16
dnn: internet
- addr: 10.46.0.1/16
dnn: iot
Step 4: Add Second UE for URLLC
Create ueransim/ue_urllc.yaml:
supi: 'imsi-001010000000002'
mcc: '001'
mnc: '01'
routingIndicator: '0000'
protectionScheme: 0
homeNetworkPublicKey: ''
homeNetworkPublicKeyId: 1
key: '465B5CE8B199B49FAA5F0A2EE238A6BC'
op: 'E8ED289DEBA952E4283B54E88E6183CA'
opType: 'OPC'
gnbSearchList:
- 172.23.0.2
sessions:
- type: 'IPv4'
apn: 'iot'
slice:
sst: 2 # URLLC slice
integrity:
IA1: true
IA2: true
IA3: true
ciphering:
EA1: true
EA2: true
EA3: true
Step 5: Register URLLC Subscriber
In WebUI (http://localhost:9999):
- IMSI:
001010000000002 - K:
465B5CE8B199B49FAA5F0A2EE238A6BC - OPc:
E8ED289DEBA952E4283B54E88E6183CA - DNN:
iot - SST:
2
Step 6: Verify Slice Assignment
docker compose logs ueransim_ue_urllc | grep -i "slice\|sst\|pdu"
Expected: UE gets IP from 10.46.0.0/16 range (URLLC slice), not 10.45.0.0/16 (eMBB slice).
4G Comparison: Network slicing is a 5G SA-only feature. It requires NSSF, AMF, and SMF working together via SBA. The 4G EPC (Part 4) has no slice awareness — the MME does not support S-NSSAI selection.
Deep Dive: NF Resilience Testing
Kill a Critical NF
# Kill the SMF
docker compose stop smf
# Try to start a new PDU session (restart UE)
docker compose restart ueransim_ue
# Check UE logs — PDU session should fail
docker compose logs ueransim_ue | tail -10
# Restart SMF
docker compose start smf
# UE should recover on retry
docker compose restart ueransim_ue
Kill the NRF
# Kill NRF — what happens to existing sessions?
docker compose stop nrf
# Answer: Existing sessions continue (NFs already have each other's addresses)
# But NEW sessions fail (NFs can't discover each other)
# Verify: existing UE still pings fine
docker exec -it ueransim_ue ping -I uesimtun0 -c 2 8.8.8.8
# Restart NRF
docker compose start nrf
This demonstrates why NRF is the heart of SBA. Losing NRF doesn't kill existing sessions (NFs cache discovery results), but prevents new sessions from being established. In production, NRF must be highly available.
Deep Dive: Metrics and Monitoring
Check Open5GS Metrics
If your NF configs include a metrics section:
metrics:
server:
- address: 172.22.0.20
port: 9090
You can scrape Prometheus metrics:
docker exec -it open5gs_amf curl -s http://172.22.0.20:9090/metrics | head -30
Look for:
amf_session_total— number of active sessionsamf_registration_total— number of registered UEs
Troubleshooting
NFs Cannot Register with NRF
docker compose logs nrf | tail -20
docker compose logs amf | grep -i "error\|failed"
Common causes:
- NRF not started before other NFs -> restart NFs after NRF is up
- Wrong NRF URI in config -> verify
http://172.22.0.10:7777
UE Cannot Authenticate
docker compose logs amf | grep -i "mac\|auth\|fail"
Common causes:
- K/OPc mismatch between WebUI and ue.yaml
- IMSI not registered -> check WebUI subscriber list
- PLMN mismatch (MCC/MNC)
No Internet from UE
# Check UPF TUN interface
docker exec -it open5gs_upf ip addr show ogstun
# Check UPF routing
docker exec -it open5gs_upf ip route
# Check NAT
docker exec -it open5gs_upf iptables -t nat -L
Fix: UPF needs NAT for outbound traffic:
docker exec -it open5gs_upf iptables -t nat -A POSTROUTING \
-s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
Cleanup
docker compose down -v # -v removes volumes (subscriber data)
Exercises
- Multi-UE: Add a second UE (
imsi-001010000000002) with different security keys. Register it in the WebUI and modifydocker-compose.ymlto addueransim_ue2. - IP Pool: Change UPF/SMF subnet from
10.45.0.0/16to10.50.0.0/16. What do you need to update? - Wireshark Analysis: Capture NGAP traffic and find the
InitialUEMessage. What identifiers can you see? Is SUPI visible? (Hint: checkprotectionSchemein ue.yaml) - DNS Test: From the UE, run
docker exec ueransim_ue nslookup google.com 8.8.8.8through the tunnel. - NRF Discovery: Capture SBI traffic on port 7777 and observe how AMF discovers SMF via NRF during PDU session setup.
- 4G vs 5G Comparison: Compare the protocol captures from Part 4 (Diameter S6a, GTP-C S11) with the SBI HTTP/2 captures from this lab. List three specific differences in how authentication and session management work.
Summary
You have successfully:
- Deployed a full 5G SA core with all NFs (NRF, SCP, AMF, SMF, UPF, AUSF, UDM, UDR, PCF, NSSF, BSF)
- Configured NRF-based service discovery (SBA)
- Registered a subscriber via WebUI
- Connected UERANSIM gNB via NGAP (N2) and UE
- Established a PDU session and verified Internet connectivity
- Captured packets on N2, N3, and SBI interfaces
- Queried NRF API to observe SBA service discovery
- Analyzed SBI HTTP/2 traffic in Wireshark
- Configured multi-slice network (eMBB + URLLC)
- Tested NF resilience (SMF kill/recover, NRF failover)
- Explored Open5GS Prometheus metrics
Next: Part 7: Kubernetes Deployment ->