Category Archives: Mobile Networks

GSM MSC Architecture

GSM with Osmocom Part 8: The Mobile Switching Center

We’re nearing the end of our “setup” story – So far we’ve covered the access network (BTS & BSC) and our subscriber database (The HLR) so now let’s talk about one of the key “Core” elements of the network – the Mobile Switching Center (MSC).

The MSC’s name kind of says it all, it’s a switching center for mobiles.

The MSC handles switching of voice calls and SMS/text messages between local & remote subscribers and networks.

Switching Function

Because GSM was designed to be voice centric (Keep in mind the first GSM network went live in 1991) the MSC’s primary function is switching phone calls between subscribers.* For this the MSC has to keep track of which subscribers it’s currently serving, their capabilities and how to reach them -which BSC they’re being served by and therefore which BTS they’re being served by.

The OsmoMSC also features a minimalistic SMSC (Short Message Service Server) for routing SMS traffic between subscribers on the network.
This basic SMSC acts in a store-and-forward fashion. Production networks would typically use an external SMSC for handling SMS, OsmoMSC has the SMSC functionality built in by default, but the interfaces are there if you wanted to use an external SMSC.

Any calls/texts to subscribers/destinations outside the MSC (for example a call to a mobile subscribers on a different carrier or on the PSTN) are typically routed to another MSC known as the Gateway MSC.
The GMSC handles the interconnection with other networks. We’ll touch upon this later with the SIP connector, but for now we’ll focus just on on-net calls between subscribers.

It’s worth noting that the MSC does not sit in the media stream, it just sets up and tears down the calls, we’ll cover more on the nitty-gritty of calling in GSM soon.

Visitor Location Register Function

The MSC also acts as the interface to the HLR for AAA, as we covered in our last post, the HLR provides the authentication role and also provides the subscriber data to the MSC. Subscriber data is copied from the HLR to the internal HLR cache on the MSC known as the Visitor Location Register (VLR) after a subscriber attaches.

Authentication, Ciphering and EIR Queries

In the last post we talked about the role of the HLR in terms of Authentication on the network, the authentication vectors but the policies that enforce this are set on the MSC.

The MSC queries the admission control info from the HLR, but it’s the MSC that’s responsible for enforcing these rules.

Core Network Identity

The MCC (Mobile Country Code) and MNC (Mobile Network Code) of the network (Together the MCC + MNC are referred to as the PLMN ID), along with the network name, are configured on the MSC.

While this may seem like a rather small detail, the PLMN ID is analogous to the SSID of a WiFi network – it’s what identifies your network out of all the others on the air, and the network name shows up on your phone when you’re connected showing your network name.

Setup & Connections

The BSC we setup earlier communicates with the MSC via SS7 Point Codes. We’ll go into how point codes route requests in a later post, but so long as you’re running Osmo-BSC, Osmo-MGW, Omso-MSC and Osmo-HLR on the same machine you won’t need to link them to each other like we had to do with adding our BTS to the BSC.

Instead we’ll just need to start everything required:

systemctl restart osmo-stp
systemctl restart osmo-hlr
systemctl restart osmo-mgw
systemctl restart osmo-msc

The GSUP connection between the MSC and the HLR will be established at startup, but BSCs will only establish a connection to the MSC when they need something from the MSC.

Once we’ve got everything started we can Telnet into the MSC to confirm it’s running and check it’s status:

root@gsm # telnet localhost 4254

Assuming you can connect that’s another network element online. – We’ll leave the default the Point Codes in place so the BSC will be able to connect to the MSC, but keep in mind that the BSC will only establish a connection when it needs something from the MSC.

Follow Up

There’s a few topics we skipped over in this topic, stuff like SS7/SIGTRAN, how real world GSM calls route using MNCC-SAP, the Media Gateway and anchoring media streams and what an SMSC does.

I’ll do posts covering each of these topics in more depth.

OsmoHLR - Update Location Request

GSM with Osmocom Part 7: The HLR – Home Location Register (and Friends)

The Home Location Register serves the AAA functions in a GSM / UMTS (2G/3G) network as well as locating which Mobile Switching Center (MSC) a subscriber is being served by.

The HLR is the equivalent of the Home Subscriber Server in LTE (I’ve written a fair bit about the role of the HSS in LTE networks, and I’ve published my own open-source HSS software.)

Authentication

One obvious need is to authenticate our subscribers so the network can verify their identity,

The IMSI (International Mobile Subscriber Identity) is used to identifier the user from all the other mobile subscribers worldwide. The IMSI is exposed to the user, but transmitting the IMSI in the clear is typically something that’s avoided where possible on the air interface.

GSM uses a single shared secret between the SIM and the network (the K key) for authentication. This shared secret is not exposed to the user and is never transmitted over the air.

When a user wants to authenticate, the HSS network takes a Random key (RAND) and mixes it with the secret key (K) to generate a Signed Response called SRES. The network sends the RAND key to the subscriber, and their SIM takes the secret key (K) and mixes it with the RAND value from the network, before sending their signed response (SRES) back to the network.
If the SRES sent by the subscriber matches the SRES generated by the HSS, then the user is authenticated. The set of keys used for one authentication session is referred to as an Authentication Vector or Authentication Tuple.

In Osmocom the generation of Authentication Tuples is requested in the GSUP “SendAuthInfo” request, and responded to by the “SendAuthInfoResponse” sent to the HLR by the MSC.

Side note about GSM Security

In a GSM setting the network only authenticates the subscribers, the subscribers don’t authenticate the network. In practice, this means there’s no way to verify in GSM if the network you’re connected to is the network it’s claiming to be.

Due to this shortfall and the cryptographic weakness in A5/x algorithm, 3GPP specified the AKA algorithm for mutual network authentication in 3G/UMTS networks.

I’ve written a fair bit about the role of SIMs for authentication in LTE which is the same scheme used in 3G/UMTS if you’d like to learn more.

LTE USIM Authentication - Mutual Authentication of the Network and Subscriber

Technically the generation of Authentication Vectors is handled by an Authentication Center (AuC) however OsomoHLR has an internal AuC that handles this internally.

Location Tracking

After a user has authenticated, the MSC sends an UpdateLocationRequest via GSUP to the HLR to let it know the current location of the subscriber is served by that MSC.

The Update Location Request is sent at the start of the session, periodic Update Location Requests can be sent based on the timers configured, and a Cancel Location Request can be sent when the subscriber disconnects from the MSC.

Subscriber Data Information

When the Update Location Request has been sent by the MSC, the HLR sends the MSC the subscriber’s info, and the MSC copies it to it’s own internal HLR called a Visitor Location Register (VLR). The VLR means the MSC doesn’t need to keep querying user data from the HLR.

This is again requseted by the MSC to the HLR via a GSUP request InsertSubscriberData Request which contains:

  • Subscriber’s IMSI
  • Subscriber’s MSISDN (Phone number)
  • Allowed Domains (CS/PS)

Note: In production GSM networks TCAP/MAP is used for communication between the HLR and the MSC. Osmocom uses GSUP for carrying this data instead.

Equipment Identity Register

Because mobiles are expensive they’ve historically been a target for theft.

To try and mitigate this GSMA encourages carriers to implement an Equipment Identity Register (EIR).

The EIR is essentially a database containing IMEIs (The Identifiers of Mobiles / Terminals) and permitting / denying access to the network based on the IMEI.

The idea being if a mobile device / terminal is stolen, it’s IMEI is blacklisted in the EIR and regardless of what SIM is put into it, it’s not permitted to access the network.

When a device connects to the network if configured the MSC will query the EIR (On the HLR in our case) with a Check IMEI Request, and will get a Check IMEI Result either permitting or denying access to the network.

Unfortunately, there is no global stolen IMEI database, meaning if a device is stolen and blocked on MNO X’s network, it may still work on MNO Y’s network if they don’t share stolen IMEI data.

Starting & Configuring OsmoHLR

We actually installed OmsoHLR in the post on Base Station Controllers, so we’ll just need to start the daemon / service:

systemctl start osmo-hlr

I’m going to enable the EIR functionality of the HSS by changing the config of the HLR, this is optional but it’s useful to use the EIR functionality.

Like with our other network elements we’ll use Tenet to interactively configure this one,

root@gsm-bts:/home/nick# telnet localhost 4258
Welcome to the OsmoHLR VTY interface
OsmoHLR> enable
OsmoHLR# configure terminal
OsmoHLR(config)# hlr
OsmoHLR(config-hlr)# store-imei
OsmoHLR(config-hlr)# exit
OsmoHLR(config)# exit
OsmoHLR# copy running-config startup-config

Adding Subscribers to OsmoHLR

But before we go adding subscribers, let’s talk about SIMs.

Okay, I’ve written a lot about SIMs before, but there’s still more to talk about!

There’s really only one peice of information from your SIM we require to add the subscriber to the HLR, and that’s the IMSI – The unique identifier of the subscriber on the SIM. You can typically view the IMSI from your mobile device / terminal.

