This blog post will briefly talk about how RADIUS and Diameter work, how we managed to incorporate Diameter into OpenSIPS 3.2 and what we have built on top of it so far.
Short Protocol Intro
The RADIUS spec first appeared in 1997 and was revised in 2000. Its purpose is to offer Authentication (Are the credentials correct?), Authorization (Once authenticated, are the permissions correct?) and Accounting (Once done, log this operation). Its functionality is simplistic in nature, as you may even compare it to HTTP to some degree: a request and its reply — success or failure — there is rarely any state to be maintained in-between. It is also customizable, thanks to its messages comprising of a dynamic set of attribute/value pairs, called AVPs. Each known AVP has a specific code in the RADIUS IANA registry, but custom ones can be easily defined by any user. Example AVPs in a RADIUS message and their values:
SIP-Method: INVITE Digest-Username: sipp Digest-Realm: sipdomain.invalid Digest-URI: firstname.lastname@example.org ...
Fast-forward to 2003 and the Diameter spec was born (revised in 2012), as both a next-generation RADIUS protocol and a terrible naming pun. Building on top of RADIUS and fully backwards-compatible with it, Diameter solves several problems that were not initially foreseen with RADIUS, to name a few:
- message failover support
- reliable transport (RADIUS uses UDP)
- universal support for TLS/TCP and DTLS/SCTP
- well-defined agent support (think proxies, redirects or relay servers)
- dynamic peer discovery and configuration
- capability negotiation
On a closer look, most (all?) of these features are low-level, pertaining to the very core of the Diameter state machine. And as RADIUS/Diameter application developers, we would work way above that level, leaving all of that minutiae to a proper Diameter server. So for us, both protocols are the same! We still work with the same list of AVPs in a message and we still do simplistic request/response exchanges, reading the given AVPs in a Diameter message and taking a decision (success or failure) based on them.
For RADIUS, the typical solution was to configure and deploy a FreeRADIUS server, then connect OpenSIPS to it using libfreeradius.
But how did the Diameter implementation shape up during this iteration?
Similarly to SIP, a Diameter implementation is non-trivial and typically comprises of several layers. In a simplified way of looking at them, they would be:
- the application layer, handling the content of Diameter messages (application they are representing, which AVPs to include when sending, which AVPs to mandate when reading, application-specific error-codes, etc.)
- the parser layer, handling building and parsing of Diameter messages
- the peer state machine layer, which controls routing and evaluation of Diameter messages once they are built or received. Example decisions: “do I have the capabilities to handle this message?”, “Am I processing or relaying?”, “My peer cannot handle this message, what is the next peer to retry?”, etc.
We then came across the freeDiameter project, which implements all of the above into two open-sourced, GPL-compatible, neatly packed C libraries: libfdproto (the protocol part) and libfdcore (the peer part). Moreover, packages are starting to be available for both of these in Debian 10+ and Ubuntu 20+, making the code easily accessible to the majority of OpenSIPS users. A match made in heaven!
On the client side, the new aaa_diameter OpenSIPS module dynamically links with both freeDiameter libraries, offering full Diameter functionality.
On the server side, freeDiameter has an excellent, modular architecture, allowing you to easily write your own application and dynamically plug it in when the server starts. And that’s exactly what we did, as I am proud to introduce the new app_opensips freeDiameter application, catered specifically to the aaa_diameter OpenSIPS module!
We would like to give a big “thank you!” to the freeDiameter open-source project for their excellent Diameter implementation, architecture and packaging!
Diameter Applications In OpenSIPS 3.2
Being an extensible protocol, Diameter offers a virtually infinite number of applications you can build on top of it. And as a way for us to get acquainted with both Diameter and the freeDiameter project, our aim for the 3.2 release was for the initial Diameter implementation to have feature-parity with the already existing RADIUS implementation of the AAA interface in OpenSIPS.
In other words, the existing RADIUS implementation has remained unaffected and is still fully functional — it is a completely separate module, after all (aaa_radius). However, we did take the time to update the default RADIUS opensips.dictionary configuration file with all missing AVP codes that were often required by OpenSIPS, yet they had to be pre-known and manually populated by each OpenSIPS system developer wishing to integrate RADIUS. So RADIUS users, please enjoy!
Regarding the new aaa_diameter module, let’s take a look at how the Diameter-based AAA applications turned out:
For accounting, we started from the Accounting-Request (Command Code: 271) Diameter messages, as part of the “Diameter base accounting” Diameter application (Application ID: 3). Both of these are specified in the Diameter base protocol (RFC 6733).
Now, thanks to Diameter being extensible, the OpenSIPS acc module will add a custom AVP to the Diameter message for each field in the CDR to be logged. All of the custom AVPs will need to be defined beforehand in the freeDiameter configuration files on both OpenSIPS client and the server side before the accounting can work.
A detailed tutorial on Diameter accounting is available on the wiki.
For digest authentication, we started from the Multimedia-Auth-Request (Command Code: 286) Diameter messages, as part of the “Diameter Session Initiation Protocol (SIP) Application” Diameter application (Application ID: 6). These messages are defined in RFC 4740 (Diameter SIP Application), and will flow as follows:
Similar to the accounting logic, we were constrained to customize the Diameter message in a similar way to its RADIUS counterpart, since both implementations follow the same API. However, the final messages are still RFC-compliant and could, in theory, be implemented both by Diameter clients wanting to interface with our app_opensips server-side application and Diameter servers wanting to interface with the aaa_diameter module.
A detailed tutorial on Diameter authentication is available on the wiki.
OpenSIPS 3.2 opens the gates in full force for Diameter and its plethora of applications. And since the Diameter implementation is quite mature thanks to the freeDiameter project, the only remaining thing is to keep building Diameter applications on top of it! This includes, possibly, finalizing the RFC 4740 SIP Application (implement all Diameter methods defined over there) or even making the first steps into the world of Diameter-based IMS applications!
If you are interested in Diameter and its applications or would like to make any suggestions on the current implementation, make sure to register for free for OpenSIPS Summit 2021 Distributed in September, where there will definitely be quite a bit of buzz around this topic!