If you want to authenticate subscribers properly (confirm their identity) and enable encryption on the air interface, you’ll need to know the K key of the SIM, for that you’ll need a programmable SIM card like the Sysmocom programmable SIM cards, (By buying from Sysmocom you’re supporting the Osmocom project too).

So now we’ve got that out of the way, let’s add a subscriber:

We’ll connect to OsmoHLR via Telnet, the port it listens on is 4258:

root@gsm-bts:/home/nick# telnet localhost 4258
Welcome to the OsmoHLR VTY interface
OsmoHLR> enable
OsmoHLR# subscriber imsi 001010000000004 create
OsmoHLR# subscriber imsi 001010000000004 update msisdn 61412341234
OsmoHLR# subscriber imsi 001010000000004 update aud2g comp128v3 ki 465B5CE8B199B49FAA5F0A2EE238A6BC

So I’ve created a subscriber with IMSI 001010000000004 in the HSS and assigned an MSISDN (phone number).

Optionally, if you’re using SIM cards you can program you can set the Ki / K key for authentication using the update aud2g function, if not you can skip that step.

And with that we’ve added our first subscriber, lather rinse repeat with any additional subscribers / SIMs you want to provision.

By default subscribers created using this method have access to both Circuit Switched (Voice and SMS) and Packet Switched (Data) networks. (We haven’t configured Packet Switched services yet)

If you’d like to restrict access to one, both or none of the above options, you can do that by using the subscriber update command to set the services available to those subscribers.

OsmoHLR# subscriber id 3 update network-access-mode cs+ps
OsmoHLR# subscriber id 3 update network-access-mode cs
OsmoHLR# subscriber id 3 update network-access-mode ps
OsmoHLR# subscriber id 3 update network-access-mode none

Creating Subscribers Programmatically

In reality if you’re trying to operate a network it’s not feasible to manually add each subscriber as needed.

If you’re buying SIMs in bulk preconfigured you’ll get sent a file containing the IMSI and Crypto values of each card, and you’d ingest that into your HLR.

We’ve used the Osmocom VTY / Telnet interface in quite a few posts now (hopefully you’re getting comfortable with it) but there’s another interface most Osmocom software has – the Osmocom Control Interface – aimed at providing a uniform way to interface external scripts / programs with Osmocom.

If you’d like to learn more about the Control Interface have a read of the OsmoHLR manual and take a look at this example in Python.

Creating Subscribers on Demand (Optional)

For most scenarios you would pre-provision each SIM in the HLR, if the SIM’s IMSI isn’t in the HLR then it’s access is rejected. However there are some scenarios where you may want to allow anyone to access the network, in this scenario Osmo-HLR features a “Create Subscribers on Demand” function.

This may be useful if you’re setting up a network where you don’t control the SIMs for example.

Let’s say we want to automatically create users with access to voice & data services and assign a 10 digit MSISDN for that subscriber, we can do that with:

OsmoHLR> enable
OsmoHLR# configure terminal
OsmoHLR(config)# hlr
OsmoHLR(config-hlr)# subscriber-create-on-demand 10 cs+ps

Alternatley you may wish to simply add the subscriber to the HLR but not provide any services:

OsmoHLR> enable
OsmoHLR# configure terminal
OsmoHLR(config)# hlr
OsmoHLR(config-hlr)# subscriber-create-on-demand no-msisdn none

Then if you wish to grant access to these users you can use the subscriber update network-access-mode method we talked about earlier to allow services for that user.

Packet Capture

To give some context I’ve attached a packet capture of the connection from the MSC to the HLR for some attach procedures on my lab network.

GSM with Osmocom Part 6: Integrating our LimeSDR BTS with OsmoBSC

In the last post we covered the config required to provision a new BTS in our BSC.

We’re going to do roughly the same thing this time around, as we connect our SDR based BTS to our BSC.

Before we fire up the BTS side of things make sure you’ve stopped the virtual BTS and disabled it.

systemctl stop osmo-bts-virtual
systemctl disable osmo-bts-virtual

Configure Osmo-BTS-TRX

Next up we’ll edit the config of osmo-bts-trx.

vi /etc/osmocom/osmo-bts-trx.cfg

We’ll edit the oml remote-ip to the IP of the server running your BSC, if you’re running on on the same machine you can leave it as localhost (127.0.0.1).

Next up we’ll set the Unit-ID of the BTS, this identifies the BTS inside the BSC,

I’ll set it to unit-id 1234 by changing ipa unit-id 1234 0

Finally we’ll change the logging config to show everything by changing it to:

log stderr
 logging filter all 1
!

Next up we’ll configure the BTS on the BSC

BSC Provisioning

This is essentially a copy of the provisioning process we followed in the last post, the only difference is we’ll use BTS 2 (as BTS 1 is setup for our Virtual BTS) in the config, and set the few different identifier such as the ipa unit id for the SDR based BTS.

telnet localhost 4242
OsmoBSC> enable
OsmoBSC# configure terminal
OsmoBSC(config)# network
OsmoBSC(config-net)# bts 2
OsmoBSC(config-net-bts)# type sysmobts
OsmoBSC(config-net-bts)# description "LimeSDR Based BTS"
OsmoBSC(config-net-bts)# ipa unit-id 1234 0
OsmoBSC(config-net-bts)# band DCS1800
OsmoBSC(config-net-bts)# codec-support fr hr efr amr
OsmoBSC(config-net-bts)# cell_identity 1234
OsmoBSC(config-net-bts)# location_area_code 1234
OsmoBSC(config-net-bts)# base_station_id_code 1234
OsmoBSC(config-net-bts)# base_station_id_code 12
OsmoBSC(config-net-bts)# ms max power 40
OsmoBSC(config-net-bts)# trx 0
OsmoBSC(config-net-bts-trx)# max_power_red 20
OsmoBSC(config-net-bts-trx)# arfcn 876
OsmoBSC(config-net-bts-trx)# timeslot 0
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config CCCH+SDCCH4
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 1
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 2
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 3
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 4
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 5
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 6
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 7
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit 
OsmoBSC(config-net-bts-trx)# exit
OsmoBSC(config-net-bts)# exit
OsmoBSC(config-net)# exit
OsmoBSC(config)# exit 
OsmoBSC# copy running-config startup-config 

Starting the SDR based BTS

Before we start the SDR based BTS it’s probably best to have 3 terminals open,

One logged into Osmo-BSC with logging enabled (see the last post for info on how to do that).

We’ll start another terminal for running the TRX modem / Layer 1 interface:

osmo-trx-lms -C /etc/osmocom/osmo-trx-lms.cfg

And in another new terminal we’ll start the BTS side;

osmo-bts-trx -c /etc/osmocom/osmo-bts-trx.cfg

All going well our terminal with Osmo-BSC should report the connection:

OsmoBSC#
<0016> input/ipa.c:287 0.0.0.0:3003 accept()ed new link from 10.0.1.252:39595
<0003> osmo_bsc_main.c:291 bootstrapping RSL for BTS/TRX (2/0) on ARFCN 875 using MCC-MNC 001-01 LAC=1234 CID=1234 BSIC=12

And the osmo-trx-lms and osmo-bts-trx windows should have data flying by at a rate of knots.

Verifying Cell Operation

If all is going to plan, our SDR is connected to our machine via osmo-trx-lms which is acting as a modem for osmo-bts-trx which is now connected to the BSC. Lot to go through, but it gets easier from here.

Let’s run a scan of the networks on our phone. I found putting mine on GSM only before scanning for networks meant it popped up a heck of a lot faster.

And lo, there it is.

Our cell is online and broadcasting it’s info. You won’t be able to connect to it at this stage as we’ve still got a few more steps to go.

In the next post we’ll introduce the Home Location Register and then the MSC.

GSM with Osmocom Part 5: Software BTS with LimeSDR & osmo-bts-trx

Osmo-BSC accepts Abis over IP connections from a number of different sources,

There’s a list of supported BTS hardware that can talk out of the box to the Osmo-BSC, such as the Ericsson RBS series, ip.access nanoBTS, Nokia and Siemens units and even a virtual BTS so you can simulate the connections.

If you’re using any of these premade BTS hardware options, or osmo-bts-virtual, you probably just need to setup the basics on your BTS and point it to your BSC, end of story.

The below post will touch on using common SDR hardware to act as our BTS. If you’re not using SDR hardware you can just skip ahead to the next post on BSCs.

But, if you’re in the same boat as me, without any commercial BTS / RAN hardware, we’ll be setting it up by using an SDR platforms (In my case LimeSDR) and that’s what this tutorial will focus on.

Osmo-TRX

In order to bring in a large array of SDR hardware, Osmocom have introduced Osmo-TRX, which handles the Layer 1 physical layer of the BTS, and connects to Osmo-BTS which serves as the BTS and talks Abis over IP to the MSC.

Certain hardware can talk directly to Osmo-BTS, but we’re going to rely on Osmo-TRX to act as the middleman between our SDR hardware and the BTS.

The above diagram from the Osmocom wiki shows how this fits together with generic SDR platforms, here’s how it fits together for us:

osmo-trx-lms will take care of the SDR side of the equation, pretty much serving as a modem and sending everything it gets on the Uu interface to osmo-bts-trx over UDP, and everything it receives from osmo-bts-trx over UDP it sends out the Uu interface.

osmo-bts-trx will then setup an Abis over IP connection to our BSC.

The LimeSDR

My ever growing collection of SDR hardware now includes a LimeSDR which I’ll be using for this series.

Before we can get too far we’ve got to setup the prerequisites for the LimeSDR to be able to interface with Osmo-TRX.

Osmocom now provide a binary for interfacing with LimeSDR boards directly, instead of having to use the UHD abstraction. This is a much cleaner way of interfacing with the boards and the path I’ll be taking.

Software Install

For this tutorial series I’ll be using Ubuntu 18.04 and trying where possible to use packages from Repos instead of compiling from source.

LimeSuite provides the drives and utilities for interfacing with the LimeSDR.

add-apt-repository -y ppa:myriadrf/drivers
apt-get update
apt-get install limesuite limesuite-udev

Next we’ll connect up the LimeSDR to a USB3 port, confirm it’s there and upgrade it’s firmware:

 LimeUtil --find

Assuming your LimeSDR is hooked up and everything installed you should see an output similar to this:

In which case we can upgrade the LimeSDR firmware with:

LimeUtil --update  

Next we’ll start installing Osmocom Sources;

wget https://download.opensuse.org/repositories/network:/osmocom:/latest/Debian_10/Release.key  
apt-key add Release.key && rm Release.key
echo "deb https://download.opensuse.org/repositories/network:/osmocom:/latest/xUbuntu_18.04/ ./" > /etc/apt/sources.list.d/osmocom-latest.list 
apt-get update

Now that we’ve got the Osmocom Debian repos added we can install the packages we need,

We’re going to install Osmo-BTS-TRX for talking to the BSC over Abis, and install Osmo-TRX-LMS for talking to the SDR.

apt-get install osmo-bts-trx osmo-trx-lms

After you’ve installed the packages, Osmo-BTS-TRX will run as a daemon, we’ll stop it for now and bring it up manually in the foreground.

systemctl disable osmo-bts-trx
systemctl disable osmo-trx-bts

Software Config

So now we’ve got two pieces of the puzzle, it’s time to connect the SDR to Osmo-TRX-LMS and connect Osmo-TRX-LMS to Osmo-BTS-TRX.

We’ll begin by running Osmo-TRX-LMS to connect to the LimeSDR and encapsulate the Uu data into UDP packets we send to Osmo-BTS-TRX.

Config files for Osmocom are installed in /etc/osmocom/ so we’ll run everything from that directory.

osmo-trx-lms -C osmo-trx-lms.cfg

If all was successful you’ll see something similar to what I’ve got below, showing Osmo-TRX-LMS has connected to the SDR and is ready to go.

But if you go scanning the airwaves now, you won’t see any data coming out of the SDR’s transmitter.

That’s because Osmo-TRX-LMS needs to connect to Osmo-BTS-TRX,

We’ll leave Osmo-TRX-LMS running, so let’s open up another session and start Osmo-BTS-TRX.

osmo-bts-trx -c osmo-bts-trx.cfg

You’ll see for starters that it’s Opened our transceiver (hooray),

You’ll see this reflected in the Osmo-TRX-LMS stdout, but it’ll show the poweroff command has been sent to it, so what gives?

Well, the answer becomes clear if you leave Osmo-BTS-TRX running for a minute or two,

Eventually the process stops, reporting:

<000d> abis.c:142 Signalling link down
<0001> bts.c:292 Shutting down BTS 0, Reason Abis close

So what’s going on? In the same way we saw our Virtual BTS shut itself down, without a connection to the BSC (Via the Abis interface) the BTS will shut itself down, as it’s not able to run on it’s own.

This took me a shamefully long time to work out that’s why it was stopping…

In our next post we’ll introduce our BSC and provision a BTS on it.

Further Reading:

OsmoTRX – Osmocom Wiki

OsmoBTS – OsmocomWiki

LimeSDR – Osmocom Wiki

GSM with Osmocom Part 4: The Base Station Controller (BSC)

So in our last post we finished setting up a Base Transceiver Station (BTS) but it’s no use unless it can home itself to a Base Station Controller (BSC).

So what does a BSC do?

The BSC acts as a central controller for one or more BTS.

In practice this means the BSC configures most of the parameters on the BTS and brings each one up onto the air when they’re ready.

The BSC monitors measurements from users to work out when to hand off from one BTS to neighboring BTS,

The BSC also handles the allocation of radio channels and radio resources across the BTSs it manages.

In short, it does pretty much everything radio related for the BTS except transmitting and receiving data over the Air (Um) interface.

As well as managing the BTS under it, the other other equally important role of the BSC is to provide connectivity to the rest of the GSM network, by connecting to a Mobile Switching Center (MSC) which handles calls to and from our mobile subscribers and authenticating them.

By acting as a funnel of sorts, the MSC only needs a connection to each BSC instead of to each BTS (Which would be an impractically large number of connections)

Osmo BSC Install

Osmocom have their own BSC – Aptly called Osmo-BSC.

Installation is pretty straightforward, assuage you’ve got the Osmocom repo in your sources list:

apt-get install osmo-bsc 
systemctl stop osmo-bsc

In order to serve the BTSs it controls, Osmo-BSC relies on connectivity to a Mobile Switching Center (MSC), which in turn connects to a HLR (Home Location Register). The BSC and MSC communicate via SS7, and the routing is done by a Signal Transfer Points (STP).

We’ll go into each of these elements in more detail, but in order to bring our BSC up in a useful way, we’ll need to install and start these applications.

We’ll talk about the MSC, the basics of SS7 / Sigtran and the HLR later in the series, but for now we’ll blindly install and start them:

apt-get install osmo-stp osmo-msc osmo-hlr
systemctl start osmo-stp
systemctl start osmo-msc
systemctl start osmo-hlr

We’ll come back and cover each of these elements in more detail in due course.

Osmo Config – Telnet Interactive Terminal

So now we’ve got the BSC installed we’ve pointed our BTS at the IP of the BSC, we’ll need to get osmo-bsc running and add the config for our new BTS.

Instead of working with the text file we’ll start the service and work on it through Telnet, like we would for many common network devices.

Osmo-BSC listens on port 4242, so we’ll start Osmo-BSC and connect to it via Telnet:

systemctl start osmo-bsc
telnet localhost 4242

The interface should come pretty naturally to anyone who’s spent much time setting up other network devices, a lot of the commands are similar and yes – tab completion is a thing!

We’ll start by enabling logging so we can get an idea of what’s going on:

OsmoBSC> enable
OsmoBSC# logging enable
OsmoBSC# logging filter all 1
OsmoBSC# logging color 1

Next up in a new terminal / SSH session, we’ll run our virtual BTS again;

 osmo-bts-virtual -c osmo-bts-virtual.cfg 

This time we’ll get a different output from the BTS when we try to start it:

root@gsm-bts:/etc/osmocom# osmo-bts-virtual -c osmo-bts-virtual.cfg
 ((*))
   |
  / \ OsmoBTS
<0010> telnet_interface.c:104 Available via telnet 127.0.0.1 4241
<0012> input/ipaccess.c:901 enabling ipaccess BTS mode, OML connecting to 127.0.0.1:3002
<0012> input/ipa.c:128 127.0.0.1:3002 connection done
<0012> input/ipaccess.c:724 received ID_GET for unit ID 4242/0/0
<0012> input/ipa.c:63 127.0.0.1:3002 lost connection with server
<000d> abis.c:142 Signalling link down
<000d> abis.c:156 OML link was closed early within 0 seconds. If this situation persists, please check your BTS and BSC configuration files for errors. A common error is a mismatch between unit_id configuration parameters of BTS and BSC.

root@gsm-bts:/etc/osmocom#

We’ll also see errors in the terminal on the BSC too:

<0016> input/ipa.c:287 0.0.0.0:3002 accept()ed new link from 10.0.1.252:39383
<0016> bts_ipaccess_nanobts.c:480 Unable to find BTS configuration for 4242/0/0, disconnecting

So what’s happening here?

Well our virtual BTS is trying to connect to our BSC, and this time it’s able to, but our BSC doesn’t have any config in place for that BTS, so the BSC has rejected the connection.

So now we’ve got to configure a the BSC to recognise our BTS.

Provisioning a new BTS in the BSC

So as to keep this tutorial generic enough for anyone to follow along, we’re first going to configure a virtual BTS in our BSC to begin with. I wrote about installing Osmo-BTS-Virtual in this post.

We can get the information about the rejected BTS connection attempt from the BSC terminal:

OsmoBSC# show rejected-bts
 Date                Site ID BTS ID IP
2020-03-29 01:32:37    4242      0      10.0.1.252

So we know the Site-ID is 4242 (we set it earlier) and the BTS ID for that site is 0, so let’s create a BTS in the BSC;

OsmoBSC> enable
OsmoBSC# configure terminal
OsmoBSC(config)# network
OsmoBSC(config-net)# bts 1
OsmoBSC(config-net-bts)# type sysmobts
OsmoBSC(config-net-bts)# description "Virtual BTS"
OsmoBSC(config-net-bts)# ipa unit-id 4242 0
OsmoBSC(config-net-bts)# band DCS1800 
OsmoBSC(config-net-bts)# codec-support fr hr efr amr
OsmoBSC(config-net-bts)# cell_identity 4242
OsmoBSC(config-net-bts)# location_area_code 4242
OsmoBSC(config-net-bts)# base_station_id_code 4242
OsmoBSC(config-net-bts)# base_station_id_code 42
OsmoBSC(config-net-bts)# ms max power 40
OsmoBSC(config-net-bts)# trx 0
OsmoBSC(config-net-bts-trx)# max_power_red 20
OsmoBSC(config-net-bts-trx)# arfcn 875
OsmoBSC(config-net-bts-trx)# timeslot 0
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config CCCH+SDCCH4
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 1
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 2
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 3
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 4
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 5
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 6
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit
OsmoBSC(config-net-bts-trx)# timeslot 7
OsmoBSC(config-net-bts-trx-ts)# phys_chan_config TCH/F
OsmoBSC(config-net-bts-trx-ts)# exit 
OsmoBSC(config-net-bts-trx)# exit
OsmoBSC(config-net-bts)# exit
OsmoBSC(config-net)# exit
OsmoBSC(config)# exit 
OsmoBSC# copy running-config startup-config

Phew,

So what did we actually do here?

Well as we’re getting the majority of the smarts for the BTS from the BSC, we’ve got to tell the BSC all about how we want the BTS setup. (Believe it or not this is the most abridged setup I could muster.)

The type, IPA Unit ID, band and Cell Identity make up some of the parameters we need to identify the BTS (IPA Unit ID) and give it it’s basic identity parameters.

Next up in the trx 0 section we set the contents of the 8 GSM timeslots. Our first time slot we configure as CCCH+SDCCH4 meaning the first timeslot will contain the Common Control Channel and 4 Standalone dedicated control channels, used for signalling, while the reamining 7 timeslots will be used with traffic channels for full-rate speech (TCH/F).

It’s important that what we tell the BSC the capabilities of the BTS are match the actual capabilities of the BTS. For example there’s no point configuring GPRS or EDGE support on the BSC if the BTS doesn’t support it.

If you’ve got logging enabled when the BTS connects to the BSC you’ll see errors listing the features mismatch between the two.

As you can imagine there’s better options than this for adding BTS in bulk – Osmocom Control Interface exposes these functions in an API like way, but before you start on network orchestration it’s good to know the basics.

Connecting the BTS to the BSC

So let’s go ahead and connect our BTS to the BSC.

If you’ve closed the BSC terminal since we enabled logging you’ll need to enable it again:

OsmoBSC> logging enable
OsmoBSC> logging filter all 1
OsmoBSC> logging color 1

And next up we’ll try and start the BTS again:

root@gsm-bts:/etc/osmocom# osmo-bts-virtual -c osmo-bts-virtual.cfg
 ((*))
   |
  / \ OsmoBTS
<0010> telnet_interface.c:104 Available via telnet 127.0.0.1 4241
<0012> input/ipaccess.c:901 enabling ipaccess BTS mode, OML connecting to 127.0.0.1:3002
<0012> input/ipa.c:128 127.0.0.1:3002 connection done
<0012> input/ipaccess.c:724 received ID_GET for unit ID 4242/0/0

And on the BSC you’ll see roughly the same thing:

OsmoBSC# 
<0016> input/ipa.c:287 0.0.0.0:3002 accept()ed new link from 127.0.0.1:40193
<0004> abis_nm.c:490 BTS1 reported variant: omso-bts-virtual
<0004> abis_nm.c:578 OC=BASEBAND-TRANSCEIVER(04) INST=(00,00,ff): BTS1: ARI reported sw[0/1]: TRX_PHY_VERSION is Unknown
<0016> input/ipa.c:287 0.0.0.0:3003 accept()ed new link from 127.0.0.1:44053
<0003> osmo_bsc_main.c:291 bootstrapping RSL for BTS/TRX (1/0) on ARFCN 0 using MCC-MNC 001-01 LAC=4242 CID=4242 BSIC=42

If you’ve made it this far, congratulations. Our virtual BTS is now connected to our BSC – If it wasn’t virtual we’d be on the air!

So in the next post we’ll setup our SDR hardware as a BTS, then provision it on the BSC, and then our cell will be on the air.

Basic GSM Architecture

GSM with Osmocom Part 3: Introduction to Osmo Software & Virtual BTS

So this series of posts will focus on using Osmocom software to create a GSM network, so let’s get some Osmocom software installed, and talk about how we run and configure each network element / node.

Osmocom Packages

For this tutorial series I’ll be using Ubuntu 18.04 and trying where possible to use packages from Repos instead of compiling from source.

This will get the Osmocom key added to your package manager and the Osmocom sources in apt ready for us to install.

wget https://download.opensuse.org/repositories/network:/osmocom:/latest/Debian_10/Release.key
apt-key add Release.key && rm Release.key
echo "deb https://download.opensuse.org/repositories/network:/osmocom:/latest/xUbuntu_18.04/ ./" > /etc/apt/sources.list.d/osmocom-latest.list
apt-get update

Osmo-BTS-Virtual

To get started we’ll install a virtual BTS. This virtual BTS won’t simulate the Um (air) interface, but it will simulate the Abis interface towards the BSC so we can configure this virtual BTS in our BSC.

Installation is pretty straightforward:

apt-get install osmo-bts-virtual

By default Osmocom software runs as a daemon in systemctl, we’ll disable and stop this behaviour for now so we can better understand it running in the foreground:

systemctl stop osmo-bts-virtual
systemctl disable osmo-bts-virtual

Osmo Config – Text Files

If you have a look in /etc/osmocom/ you’ll see .cfg files that contain our config in text files.

But that’s not the only way (or even the recommended way) that we’ll put together the config for Osmocom software, but we’ll get started by editing the config file manually.

We’ll start by setting a Unit ID of the BTS and setting the IP of the BSC.

cd /etc/osmocom/
vi osmo-bts-virtual.cfg

We’ll edit the oml remote-ip to point to the IP of the server that will run our BSC, if you’re planning on running the BTS and BSC on the same machine you can leave it as localhost (127.0.0.1).

Next up we’ll set the Unit-ID of the BTS, this identifies the BTS inside the BSC,

I’ll set it to unit-id 4242 by changing ipa unit-id 4242 0

Finally we’ll change the logging config to show everything by changing it to:

log stderr
 logging filter all 1
!

So that’s it in terms of config for our virtual BTS through text files, so we’ll save the file and try starting up osmo-bts-virtual.

osmo-bts-virtual -c osmo-bts-virtual.cfg

You should get a result similar to this:

root@gsm-bts:/etc/osmocom# osmo-bts-virtual -c osmo-bts-virtual.cfg
 ((*))
   |
  / \ OsmoBTS
<0010> telnet_interface.c:104 Available via telnet 127.0.0.1 4241
<0012> input/ipaccess.c:901 enabling ipaccess BTS mode, OML connecting to 127.0.0.1:3002
<000d> abis.c:142 Signalling link down
<0001> bts.c:292 Shutting down BTS 0, Reason Abis close
Shutdown timer expired

root@gsm-bts:/etc/osmocom#

So what are we seeing here?

Well Osmo-BTS-Virtual is trying to bring up it’s Abis interface but it’s not getting a connection to the the BSC (We haven’t set one up yet). No connection to a BSC means the BTS won’t go on the air as it doesn’t have any processing for itself, so it eventually times out and shuts down.

In the next post we’ll move from using osmo-bts-virtual to using a SDR to run Osmo-BTS. If you’re using commercial RAN hardware, or just playing along without any RAN, skip straight to the post on Base Station Controllers where we’ll pick up again adding our Virtual BTS to the BSC.

GSM base Station

GSM with Osmocom Part 2: BTS Basics

By far the most visable part of any mobile network (apart from your phone!) is the Base (Transciver) Stations.

Dotted around the countryside, on masts, towers and monopoles, whether you notice them or not, base stations are everywhere.

The Architecture

The RF side of LTE has an eNodeB, which is a smart device. – You connect it to a TCP/IP network, it establishes a connection with your MME(s) and away you go.

A GSM BTS (Base Transceiver Station) isn’t all that clever…

The BTS is a similar to the WiFi access points that talk to a centralised controller for all their thinking.
A BTS gets most of its brains from elsewhere and essentially just handles the TX/RX of baseband data.

That elsewhere is the BSC – Base Station Controller. Each BTS connects to a BSC, and a BSC would typically control a number of BTS.

We’ll explore the BSC and it’s connections in depth, but I’ve put together a basic diagram of how everything fits together below.

Basic GSM Access Architecture

Um Interface

The Um interface is the Air Interface of GSM. It’s what takes the data and sends it out “over the air”.

There’s a lot to know about air interfaces, and I know very little. What I do know is I need to set the Um interface to use a frequency band my mobile phone supports (so I can see and connect to the network).

The Abis Interface

The fact that GSM was first deployed in 1991, explains why the Abis interface used ISDN E1/T1 TDM links to connect the Base Transceiver Stations (BTSs) to the Base Station Controller (BSC).

While now looking back you may ask why TCP/IP wasn’t used for the Abis interface, keep in mind that Windows 95 was the first version to include TCP/IP support, and that gives you an idea of the state of play. ISDN is very reliable and was well known in the telco space at that time.

I no longer have any ISDN hardware, so for me this is all going to be built using packet switched networks working as circuit switched.

Osmocom does have support for E1/T1 interfaces, so if you’ve got BTS hardware that only communicates over TDM links, that’s an option too.

GSMA never wrote a standard for taking Abis over IP, so as such each vendor has implemented it differently.

Osmocom have a flavour of Abis over IP protocol they’ve developed based on traces from a commercial implementation which we’ll be using. You can find the full protocol spec for Osmocom’s Abis over IP interface here.

OML Interface

With all the brains for the BTS residing in the BSC, there’s a need to control the BTS from the BSC. The Operation and Maintenance Link (OML) is a protocol for changing certain parameters of the BTS from the BSC.

A prime example of use of the OML would be the BSC turning the BTS off/on.

We’ll see a tiny bit of OML usage in the next post, just for turning the BTS off and on.

So let’s put this into practice and setup a virtual BTS with Osmocom.

Osmocom Logo

GSM with Osmocom Part 1: Intro

Meta

Like most people at the moment because of the lockdown I’ve got a bit more time at home than normal.

Because of this I thought I’d finally dive into GSM/UMTS and all that circuit switched tech you skip out on when getting started with LTE.

Please excuse the loving tone I use when describing some older tech, it’s a result of being a telephony tragic who gets all reminiscent thinking about the first phones they interacted with & wondered about how it all worked…

So why learn GSM?

My best friend is a translator of technical documents. In University, what’s the first language they study? Latin. Because it’s the root of so many languages.

While a lot of carriers have already switched off their GSM networks (There are no public GSM networks in Australia), the core of GSM is essentially shared with that of UMTS / 3G, which is still going to be around for the foreseeable future.

Circuit Switched Fallback (CSFB) is still common today for voice calls for a great many LTE handsets without VoLTE support. GSM powers GSM-R, the rail specific standard of GSM used across Europe. The uplink power of GSM can be up to 8 Watts (while in LTE it’s 20 dBm – 0.1W) which means it’s effective service area could be larger than 3G and 4G air interfaces.

GSM isn’t as dead as it might seem, so let’s have a Weekend at Bernie’s!

Disclaimer: Please let me know if I’ve got anything wrong! These posts will focus on the Omsocom network elements which do handle a few things the “non standard” way.

Platforms

I wrote last week about using YateBTS to get a functional GSM / GPRS network online,

It’s great that it works from a Um interface perspective; your UE / terminal can see and connect to the network. But it’s sort of an all-in-one solution; there’s no Mobile Switching Center, Base Station Controller, Sigtran, HLR or Media Gateway; Yate ties all this up into a single easy to use package.

This gets you on the air in no time, but unfortunately you don’t get exposed to how GSM / UMTS works in the real world – real networks don’t look like YateBTS NITPC.

Enter Osmocom

Osmocom (and the Sysmocom team driving many of the projects) have done a phenomenal job of building each of the network elements I just talked about pretty much “by the book”, meaning most should interop with commercial equipment and comply to the standards.

Over the next few weeks I’ll cover setting up each of the network elements, talking about what they do and how they work, and use them to create a functional GSM network (2G / Circuit Switched) using the software from Osmocom.

Once we’ve got our network functional we’ll be adding SMS, Data (GPRS / EDGE), USSD codes and even inter-RAT handover with LTE.

For this series of posts I’ll be using a mix of hardware. At the start I’ll be using a Software Defined Radio (LimeSDR) to do the RF side of the network (BTS). Osmocom has support for a lot of common SDR hardware, so hopefully for anyone wanting to follow along at home you’ll have access to a LimeSDR or USRP.

Osmocom supports many commercial BTS vendors products, as well as Sysmocom’s hardware, hardware from Range Networks. Osmocom also supports the NanoBTS range from ip.access – which are available second hand quite cheaply, which I’ll be adding to our network as well.

So buy some cheap programmable SIM cards, grab your SDR hardware or order cheap second hand GSM BTS online, and let’s get building a GSM network!

Topics Covered

I’ll update the links in here as I publish these posts, I may forget so if there’s something missing search the site or drop me a line.

My Osmocom Config Files on GitHub

Radio Access Network

BTS Basics

BTS In Practice with LimeSDR & osmo-bts-trx

The Base Station Controller (BSC)

Integrating our LimeSDR BTS with OsmoBSC

Integrating an ipaccess NanoBTS with OsmoBSC

Channel Types

Switching & Signaling

Home Location Register (HLR) (with EIR & AuC)

The SS7 Signaling Transfer Point

The Mobile Switching Center

Basic calls & SMS

Call Routing

SMS Routing

Distributed GSM

Cell Broadcast Center

External USSD Interfaces

Data Services

GPRS & Packet Data Basics

Serving Gateway Support Node

Gateway GPRS Support Node

Call Flows & Handovers

Basic GSM Calls

Basic GSM SMS

Basic GSM Packet Bearers

Inter BSC

Inter MSC

Inter-RAT

Inter RAT between LTE and GSM

GSM CSFB with OmsmoMSC and Open5GS LTE

SGs Interface for SMS over LTE

Decoding MAC LTE Frames in Wireshark

Working with LTE MAC traces in Wireshark

I recently pulled MAC layer traces off an eNB and wanted to view them,

In Wireshark this shows up as raw data, and there’s no option to decode as LTE MAC from the Decode As menu.

Instead you’ve got to go to Preferences -> Protocols and select DLT_USER and then edit the encapsulation table.

For DLT_147 enter:

mac-lte-framed

Now you’ll have your MAC frames decoded:

On top of this there’s also now the option to run analysis on these traces,

By selecting Telephony -> LTE -> MAC Statistics you’re able to view stats for each RNTI connected to the eNB.

I’ve attached a copy of my trace for reference.

Magic SIM Card Art

16 in 1 Magic SIM Card Revisited

I found a “16-in-1 Super SIM X-SIM” in my SIM card drawer, I think I ordered these when I was first playing with GSM and never used it.

I was kind of curious about how these actually worked, so after some online sleuthing I found a very suspicious looking rar file, which I ended up running in a VM and mapping the Card Reader to the VM.

What a treat I was in for in terms of UI.

The concept is quite simple, you program a series of IMSI and K key values onto the SIM card, and then using a SIM Toolkit application, you’re able to select which IMSI / K key combination you want to use.

A neat trick, I’d love a LTE version of this for changing values on the fly, but it’d be a pretty niche item considering no operator is going to give our their K and OPc keys,

But come to think of it, no GSM operator would give out K keys, so how do you get the K key from your commercial operator?

I noticed the grayed out “Crack” icon on the menu.

After rifling through my SIM drawer I found a few really old 2G SIMs, stuck one in, reconnected and clicked “Crack” and then start.

I left it running in the background after the manual suggested it could take up to 24 hours to run through all the codes.

To my surprise after 2 minutes the software was requesting I save the exported data, which I did.

Then I put the 16 in 1 back in, selected Magic and then imported the cracked SIM data (IMSI, ICCID, Ki & SMSp).

By the looks of it the software is just running a brute force attack on the SIM card, and the keyspace is only so large meaning it can be reversed in.

I did a bit of research to find out if this is exploiting any clever vulnerabilities in UCCID cards, but after running some USB Pcap traces it looks like it’s just plain old brute force, which could be easily defended against by putting a pause between auth attempts on the SIM.

I’ve no idea if that’s the actual K value I extracted from the SIM – The operator that issued the SIM doesn’t even exist anymore, but I’ll add the details to the HLR of my Osmocom GSM lab and see if it matches up.

Out of curiosity I also connected some of my development USIM/ISIM/SIM cards that I can program, the software is amazing in it’s response:

Configuring YateBTS for Software Defined GSM/GPRS

I did a post yesterday on setting up YateBTS, I thought I’d cover the basic setup I had to do to get everything humming;

Subscribers

In order to actually accept subscribers on the network you’ll need to set a Regex pattern to match the prefix of the IMSI of the subscribers you want to connect to the network,

In my case I’m using programmable SIMs with MCC / MNC 00101 so I’ve put the regex pattern matching starting with 00101.

BTS Configuration

Next up you need to set the operating frequency (radio band), MNC and MCC of the network. I’m using GSM850,

Next up we’ll need to set the device we’re going to use for the TX/RX, I’m using a BladeRF Software Defined Radio, so I’ve selected that from the path.

Optional Steps

I’ve connected Yate to a SIP trunk so I can make and receive calls,

I’ve also put a tap on the GSM signaling, so I can see what’s going on, to access it just spin up Wireshark and filter for GSMMAP

Kamailio Proxy-CSCF Pull

I had a few headaches getting the example P-CSCF example configs from the Kamailio team to run, recent improvements with the IPsec support and code evolution meant that the example config just didn’t run.

So, after finally working out the changes I needed to make to get Kamailio to function as a P-CSCF, I took the plunge and made my first pull request on the Kamailio project.

And here it is!

https://github.com/kamailio/kamailio/pull/2203

It’s now in the master branch, so if you want to setup a P-CSCF using Kamailio, give it a shot, as the example config finally works!

Multi Operator Core-Networks (MOCN) for RAN Sharing

MOCN is one of those great concepts I’d not really come across,

Multi-tenancy on the RAN side of the network, allowing an eNB to broadcast multiple PLMN IDs (MCC/MNC) in the System Information Block (SIB).

It allows site sharing not just on the tower itself, but site sharing on the RAN side, allowing customers of MNO A to see themselves connected to MNO A, and customers from MNO B see themselves as connected to MNO B, but they’re both connected to the same RAN hardware.

Setup in my lab was a breeze; your RAN hardware will probably be different.

In terms of signaling it’s a standard S1AP Setup Request except with multiple broadcast PLMN keys:

Now when I run a manual cell selection on my UE I can see the PLMN 460/11 as well as the Open5gs 00101 PLMN:

Ansible for Scaling and Deployment of Evolved Packet Core NEs

There’s always lots of talk of Network Function Virtualization (NFV) in the Telco space, but replacing custom hardware with computing resources is only going to get you so far, if every machine has to be configured manually.

Ansible is a topic I’ve written a little bit about in terms of network automation / orchestration.

I wanted to test limits of Open5gs EPC, which led me to creating a lot of Packet Gateways, so I thought I’d share a little Ansible Playbook I wrote for deploying P-GWs.

It dynamically sets the binding address and DHCP servers, and points to each PCRF in the defined pool.

You can obviously build upon this too, creating another playbook to deploy PCRFs, MMEs and S-GWs will allow you to reference the hosts in each group to populate the references.

The Playbook

---
- name: Install & configure Open5GS EPC (P-GW)

  hosts: epc

  become: yes
  become_method: sudo

  vars:
    dns_servers: ['8.8.8.8','1.1.1.1']
    diameter_realm: 'nickvsnetworking.com'
    pcrf_hosts: ['pcrf1.nickvsnetworking.com', 'pcrf2.nickvsnetworking.com']
  tasks:
    - name: Set Hostname to {{inventory_hostname}}
      hostname:
        name: "{{inventory_hostname}}"
      register: rebootrequired

    - name: Updating hotnamectl
      command: "hostnamectl set-hostname {{inventory_hostname}}"
      become: True
      become: True
      when: rebootrequired.changed

    - name: Reboot VM due to Hostname Change
      reboot:
        reboot_timeout: 180
      when: rebootrequired.changed

    - name: Add Software common
      apt:
        name: software-properties-common

    - name: Add Repository
      apt_repository:
        repo: ppa:open5gs/latest

    - name: Install Open5gs P-GW
      apt:
        update_cache: true
        name: open5gs-pgw

    - name: Fill in GTP Addresses in Config
      template:
        src: pgw.yaml.j2
        dest: /etc/open5gs/pgw.yaml
        backup: true
      register: config_changed

    - name: Fill in P-GW Diameter Config
      template:
        src: pgw.conf.j2
        dest: /etc/freeDiameter/pgw.conf
        backup: true
      register: config_changed


    - name: Restart P-GW Service if Config Changed
      service:
        name: open5gs-pgwd
        state: restarted
      when: config_changed.changed

Jinja2 Template

P-GW Config (pgw.yaml.jn2)

logger:
    file: /var/log/open5gs/pgw.log

parameter:

pgw:
    freeDiameter: /etc/freeDiameter/pgw.conf
    gtpc:
      - addr: {{hostvars[inventory_hostname]['ansible_default_ipv4']['address']}}

    gtpu:
      - addr: {{hostvars[inventory_hostname]['ansible_default_ipv4']['address']}}

    ue_pool:
      - addr: 45.45.0.1/16
      - addr: cafe::1/64
    dns:
{% for dns in dns_servers %}
      - {{ dns }}
{% endfor %}

Diameter Config (pgw.conf.j2)

# This is a sample configuration file for freeDiameter daemon.

# Most of the options can be omitted, as they default to reasonable values.
# Only TLS-related options must be configured properly in usual setups.

# It is possible to use "include" keyword to import additional files
# e.g.: include "/etc/freeDiameter.d/*.conf"
# This is exactly equivalent as copy & paste the content of the included file(s)
# where the "include" keyword is found.


##############################################################
##  Peer identity and realm

# The Diameter Identity of this daemon.
# This must be a valid FQDN that resolves to the local host.
# Default: hostname's FQDN
#Identity = "aaa.koganei.freediameter.net";
Identity = "{{ inventory_hostname  }}.{{ diameter_realm }}";

# The Diameter Realm of this daemon.
# Default: the domain part of Identity (after the first dot).
#Realm = "koganei.freediameter.net";
Realm = "{{ diameter_realm }}";
##############################################################
##  Transport protocol configuration

# The port this peer is listening on for incoming connections (TCP and SCTP).
# Default: 3868. Use 0 to disable.
#Port = 3868;

# The port this peer is listening on for incoming TLS-protected connections (TCP and SCTP).
# See TLS_old_method for more information about TLS flavours.
# Note: we use TLS/SCTP instead of DTLS/SCTP at the moment. This will change in future version of freeDiameter.
# Default: 5868. Use 0 to disable.
#SecPort = 5868;

# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA exchange is completed
# on the unsecure connection. The alternative is RFC6733 mechanism, where TLS protects also the
# CER/CEA exchange on a dedicated secure port.
# This parameter only affects outgoing connections.
# The setting can be also defined per-peer (see Peers configuration section).
# Default: use RFC6733 method with separate port for TLS.
#TLS_old_method;

# Disable use of TCP protocol (only listen and connect over SCTP)
# Default : TCP enabled
#No_TCP;

# Disable use of SCTP protocol (only listen and connect over TCP)
# Default : SCTP enabled
#No_SCTP;
# This option is ignored if freeDiameter is compiled with DISABLE_SCTP option.

# Prefer TCP instead of SCTP for establishing new connections.
# This setting may be overwritten per peer in peer configuration blocs.
# Default : SCTP is attempted first.
#Prefer_TCP;

# Default number of streams per SCTP associations.
# This setting may be overwritten per peer basis.
# Default : 30 streams
#SCTP_streams = 30;

##############################################################
##  Endpoint configuration

# Disable use of IP addresses (only IPv6)
# Default : IP enabled
#No_IP;

# Disable use of IPv6 addresses (only IP)
# Default : IPv6 enabled
#No_IPv6;

# Specify local addresses the server must bind to
# Default : listen on all addresses available.
#ListenOn = "202.249.37.5";
#ListenOn = "2001:200:903:2::202:1";
#ListenOn = "fe80::21c:5ff:fe98:7d62%eth0";
ListenOn = "{{hostvars[inventory_hostname]['ansible_default_ipv4']['address']}}";


##############################################################
##  Server configuration

# How many Diameter peers are allowed to be connecting at the same time ?
# This parameter limits the number of incoming connections from the time
# the connection is accepted until the first CER is received.
# Default: 5 unidentified clients in paralel.
#ThreadsPerServer = 5;

##############################################################
##  TLS Configuration

# TLS is managed by the GNUTLS library in the freeDiameter daemon.
# You may find more information about parameters and special behaviors
# in the relevant documentation.
# http://www.gnu.org/software/gnutls/manual/

# Credentials of the local peer
# The X509 certificate and private key file to use for the local peer.
# The files must contain PKCS-1 encoded RSA key, in PEM format.
# (These parameters are passed to gnutls_certificate_set_x509_key_file function)
# Default : NO DEFAULT
#TLS_Cred = "<x509 certif file.PEM>" , "<x509 private key file.PEM>";
#TLS_Cred = "/etc/ssl/certs/freeDiameter.pem", "/etc/ssl/private/freeDiameter.key";
TLS_Cred = "/etc/freeDiameter/pgw.cert.pem", "/etc/freeDiameter/pgw.key.pem";

# Certificate authority / trust anchors
# The file containing the list of trusted Certificate Authorities (PEM list)
# (This parameter is passed to gnutls_certificate_set_x509_trust_file function)
# The directive can appear several times to specify several files.
# Default : GNUTLS default behavior
#TLS_CA = "<file.PEM>";
TLS_CA = "/etc/freeDiameter/cacert.pem";

# Certificate Revocation List file
# The information about revoked certificates.
# The file contains a list of trusted CRLs in PEM format. They should have been verified before.
# (This parameter is passed to gnutls_certificate_set_x509_crl_file function)
# Note: openssl CRL format might have interoperability issue with GNUTLS format.
# Default : GNUTLS default behavior
#TLS_CRL = "<file.PEM>";

# GNU TLS Priority string
# This string allows to configure the behavior of GNUTLS key exchanges
# algorithms. See gnutls_priority_init function documentation for information.
# You should also refer to the Diameter required TLS support here:
#   http://tools.ietf.org/html/rfc6733#section-13.1
# Default : "NORMAL"
# Example: TLS_Prio = "NONE:+VERS-TLS1.1:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL";
#TLS_Prio = "NORMAL";

# Diffie-Hellman parameters size
# Set the number of bits for generated DH parameters
# Valid value should be 768, 1024, 2048, 3072 or 4096.
# (This parameter is passed to gnutls_dh_params_generate2 function,
# it usually should match RSA key size)
# Default : 1024
#TLS_DH_Bits = 1024;

# Alternatively, you can specify a file to load the PKCS#3 encoded
# DH parameters directly from. This accelerates the daemon start
# but is slightly less secure. If this file is provided, the
# TLS_DH_Bits parameters has no effect.
# Default : no default.
#TLS_DH_File = "<file.PEM>";


##############################################################
##  Timers configuration

# The Tc timer of this peer.
# It is the delay before a new attempt is made to reconnect a disconnected peer.
# The value is expressed in seconds. The recommended value is 30 seconds.
# Default: 30
#TcTimer = 30;

# The Tw timer of this peer.
# It is the delay before a watchdog message is sent, as described in RFC 3539.
# The value is expressed in seconds. The default value is 30 seconds. Value must
# be greater or equal to 6 seconds. See details in the RFC.
# Default: 30
#TwTimer = 30;

##############################################################
##  Applications configuration

# Disable the relaying of Diameter messages?
# For messages not handled locally, the default behavior is to forward the
# message to another peer if any is available, according to the routing
# algorithms. In addition the "0xffffff" application is advertised in CER/CEA
# exchanges.
# Default: Relaying is enabled.
#NoRelay;

# Number of server threads that can handle incoming messages at the same time.
# Default: 4
#AppServThreads = 4;

# Other applications are configured by loaded extensions.

##############################################################
##  Extensions configuration

#  The freeDiameter framework merely provides support for
# Diameter Base Protocol. The specific application behaviors,
# as well as advanced functions, are provided
# by loadable extensions (plug-ins).
#  These extensions may in addition receive the name of a
# configuration file, the format of which is extension-specific.
#
# Format:
#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ;
#
# Examples:
#LoadExtension = "extensions/sample.fdx";
#LoadExtension = "extensions/sample.fdx":"conf/sample.conf";

# Extensions are named as follow:
# dict_* for extensions that add content to the dictionary definitions.
# dbg_*  for extensions useful only to retrieve more information on the framework execution.
# acl_*  : Access control list, to control which peers are allowed to connect.
# rt_*   : routing extensions that impact how messages are forwarded to other peers.
# app_*  : applications, these extensions usually register callbacks to handle specific messages.
# test_* : dummy extensions that are useful only in testing environments.


# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some
# information about some events. This extension does not actually use a configuration file
# but receives directly a parameter in the string passed to the extension. Here are some examples:
## LoadExtension = "dbg_msg_dumps.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors.
## LoadExtension = "dbg_msg_dumps.fdx" : "0x2222"; # Display all events with few details.
## LoadExtension = "dbg_msg_dumps.fdx" : "0x0080"; # Dump complete information about sent and received messages.
# The four digits respectively control: connections, routing decisions, sent/received messages, errors.
# The values for each digit are:
#  0 - default - keep the default behavior
#  1 - quiet   - remove any specific log
#  2 - compact - display only a summary of the information
#  4 - full    - display the complete information on a single long line
#  8 - tree    - display the complete information in an easier to read format spanning several lines.

LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dbg_msg_dumps.fdx" : "0x8888";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_rfc5777.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_mip6i.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_nasreq.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_nas_mipv6.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_dcca.fdx";
LoadExtension = "/usr/lib/x86_64-linux-gnu/freeDiameter/dict_dcca_3gpp.fdx";


##############################################################
##  Peers configuration

#  The local server listens for incoming connections. By default,
# all unknown connecting peers are rejected. Extensions can override this behavior (e.g., acl_wl).
#
#  In addition to incoming connections, the local peer can
# be configured to establish and maintain connections to some
# Diameter nodes and allow connections from these nodes.
#  This is achieved with the ConnectPeer directive described below.
#
# Note that the configured Diameter Identity MUST match
# the information received inside CEA, or the connection will be aborted.
#
# Format:
#ConnectPeer = "diameterid" [ { parameter1; parameter2; ...} ] ;
# Parameters that can be specified in the peer's parameter list:
#  No_TCP; No_SCTP; No_IP; No_IPv6; Prefer_TCP; TLS_old_method;
#  No_TLS;       # assume transparent security instead of TLS. DTLS is not supported yet (will change in future versions).
#  Port = 5868;  # The port to connect to
#  TcTimer = 30;
#  TwTimer = 30;
#  ConnectTo = "202.249.37.5";
#  ConnectTo = "2001:200:903:2::202:1";
#  TLS_Prio = "NORMAL";
#  Realm = "realm.net"; # Reject the peer if it does not advertise this realm.
# Examples:
#ConnectPeer = "aaa.wide.ad.jp";
#ConnectPeer = "old.diameter.serv" { TcTimer = 60; TLS_old_method; No_SCTP; Port=3868; } ;
{% for pcrf in pcrf_hosts %}
ConnectPeer = "{{ pcrf }}" { ConnectTo = "{{ pcrf }}"; No_TLS; };
{% endfor %}



##############################################################

GTPv2 – F-TEID Interface Types

I’ve been working on a ePDG for VoWiFi access to my IMS core.

This has led to a bit of a deep dive into GTP (easy enough) and GTPv2 (Bit harder).

The Fully Qualified Tunnel Endpoint Identifier includes an information element for the Interface Type, identified by a two digit number.

Here we see S2b is 32

In the end I found the answer in 3GPP TS 29.274, but thought I’d share it here.

0S1-U eNodeB GTP-U interface
1S1-U SGW GTP-U interface
2S12 RNC GTP-U interface
3S12 SGW GTP-U interface
4S5/S8 SGW GTP-U interface
5S5/S8 PGW GTP-U interface
6S5/S8 SGW GTP-C interface
7S5/S8 PGW GTP-C interface
8S5/S8 SGW PMIPv6 interface (the 32 bit GRE key is encoded in 32 bit TEID field and since alternate CoA is
not used the control plane and user plane addresses are the same for PMIPv6)
9S5/S8 PGW PMIPv6 interface (the 32 bit GRE key is encoded in 32 bit TEID field and the control plane and
user plane addresses are the same for PMIPv6)
10S11 MME GTP-C interface
11S11/S4 SGW GTP-C interface
12S10 MME GTP-C interface
13S3 MME GTP-C interface
14S3 SGSN GTP-C interface
15S4 SGSN GTP-U interface
16S4 SGW GTP-U interface
17S4 SGSN GTP-C interface
18S16 SGSN GTP-C interface
19eNodeB GTP-U interface for DL data forwarding
20eNodeB GTP-U interface for UL data forwarding
21RNC GTP-U interface for data forwarding
22SGSN GTP-U interface for data forwarding
23SGW GTP-U interface for DL data forwarding
24Sm MBMS GW GTP-C interface
25Sn MBMS GW GTP-C interface
26Sm MME GTP-C interface
27Sn SGSN GTP-C interface
28SGW GTP-U interface for UL data forwarding
29Sn SGSN GTP-U interface
30S2b ePDG GTP-C interface
31S2b-U ePDG GTP-U interface
32S2b PGW GTP-C interface
33S2b-U PGW GTP-U interface

I also found how this data is encoded on the wire is a bit strange,

In the example above the Interface Type is 7,

This is encoded in binary which give us 111.

This is then padded to 6 bits to give us 000111.

This is prefixed by two additional bits the first denotes if IPv4 address is present, the second bit is for if IPv6 address is present.

Bit 1Bit 2Bit 3-6
IPv4 Address Present IPv4 Address PresentInterface Type
11 000111

This is then encoded to hex to give us 87

Here’s my Python example;

interface_type = int(7)
interface_type = "{0:b}".format(interface_type).zfill(6)   #Produce binary bits
ipv4ipv6 = "10" #IPv4 only
interface_type = ipv4ipv6 + interface_type #concatenate the two
interface_type  = format(int(str(interface_type), 2),"x") #convert to hex

VoLTE Logo on Samsung Galaxy Handset

Things I wish I knew about setting up private VoLTE Networks

I’ve been working for some time on open source mobile network cores, and one feature that has been a real struggle for a lot of people (Myself included) is getting VoLTE / IMS working.

Here’s some of the issues I’ve faced, and the lessons I learned along the way,

Sadly on most UEs / handsets, there’s no “Make VoLTE work now” switch, you’ve got a satisfy a bunch of dependencies in the OS before the baseband will start sending SIP anywhere.

Get the right Hardware

Your eNB must support additional bearers (dedicated bearers I’ve managed to get away without in my testing) so the device can setup an APN for the IMS traffic.

Sadly at the moment this rules our Software Defined eNodeBs, like srsENB.

In the end I opted for a commercial eNB which has support for dedicated bearers.

ISIM – When you thought you understood USIMs – Guess again

According to the 3GPP IMS docs, an ISIM (IMS SIM) is not a requirement for IMS to work.

However in my testing I found Android didn’t have the option to enable VoLTE unless an ISIM was present the first time.

In a weird quirk I found once I’d inserted an ISIM and connected to the VoLTE network, I could put a USIM in the UE and also connect to the VoLTE network.

Obviously the parameters you can set on the USIM, such as Domain, IMPU, IMPI & AD, are kind of “guessed” but the AKAv1-MD5 algorithm does run.

Getting the APN Config Right

There’s a lot of things you’ll need to have correct on your UE before it’ll even start to think about sending SIP messaging.

I was using commercial UE (Samsung handsets) without engineering firmware so I had very limited info on what’s going on “under the hood”. There’s no “Make VoLTE do” tickbox, there’s VoLTE enable, but that won’t do anything by default.

In the end I found adding a new APN called ims with type ims and enabling VoLTE in the settings finally saw the UE setup an IMS dedicated bearer, and request the P-CSCF address in the Protocol Configuration Options.

Also keep in mind on Android at least, what you specify as your APN might be ignored if your UE thinks it knows best – Thanks to the Android Master APN Config – which guesses the best APN for you to use, which is a useful feature to almost any Android user, except the very small number who see fit to setup their own network.

Get the P-GW your P-CSCF Address

If your P-GW doesn’t know the IP of your P-CSCF, it’s not going to be able to respond to it in the Protocol Configuration Options (PCO) request sent by the UE with that nice new bearer for IMS we just setup.

There’s no way around Mutual Authentication

Coming from a voice background, and pretty much having RFC 3261 tattooed on my brain, when I finally got the SIP REGISTER request sent to the Proxy CSCF I knocked something up in Kamailio to send back a 200 OK, thinking that’d be the end of it.

For any other SIP endpoint this would have been fine, but IMS Clients, nope.

Reading the specs drove home the same lesson anyone attempting to setup their own LTE network quickly learns – Mutual authentication means both the network and the UE need to verify each other, while I (as the network) can say the UE is OK, the UE needs to check I’m on the level.

For anyone not familiar with the intricacies of 3GPP USIM Network Authentication, I’ve written about Mutual Network Authentication in this post.

In the end I added Multimedia Authentication support to PyHSS, and responded with a Crypto challenge using the AKAv1-MD5 auth,

For anyone curious about what goes on under the hood with this, I wrote about how the AKAv1-MD5 Authentication algorithm works in this post,

I saw my 401 response go back to the UE and then no response. Nada.

This led to my next lesson…

There’s no way around IPsec

According to the 3GPP docs, support for IPsec is optional, but I found this not to be the case on the handsets I’ve tested.

After sending back my 401 response the UE looks for the IPsec info in the 401 response, then tries to setup an IPsec SA and sends ESP packets back to the P-CSCF address.

Even with my valid AKAv1-MD5 auth, I found my UE wasn’t responding until I added IPsec support on the P-CSCF, hence why I couldn’t see the second REGISTER with the Authentication Info.

After setting up IPsec support, I finally saw the UE’s REGISTER with the AKAv1-MD5 authentication, and was able to send a 200 OK.

For some more info on ESP, IPsec SAs and how it works between the UE and the P-CSCF there’s a post on that too.

Get Good at Mind Reading (Or an Engineering Firmware)

To learn all these lessons took a long time,

One thing I worked out a bit late but would have been invaluable was cracking into the Engineering Debug options on the UEs I was testing with.

Samsung UEs feature a Sysdump utility that has an IMS Debugging tool, sadly it’s only their for carriers doing IMS interop testing.

After a bit of work I detailed in this post – Reverse Engineering Samsung Sysdump Utils to Unlock IMS Debug & TCPdump on Samsung Phones – I managed to create a One-Time-Password generator for this to generate valid Samsung OTP keys to unlock the IMS Debugging feature on these handsets.

I outlined turning on these features in this post.

This means without engineering firmware you’re able to pull a bunch of debugging info off the UE.

If you’ve recently gone through this, are going through this or thinking about it, I’d love to hear your experiences.

I’ll be continuing to share my adventures here and elsewhere to help others get their own VoLTE networks happening.

If you’re leaning about VoLTE & IMS networks, or building your own, I’d suggest checking out my other posts on the topic.

BaiCells Neutrino eNB Setup

For my LTE lab I got myself a BaiCells Neutrino, it operates on Band 3 (FDD ~1800Mhz) with only 24dBm of output power max and PoE powered it works well in a lab environment without needing -48vDC supply, BBUs, DUs feeders and antennas.

Setup can be done via TR-069 or via BaiCells management server, for smaller setups the web UI makes setup pretty easy,

Logging in with admin/admin to the web interface:

We’ll select Quick Settings, and load in our MME IP address, PLMN (MCC & MNC), Tracking Area Code, Cell ID and Absolute Radio Frequency No.

Once that’s done we’ll set our Sync settings to use GPS / GNSS (I’ve attached an external GPS Antenna purchased cheaply online).

Finally we’ll set the power levels, my RF blocking setup is quite small so I don’t want excess power messing around with it, so I’ve dialed the power right back:

And that’s it, it’ll now connect to my MME on 10.0.1.133 port 36412 on SCTP.

VoLTE / IMS – P-CSCF Assignment

The Proxy-Call Session Control Function is the first network element a UE sends it’s SIP REGISTER message to, but how does it get there?

To begin with our UE connects as it would normally, getting a default bearer, an IP address and connectivity.

Overview

If the USIM has an ISIM application on it (or IMS is enabled on the UE using USIM for auth) and an IMS APN exists on the UE for IMS, the UE will set up another bearer in addition to the default bearer.

This bearer will carry our IMS traffic and allow QoS to be managed through the QCI values set on the bearer.

While setting up the bearer the UE requests certain parameters from the network in the Protocol Configuration Options element, including the P-CSCF address.

When setting up the bearer the network responds with this information, which if supported includes the P-CSCF IPv4 &/or IPv6 addresses.

The Message Exchange

We’ll start assuming the default bearer is in place & our UE is configured with the APN for IMS and supports IMS functionality.

The first step is to begin the establishment of an additional bearer for the IMS traffic.

This is kicked off through the Uplink NAS Transport, PDN Connectivity Request from the UE to the network. This includes the IMS APN information, and the UE’s NAS Payload includes the Protocol Configuration Options element (PCO), with a series of fields the UE requires responses from the network. including DNS Server, MTU, etc.

In the PCO the UE also includes the P-CSCF address request, so the network can tell the UE the IP of the P-CSCF to use.

If this is missing it’s because either your APN settings for IMS are not valid, or your device doesn’t have IMS support or isn’t enabling it.(that could be for a few reasons).

Protocol Configuration Options (Unpopulated) used to request information from the Network by the UE

The MME gets this information from the P-GW, and the network responds in the E-RAB Setup Request, Activate default EPS bearer Context Request and includes the Protocol Configuration Options again, this time the fields are populated with their respective values, including the P-CSCF Address;

Once the UE has this setup, the eNB confirms it’s setup the radio resources through the E-RAB Setup Response.

One the eNB has put the radio side of things in place, the UE confirms the bearer assignment has completed successfully through the Uplink NAS Transport, Activate default EPS Bearer Accept, denoting the bearer is now in place.

Now the UE has the IP address(s) of the P-CSCF and a bearer to send it over, the UE establishes a TCP socket with the address specified in the P-CSCF IPv4 or IPv6 address, to start communicating with the P-CSCF.

The SIP REGISTER request can now be sent and the REGISTRATION procedure can begin.

I’ve attached a PCAP of the full exchange here.

I’ve written a bit about the Gm REGISTER procedure and how IPsec is implemented between the UE and the P-CSCF in this post.

If you’re leaning about VoLTE & IMS networks, or building your own, I’d suggest checking out my other posts on the topic.