OpenSER Getting Started Guide

Adam Linford

Oralnet Ltd.

Table of Contents
I. The Theory
Introduction
OpenSER / SER
OpenSER Releases
OpenSER management
The OpenSER Guide
The Technology
SIP - A brief Introduction
Elements of a SIP network (and where OpenSER fits in)
SIP - In action
NAT and Firewalls
Security and SIP
OpenSER architecture
OpenSER Core
Configuration: openser.cfg
OpenSER modules
II. The Practical
Before you begin
Third Party Applications
Troubleshooting
Hello World
Objectives
openser.cfg
Commentary
Usage
Summary
MySQL and Authentication
Objectives
openser.cfg
openserctl - An introduction to the Mangement Interface
Commentary
Usage
Nathelper and RTP Proxy
Objectives
openser.cfg
Commentary
Usage
PBX/PSTN Gateway
Objectives
openser.cfg
Commentary
Usage
Call Forwarding
Objectives
openser.cfg
Commentary
Usage
III. Case Studies
Scalability and Resilience
Discussion
openser.cfg
Other sources of information
Objectives
openser.cfg
Software Installation and Configuration
OpenSER
MySQL
FreeRadius
Media Proxy
RTP Proxy
Reference Information
OpenSER Modules

Introduction


OpenSER / SER

Note

This chapter is being contributed by Daniel-Constantin Mierla

OpenSER started from SER v0.9.3 and its first version was 0.9.5. Up to v1.0.x, OpenSER has similar architecture and the compatibility with SER 0.9.x was kept. With v1.1.0, major changes were introduced in OpenSER and the compatibility is hard to maintain.

The fork of SER into OpenSER happened on the 14th of June, 2005. The decision was made by two core developers of SER, Bogdan-Andrei Iancu and Daniel-Constantin Mierla, and a main contributor, Elena-Ramona Modroiu. The three were concerned because the other core developers hired by iptelorg.com (bought later 2005 by Tekelek) were not collaborating for the public project anymore, and they refused including into SER major contributions like TLS (required by RFC3261) and mutileg accounting.


When did everything start?

History of OpenSER/SER starts back in 2001/2002, when Andrei Pelinescu-Oncliul started the project at Fraunhofer FOKUS Institute, Berlin, Germany. It was joined in short time by Bogdan-Andrei Iancu. The other core developers completed the team of five: Daniel-Constantin Mierla, Jan Janak and Jiri Kuthan. Since autum 2002 when the project was made open source under GPL, the five leaded the project till 2005, all of them being most of the time reasearchers at FhG FOKUS. The main rule of the project was that any contribuited code has to be reviewed by the developer who wrote the initial version to whom the code applies. The decisions about releases were taken upon agreement of all core developers.

SER became a powerful SIP server in a short time, contributors from outside of the institure joined very soon: Juha Heinanen, mainly with RADIUS and enum support, Maxim Sobolev and Adrian Georgescu with NAT traversal solutions, Elena-Ramona Modroiu with couple of handful modules.

In 2004 (my guess), iptelorg.com, a private company was founded with main focus on SER-based business. During 2004 and 2005, three core developers moved to iptelorg.com, one of them being co-founder of the company. The other two, continued with FhG FOKUS until few months before starting OpenSER in June 2005.


Design and versioning

As expected, the two SIP servers have same internal design: core and modules. The core includes key components like transport layer (UDP/TCP/TLS server, SIP parser, database abstract interface). The modules implements the features-side of the server: authentication, authorization and accounting, user location and registrar, transaction support and many others you will discover in this document.

Versioning uses three numbers X.Y.Z. X denotes the version and it is increased when architectural changes were introduced. In OpenSER case X was kept to 0 until the 'MUST' requirements of RFC3261 were completed. Y is the major revision and it is increased when new features are introduced in stable version. Z is the minor revision and denotes fixes to a major revision.

Although some people try to suggest that by its release policy, OpenSER is very likely to be not very stable, the time proved the contrary. OpenSER release policy has a clear schedule and very good reasons. Each cycle starts with 5-6 months of development. Then follows a period of 1-2 months with code frozen and heavy testing. Afterwards is the time for packaging and new major release. The reason of doing often releases, but still ensure the stability, is to allow the administrators of OpenSER-based platform to migrate easily to new versions. By letting the development to last for ages the acumulated code will be hard to be tested thoroughly and the amount of changes will make the upgrade process very tough.

This kind of release policy is adopted by other major player in the VoIP area, namely Asterisk.


OpenSER Releases

This section tries to collect the most important features a major release introduced in OpenSER.


OpenSER 0.9.4

This is the first official release of the SIP server under name 'OpenSER', on the 14th of June, 2005. A snapshot of SER branch rel_0_9_0 was taken, the code was tested, some new features from unstable version were backported, the documentation for modules was completely updated.

The new modules introduced are:

  • alias_db - simple alias management with database storage only.

  • avpops - powerful module that allow complex operations. It introduced the first implementation for variable-like support in configuration file.

  • dispatcher - load balancing using hash algorithms over parts if SIP requests

  • lcr - least cost routing module - backport in 0.9.5

  • speeddial - server side short dialing

About one month later, SER released 0.9.3 as new stable version, basically using the code tested and prepared during spring by the team members which started OpenSER.


OpenSER 1.0.0

The big step to versiong '1' was acomplished by adding support for TLS - the last big requirement of RFC3261. OpenSER became the first open source SIP server which had TLS support, on the 10th of October 2005. These release introduced for the first time the idea of pseudo-variables, unifying the concept of AVP and references to parts of SIP messages. Several months after, similar concept was adopted in SER under the name 'select'.

There were lot of improvements to 'avpops' module which allowed many arithmetic and string operations. 'exit' and 'return' statements were introduced in config along with 'switch' and return code. The configuration script got more functions to manage the destionation address (outboud address), accounting added support for multi-leg calls (one record per leg, when server has to deal with call forwarding), nathelper became capable of sending SIP OPTIONS requests to keep the pinhole open in the NAT.

The new modules introduced are:

  • uac - user agent client functionalities: anonymization and authentication done by server.

  • uac_redirect - user agent client behavior for handling 3XX redirect replies.


OpenSER 1.1.0

Launched on the 10th of July, 2006, this release confirmed the maturity of TLS and pseudo-variables concept. It introduces many new modules and features in OpenSER, being another big step further. The core got support for serial forking and DNS NAPTR for service discovery. OpenSERCtl script got significat refurbishing, with new modular concept. A new designed 'statistics' support allow admins to watch the internal state of OpenSER. AVPOPS module introduced unified notation for pseudo-variables along with avp_sb_query() which allow to execute any SQL statement and load the result in AVPs.

Other major achievement with this release was the addoption of OpenSER in official Debian distributions (unstable and testing). Just for the records, at that time SER was not yet included in Debian. The project may have been considered young by some people, but it has inherited the history of SER and it has accumulated during the first year of activity over 60 contributors. The activity on mailing lists and forums was reflecting a comunity of over 1000 members.

The new modules introduced are:

  • dialog - call stateful support.

  • osp - mutilateral peering support with OSP.

  • path - PATH extension support (RFC3327).

  • siptrace - ability to log SIP traffic to meet legal requirements.

  • statistics - added support for user defined statistics in configuartion script.

  • unixodbc - database conectivity module based on uniodbc library.


OpenSER management

The project is managed by a board of seven people, in alphabetical order at this moment, they are: Adrian Georgescu, Bogdan-Andrei Iancu, Cesc Santasusana, Daniel-Constantin Mierla, Elena-Ramona Modroiu, Juha Heinanen and Klaus Darilion. The members are from different companies, for the reason to ensure fair and independent decisions for OpenSER project. This should avoid conflicts when the interest of one company tries to stop the contributions or the evolution of the project. The sources are hosted in an independed site, well known for open source projects: sourceforge.net.


The OpenSER Guide

This document was inspired by the SER Getting Started guide, which is hosted at onsip.org. It was probably the single most important document produced for the SER project, which users new to SER (and importantly, users new to SIP, and without programming experience) could use to get their server up and running with minimum fuss or confusion.

The requirement for this document can be identified in 3 parts:

  • With VoIP becoming more and more popular worldwide, a significant set of users new to SIP and OpenSER were asking the same kinds of questions. Questions answered thoroguhly in onsip.org's Getting Started guide for SER

  • OpenSER's rapid development cycle was constantly introducing new features, which of course gets no representation in SER's guide, leaving many users unsure as to the difference between the two applications. Additionally, small changes in the way to two pieces of software were being introduced, and over time this was becoming significantly

  • As SER approaches a stable release of the 0.10.0 branch, which includes a major overhaul of a lot of core code, the consequential effects on how ser is configured, and the database schema's it uses, have become much more evident.

The long and short of it is the authors saw for the first time that SER and OpenSER were nearing a point where they could no longer have direct comparisons drawn between them with any degree of reliability, as far as configuration methods and syntax was concerned, which for the new user to OpenSER, is a mjor problem.


How to use this guide

This guide is in four parts. Part I is an introduction. It discusses core concepts around OpenSER and its operation. It informs you about the modules that are distributed with OpenSER, and discusses briefly the protocols and technology that OpenSER works with.

Part II is the tutorial. It provides fully working and tested configuration files, and walks you through them, line by line. It puts the statements in context and explains why they operate the way they do. It goes on to discuss how and why you would want to emply that functionality. Starting with a very simple configuration file of a basic proxy, it adds in more and more features, and leaves the reader (hopefully), with a decent grounding in how get all the basic things working in OpenSER

Part III concerns itself with some advanced topics. Including Security, performance, and scalability, it discusses key issues about how to get OpenSER to do what you want it to do, but in a production environment. It points you in the right direction for questions you might have about more advanced features, and hopefully leaves the reader with a decent picture of what is capable with OpenSER.

The fourth and final part is a catalogue of reference information, helping you with third part application configuration, providng SIP call-flow examples, and generally is a place to put all associated information that I couldnt or wouldnt put into the main guide!

reference sections for installation, what to do first, how to read the guide, where to get latest version etc


The Technology

This section tries to give you enough relevant information about SIP and associated protocols, in order for you to be able to understand what OpenSER can and cannot do. It covers logical network components as set out in IETF standards, and is generally a primer for the tutorials which follow.


SIP - A brief Introduction

SIP is a protocol; the product of the Internet Engineering Task Force (IETF), and was developed using open standards. SIP stands for Session Initiation Protocol, which pretty much says it all. SIP, in simple terms, provides a means for users to do 3 simple things:

  • Locate other users in order to try and establish a session.

  • Establish communicative sessions, through negotiation.

  • Enable users to terminate an active session.

SIP is extensive and powerful, but rather limited at the same time (and quite rightly so). Many people new to SIP are confused as to its responsiblities initially, as it has become almost a synonym for VoIP. In truth SIP is not VoIP. VoIP is one type of application that SIP is capable of providing.

Possibly the most important thing that SIP does not do, is that it does not manage, or interract, with the media stream. By that, we mean that once a session is established between two SIP end-points, SIP's job is done (until the session needs to be terminated). Other protocols are involved in the actual media of that session. This means that SIP wont help you detect DTMF tones generated during a VoIP call, it is not responsible for playing music on hold, and it wont act as a conference bridge. It will, however, negotiate and set up sessions with the appropraite SIP UA's which will provide those services.

As far as SIP is concerned, once a session is established, the actual media goes directly between the users. The media stream itself is managed by a completely different protocol, RTP (Real-time Transport Protocol), which is introduced below.

What particular type of media, how it should be encoded, and what contact information should be used regarding its transmission/reception, is part of a negotiation process that is handled by another protocol (the term 'protocol' is used loosely here), called SDP (Session Description Protocol). This is also explained in some more detail below.


RTP

RTp uses UDP for transport over IP. This means it uses a connection-less method of communication, which is great for getting as much data transmitted to the destination as soona s possible, but does not offer any guarantee of delivery as its major drawback. RTP compensates for this defficiency in two ways:

Firstly, it issues a sequence numbers to its packets, along with a timestamp and allows for synhronisation. It also employs the use of RTCP (RTP Control Protocol), which is designed to provide fault diagnosis, quality monitoring, and other useful information that allows SIP UA's to more accurately determine the validity of the information it is recieving.

RTP provides transport for a variety of media, but audio and viedo remain the most common.


SDP

SDP stands for Session Description Protocol, and it is used to handle the session negotiation process within a SIP transaction. an SDP packet is often carried as the message body of a SIP request. This is exemplified in section x.x

As part of a session (SIP) INVITE, an SDP offer is made, detailing a number of characteristics that define the proposed session. The response to this (via SIP, from the UAS), acknowledges acceptance, or offers alternative session parameters, or declines the proposed session with no alternatives offered.


Elements of a SIP network (and where OpenSER fits in)

SIP is a text-encoded protocol (opposed to binary-encoded), not disimilar to HTTP or SMTP. However, it is not a strict client-server architecture in the same way that HTTP or SMTP is. Each endpoint in a SIP network (referred to as a SIP User Agent), contains both client and server functionality. This is part ot the flexibility of SIP, as it can operate in a peer-to-peer model, unlike HTTP or SMTP.

You can therefore look at SIP's communication model as one of 'request and response', with additional handling for failure. The elements of a SIP network fall into one of two categories, broadly speaking: User Agents and SIP Servers


SIP User Agents (UA's)

These are the endpoints in a SIP network, and each UA can be divided into two sub-components:

  • User Agent Client (UAC): This entitiy initiaites requests. Imagine picking up your SIP phone to make a call. It is the UAC that makes the request to the SIP server (or sometimes directly to another UA), in order to try and establish a session.

  • User Agent Server (UAS): This element of a UA is the one which generates responses to requests it has recieved. It is this part of your SIP phone that will play a ring-tone to notify you that another UA wishes to establish a session.


SIP Servers

There are three core pieces of functionality, defined within SIP RFC 3261, which are performed by SIP Servers. One or more (or all) can be performed by the same application or device, and this is exactly what OpenSER is capable of. Thes types of server, are:

  • Registrar Sever: This server takes registration requests from UA's, and maintains information as to their location.

  • Location Sever: This server replaces the user's AoR (Address of Record) with the contact address registered by user. This entity is complementary to Registrar Server

  • Proxy Server: A SIP proxy recieves SIP messages (both requests and responses), that are gerneated by UA's, and forwards them on (either to the destination UA, or the next SIP Server in the route, as specified in the SIP message itself).

  • Redirect Server: This conceptual SIP network entity recieves requests from a proxy or UA, and responds with a specific SIP response method, telling the originator of the request that the user is not available at that location, and indicates where the request should be sent in order to try again.

  • Application Sever: this is the place were differet features are implemented, adding value to the VoIP platform. Among common features you can find advanced call control applications like call blocking or call baring, prepaid system, interactive call routing.


Media Servers (non-SIP)

It is worth noting that everything we have convered up to this point does not allow for many of the traditional functions we assoaciate with a telephone service. What about IVR's, or Voicemail? Where are the auto-attendants, and the music on hold features? Well this is where a media server comes in.

In order to have an active control of what happens during a call, a device has to be 'in the media stream', as it is often called. This means a separate network device has to act as a SIP UA in order to begin a session, and then can control the channel accordingly. This is how voicemail and many other features of its ilk operate.


SIP - In action

The best way to learn a new protocol is to study it in action. The following examples show some common transactions and dialogs created using SIP, and they demonstrate how SIP reqests and responces are interchanged. This will hopefully put OpenSER's job as a SIP Server application in perspective.


REGISTER

The REGISTER method in SIP, is a request that initiates a transaction with a regsitrar server, in the manner depicted below:

Figure 1. SIP Registration example

This demonstrates the function of the registrar entity in simple terms. The UA informs the registrar of its location, allowing the server to maintain a record (valid for a pre-determined duration) of which IP address matches that SIP URI (Uniform Resource Indicator). In a more practical model additional information would be exchanged, for purposes like authentication.


INVITE

An INVITE is a SIP request method a UA would use to initiaite a session with another party. A simple example is shown below:

Figure 2. SIP INVITE example

This demonstrates the initial message; the INVITE, being sent in an end-to-end model. The recieving UA reacts to the INVITE by sending a '180 Ringing'. This means it is responding with a specific SIP response code, as detailed in the SIP RFC (response code 180). The text attached to that response code is arbitrary, but often identical across platforms and implementations.

Once the use picks up the handset (i.e. accepts the call), a response with the code '200' is sent. This is always used as an 'OK' when used in response to a SIP request, and means that the request has been accepted.

The arrival of this 'OK' message from the callee is confirmed by the caller, by the use of another SIP request method; an ACK, and the media session can begin.

We left out all security, encryption, routing, timeouts, and the hundreds of other possiblities that can cause a SIP INVITE transaction to differ from this model, but as a bare minimum, all SIP sessions will have this as a minimum INVITE transaction to set up a session.


Session initiation with OpenSER

We've seen an example of the fact that SIP can operate in an end-to-end fashion, but where does OpenSER fit into this picture? An example of the same basic INVITE transaction is show below, but this time using OpenSER as a stateless proxy. Dont worry if you dont know what stateless refers to in this context, we'll explain later.

Figure 3. INVITE with stateless proxy

As you can see, a SIP proxy does not need to understand a SIP message in order to operate; it merely forwards them on. Typically a proxy will perform some kind of authentication, and can be separated, locically, from a UA, in three ways:

  1. It never issues requests (for those taking note, the CANCEL method is the exception to this rule)

  2. It has nothing to do with the media

  3. It only operates on message headers, and does not concern itself with message bodies

A stateless proxy does not implement any timers, nor will it re-transmit any messages that have not had a response. A stateless proxy wont even keep track of a SIP transaction. It is perfectly happy to be removed from the chain of communications when it offers no additional value to the process, as identified here with the end-to-end transmission of the ACK

The consequences of this mean that if you want to offer VoIP services such as presence, music on hold, serial or parallel forking, or the many other things OpenSER is capable of, then we have to operate in a stateful way. A stateful transaction can be demonstrated by altering the previous example to the image show below:

Figure 4. INVITE with stateful proxy

Not only does the ACK now route via OpenSER, but furthermore, through use of the Record-Route header, all future SIP messagess will go via the server. This allows OpenSER to provide useful features, such as being able to tell whether a request was answered or not, or being able to fork two requests from one invite, responding accordingly and separately to each individual response.

Okay, so what is all this talk about 'transactions' and 'dialog's'? And when we say something is 'stateful', do we mean 'transactionally stateful' or 'dialog stateful'? Well its an important concept in SIP.

A transaction starts with a SIP request (such as an INVITE), and ends with a 'final response', which can be one of a variety of SIP responses. In between a request and its final response, there can be a number of provisional responses (or none).

A dialog can be thought of as a sequence of transactions. it is representative of a sip relationship between two end-points, and it is common to think of a regular phone call, from the moment you dial the number, to the moment one party hangs up, as a dialog.

Note

OpenSER is a transaction satateful proxy. It is not dialogue stateful. Therefore it cannot, in its native state, know when a particular session has been terminated.


NAT and Firewalls

The following sections discuss some of the issues surrounding the interoperation of SIP across open networks, including NAT traversal and the various methods of security that SIP allows for. This section assumes a basic understanding of the concepts behind NAT.


Network Address Translation (NAT) and SIP

Network Address Translators modify the IP address and port information for packets traversing from one network to another. In its most typical incarnation, this is to used to manage private network ranges, and allow them to interract with publicly routed networks.

There are several 'points of impact' where SIP finds NAT problematic, and it is not merely limited to NAT. RTP also has problems with NAT. Because SIP packets go out from a NATed client with their private (and un-routable) IP addresses coded into the message headers and SDP bodies, they are not processed by a NAT device, that operates only on the IP packets as they pass by. This then means that when the packets get to their destination, they are processed and responded to using completley useless source address information.

3 major implications of NAT

  1. The VIA header problem: Responses to requests cannot he be routed back ot the originating party, as the supplied addressing information is not globally routable.

  2. The CONTACT header problem: This refers to the fact that future requests would be routed incorrectly, again due to non-routable addresses being supplied.

  3. The RTP problem: When the globally routable UA sends RTP traffic to a NATed UA that it has established a session with, the RTP traffic will never arrive. this is also known as The one-way audio problem.

There are several solutions to choose from to allow SIP to traverse NAT effectively. None of them is ideal, and much of it is external to SIP. The following sections refers to the three main problems caused by SIP (listed above), and discusses the techniques applied within the protocol, and common third party solutions, to the problems.


The Via header problem

This is solved within SIP. When a message arrives at a SIP server or UA, a comparison is made between the address the packet came from, and the one that is listed in the via header. If there is a difference, then the correct IP address (the one from which the packet originated from) is written as a parameter 'recieved=', and is added to the via header.


The contact header problem

This is a similar problem to the Via header issue, and is solved in the same way, updating the contact header instead. The contact header is referred to for communications that occur some time after an original request (such as BYE's or re-INVITE's), and this can cause additional problems.

NAT bindings are kept active on the NAT device for only a finite amount of time if SIP is being transported over UDP. This is not a problem if TCP is used to transport SIP, but if UDP is used, then there is only a finite and small operating window for each nat binding.

OpenSER has functions that can address this issue, making sure NAT mappings are kept active, and these are demonstrated in Part II.


The RTP problem

For instances where only one UA is behind a NAT device, symmetric NAT can be used. This effectively synchronises the two RTP streams; the recipeint of the successful RTP stream (i.e. the globally routable UA in the session) transmits its RTP stream using the source IP of that RTP flow, ignoring the one that SIP has told it to use.

For cases where both UA's are behind NAT, then solutions outside of SIP and OpenSER must be used.


Other approaches..

One such appraoch to traversing NAT is to employ the use of a B2BUA or a dedicated RTP Proxy. This means that each NATed UA then routes its traffic to the same publicly routable device, which passes the audio stream on to the required end-point.

The obvious disadvantages of that are that it breaks one call elg into two, thus using more bandwidth. It also introduces a single point of failure into the SIP network. its advantages include the ability to actively manage and control the media stream, thus enabling applcations such as voicemail, IVR's, call accounting, and more. An example of the use of a B2BUA in this model is show below:

Another common solution is the Simple Traversal of UDP through NATs (STUN) protocol. This, in essence, uses a searate device at a globally routable location to enable SIP UA's to identify the presence and type of NAT's that it must traverse to get to a publicly routable network (can be read as 'the Internet').

STUN allows for security, and does not suffer many of the drawbacks the RTP proxy does. High availability can be achieved through use of DNS SRV records, and it still enables SIP UA's to establish a session directly.


Security and SIP

The forms of authentication used with SIP in OpenSER are authentication and encryption.


Authentication

This operates using MD5 hashing algorithms on a shared key, which is supplied via the challange/response mechanism required for authentication in SIP and OpenSER.

A request is challanged using SIP methods 401 or 407 (Authentication Required, and Proxy AUthentication Required, respectively). The request is then re-tried using the correct credentials. SIP UA's often cache the credtials required in order to avoid the overhead of further challange/response exchanges for future requests.

The call flow example below demonstrates OpenSER providing an authentication challenge for a UA transmitting an INVITE.

Figure 5. Authentication example with OpenSER


Encryption

As SIP is a text-based protocol, encryption prevents information contained in SIP messages being read by parties not involved in the SIP dialog. Transmission Transport Layer Security (TLS), and IP Security Protocol (IPSec) are methods of achieving a completely secure medium between two SIP endpoints involved in a dialog. SIP is encapsulated in IPSec tunnels, and the use of TLS has been extensively integrated into OpenSER's capabilities.

The message body of a SIP message may also be encrypted, allowing for security of all but the SIP message headers. This offers flexibility as the SIP message can traverse any standard proxy and the message will be correctly processed and routed, as a proxy will never need to analyse the message body.


OpenSER architecture


OpenSER Core

OpenSER is built using a modular architecture. It's core, which still retains great similarity to that of SER, is small, fast and stable. Also like SER, the majority of its functionality originates through the use of loadable modules, and is all centrally configured using the text file openser.cfg

The important parts of the core are the SIP parser, transport layer management, memory and locking manager, database API, mangement interface and configuration interpreter.

The SIP parser implemented in OpenSER does incremental parsing. It means that it parses as much as needed to process the SIP message. Initialy only the first line and the mandatory headers (like first Via, To header, ...) are parsed. Once a component need access to other headers, the parser goes further until finds them.

OpenSER supports all the network transports required by the RFC: UDP, TCP and TLS. The management of connections, sending and receiving SIP messages as well as DNS queries are done in the core.

To optimize the communication between OpenSER processes, there was added a self system to manage the private and share meory. This improves the speed of processing quite a lot on common Operating Systems and architectures. The system for sychronization is also optimized for known CPUs. In special cases of unknown architecture, OpenSER can be configured to use the standard POSIX/SysV managers for memory and locking.

The set of database operations required within OpenSER is pretty much limited. To be able to easily replace a database engine with another, OpenSER core exports an abstract DB interface with can be implemented as module. At the time of writing this document, OpenSER includes support for MySQL, PostgreSQL and UnixODBC, plus a tiny DB module that works with plain text file, namely dbtext.

The managemnt interface is designed to allow access to server's internals, either from the local system, via command line, or, remotely, via network connections. Also, an administarator can issue commands to the server to dynamically update the state or change the behavior.

The configuration file of OpenSER looks pretty much similar to a script witten in a programming language. The script is executed for each SIP message that comes in the system. The decision of what to do with the SIP message is actually the resut of interpreting the scripy.


Configuration: openser.cfg

The openser.cfg configuration file has 7 mains sections. The first three are static, and the last four are used each time OpenSER processes a SIP message. In this way it combines both static settings and a dynamic programming environment.

When you create the configuration file, you will spend more time “programming” then setting initialization variables. It may be easier for you to consider the configuration file (openser.cfg) as a "program".

  1. Global Defintions

    These are settings for OpenSER that affect the core application. Configuration attributes here are include things like debug level settings, IP addresses to listen on, and DNS settings

  2. Module Definition

    Here is where you specify the modules which youw want OpenSER to include. They are shared object files which are processed upon OpenSER's execution.

  3. Module Configuration

    Many of the modules OpenSER has available to it often require certain parameters to be set in order for the module to operate correctly. There are also many optional configurations that are available, which can cause the module to operate in a different way.

  4. Main Route Block

    This is where all the 'routing' and processing of incoming SIP messages starts. You can read it like a C program, in that it executes top-down, and makes calls to secondary route block (like functions).

  5. Secondary Route Block(s) (OPTIONAL)

    These offer a way to segment the message processing. These are commonly used like a subroutine would be; to handle specific tasks. You could implement a specific route block to handle all INVITE requests for example, or all messages destined for a PSTN gateway.

  6. Reply Route Block (OPTIONAL)

    This allows you to define a specific way of handling responses to SIP messages.

  7. Failure Route Block (OPTIONAL)

    This allows you to define a specific way of handling failure conditions, such as time-outs.

Note

Not all of OpenSER's commands and modules are avialable to be used in the Reply Route Block or the Failure Route Block. Refer to the modules documentation as to where it can be used within openser.cfg

OpenSER's configuration file can become quite unweildy, and as such, you may wish to look at using the M4 macro processor to make your configurations easier to read and edit, and simple to read.


OpenSER modules

OpenSER has a wealth of functionality that can be exported from the many modules that you can enable from within your openser.cfg. This allows you to run only the mdoules you need for your particular situation, keeping your SIP server lean, fast, and secure.

A complete ist of modules, correct as of the current stable release of OpenSER, is supplied in Appendix B. Do not try to remember what each module does at this point, but scan over it to get an idea of what OpenSER's modules are capable of.


Before you begin

The following sections exemplify several subsets of the total functionality OpenSER offers. These sections are arranged in some order, starting with the most simple and common tasks. The latter chapters build on this basic functionality, offering alternatives where available, to demonstrate some of the more advanced features available.


Third Party Applications

All of these scripts herein are built to operate on the current stable release of OpenSER (see document header for version number), and will function correctly by simply copying and pasting the examples as standalone openser.cfg files for your own servers. If you are using any third party applications such as databases or authentication mechanisms, you will need to ensure that these are set up accordingly before running OpenSER. Wherever possible, however, we do try to walk you through the entire process of getting the full solution up and running.

OpenSER is all about flexibility, and to demonstrate how well it works with different applications, we've given alternative solutions for common functions (e.g. for authentication we've shown database-driven and RADIUS based configurations). Unfortunately, there are far too many different applications that interoperate with OpenSER to be able to cover every option comprehensively, so we've tried to pick the most commonly used applications, and specifically those which are Open Source and are offered under the GNU GPL.


Troubleshooting

Many of you will want to use the examples here to add functionality to existing systems, and as you merge the scripts into your own, you will undoubtedly run into some problems. We'd like you to take a minute or two to read this section, which gives you information on how to find and fix problems yourself, how to formulate requests for others to help you, and where to find help.


Core logging in OpenSER

OpenSER, by default, logs to syslog. Alternatively, it can write log and debug information to STDERR. You can also alter the verbosity of openser's logging, and this can all be defined within the openser.cfg file, or at startup on the command line. The following table summarises these commands:

Table 1. Logging Options within OpenSER

Some people set up their configuration files so that they can easily swap between development and production verbosity, as shown below. Note that as STDERR is commonly piped to the console from which the program was originally executed, that it is important the OpenSER is not allowed to fork when executed, to ensure all the program output is retained for troubleshooting.

debug=3
fork=yes
log_stderror=no

/* Comment out the above lines, and uncomment the three lines below to enter debugging mode
debug=7
fork=no
log_stderror=yes
*/

You might also find that it is useful, in development systems, to prevent openser performing DNS and reverse DNS lookups. This can be set upon execution or within the openser.cfg

dns=no          # (cmd. line equiv: -r) - default is "no"
rev_dns=no      # (cmd. line equiv: -R) - default is "no"

Note

You can also create custom syslog setup's, with output going to separate files which can then be managed using log rotation software.


Logging Modules to use with OpenSER

Okay so you have a way for OpenSER to pipe out its own information to you, but what if it doesnt tell you what you need to know? Quite often, you will want to know about a specific transaction that is being processed, or you might want to know about the execution of a particular function you have.

OpenSER's 'xlog' module offers you the ability to output messages (to syslog or STDERR, as defined above). Moreover, it can also output the values of any 'pseudo-variables' that OpenSER has set. You can enter lines, such as the one below, into your openser.cfg at any point.

xlog("L_INFO", "SIP Request: method [$rm] from [$fu] to [$tu]\n");

.. which in turn will produce output specific to the particular SIP message OpenSER is currently processing, so you could expect to see something like:

SIP Request: method [INVITE] from [me@mydomain.com] to [you@yourdomain.com]

Hello World

Intro, script, walkthrough, and modus operandi


Objectives

The objectives of this chapter are:

  1. Establish a SIP Server on the network

  2. Ensure that the SIP Server makes some basic checks about the SIP emssages it processes

  3. Enable the SIP Server to route SIP messages so local SIP phone's are capable of making calls to each other

The network diagram below demonstrates the topolgy in which OpenSER is to operate.

Figure 1. Hello World - Network Diagram


openser.cfg

The following script is available for download from <insert URL here>.

# SECTION 1 - GLOBAL DEFINTIONS

debug=3 (1)
fork=yes (2)
log_stderror=no (3)

/* Uncomment these lines to enter debugging mode (4)
fork=no
log_stderror=yes
*/

listen=192.168.1.99 
port=5060 (5)

dns=no
rev_dns=no (6)

children=4 

# SECTION 2 - MODULE DEFINTION 

mpath="/usr/local/lib/openser/modules/" (7)

loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "textops.so"
loadmodule "xlog.so"

# SECTION 3 - MODULE CONFIGURATION

modparam("usrloc", "db_mode", 0) (8)
modparam("rr", "enable_full_lr", 1) (9)

# SECTION 4 - MAIN ROUTE BLOCK (10)

route{

    if (!mf_process_maxfwd_header("10")) { (11)
        sl_send_reply("483","Too Many Hops"); (12)
        exit; (13)
    };

    if (msg:len >=  max_len ) { (14)
        sl_send_reply("513", "Message too big");
        exit;
    };

    if (method=="REGISTER") { (15)
        record_route(); (16)
    };

    if (loose_route()) { (17)
        append_hf("P-hint: rr-enforced\r\n"); (18)
        route(1); (19)
    };

    if (!uri==myself) { (20)
        append_hf("P-hint: outbound\r\n"); 
        route(1);
    };

    if (uri==myself) { 
       
        if (!lookup("location")) { (21)
            sl_send_reply("404", "Not Found"); (22)
            exit;
            };
        append_hf("P-hint: usrloc applied\r\n"); 
    };

    route(1); 
}

# SECTION 5 - SECONDARY ROUTE BLOCKS

route[1] {
    if (!t_relay()) { (23)
        sl_reply_error(); (24)
    };
    exit;
}

# SECTION 6 - REPLY ROUTE BLOCKS

# SECTION 7 - FAILURE ROUTE BLOCKS (25)

Commentary

Sets the debug level for OpenSER. Valid values are 1-9 (low-high). 3 is deemed an acceptable level for production systems Tells OpenSER whether to fork upon its initial execution or not. It is useful tos et this to 'no' when debugging, so all output is sent to the console.

Note

If you have configured init to start OpenSER, fork=yes must be set, as otherwise it will not daemonise and return control of the system to init

This will log to the systems Syslog application as set currently (/var/log/messages, typically, although that can be altered. Setting it to 'yes' outputs all server messages to STDERROR The C style commenting (using /* and */) here denotes that these lines are ignored by OpenSER when the openser.cfg is processed at run-time. 'Commenting out' the first three lines, and uncommenting these two, enable a 'debugging mode' in that the OpenSER server will not fork at run-time, and will output all errors to the console, allowing for easy debugging. These two paramteres; 'listen=' and 'port=' specify which IP addresses and port for OpenSER to listen on. If no values are entered, it will listen on all available addresses, and will use default port 5060. Multiple 'listen=' statements are allowed for multi-homed hosts. These two lines tell OpenSER not to look-up its address from DNS (or perform reverse DNS lookups). Useful for debugging, but should be enabled for production systems. This specifies the module path to be used for all modules listed in openser.cfg. A useful way of avoiding the need to specify the path for each and every module defined in the following section.

The following section names each module that is required for the operation of openser. Each module is responsible for certain types of logic, and the OpenSER core on it own is not particularly useful in real workd scenario's without some of the modules available. The modules listed here are common ones used as part of a typical OpenSER SIP server, but for more information, visit http://www.openser.org/docs, or refer to Appendex B

This sets a paramter called 'db_mode', which is exported from the 'usrloc' module. In reality, it tells OpenSER not to use a database such as MySQL for storing user-location information. This module is responsible for storing and maintaing contact information (AOR) suppled by SIP UAC registration Another module paramtere is set here, this time one that is part of the record-route module. This is a workaround for older SIP UA's that don't properly handle RFC3261 headers; they dro the ';lr' tag in the record-route header, because there is no value associated with it. Every SIP message that comes into the system starts here; at the beginning of the main route block. 99% of the functionality you require from a SIP server stems from this next section.

The route block works in a sequential model, top-to-bottom. Secondary route blocks are called from the main route block, and once the processing logic gets to the end of this main route block, all processing on that particular SIP message ends.

Okay, we are now actively processing the message. The first few things we typically want to do here is execute some basic sanity and security checks.

This first test checks the number of times the current SIP message has been forwarded. If the value returned is greater than the value we have specified, a certain action is taken...

sl_send_reply() is an exported function from the SL module. It instructs OpenSER to respond to the sender of the current SIP message, in a stateless fashion (i.e. it will not wait for a response, set a timer, or retransmit any messages). The message we have asked it to respond with, is the SIP response message of type 483

The text string we specify alongside the response type, in this case "Too many hops", is arbitrary. That is, it can be anything you like. You can use this ability for developing your own unique UAC-side applications.

exit().. a short and sweet core function and it means what it says. Stop all processing and exit the main route block. Next message please! msg:len returns the length of the current message, and max_len is a predetermined value (set within openser source code(?)). If the current message is too big, then an error response is sent, and processing of the message ends. This is an example of the many tests you can perform within the openser configuration file. Here we are performing a string match of the method type. As with many things with OpenSER, there are often several ways of accomplishing the same objective, and there is a function that performs bit-level checks to ascertain the method of a SIP message (is_method()) If we reach this part of the code, then the SIP message is a REGISTER request. We do need to do more than just issue this record_route command, but we separate it here as it is a basic initial requirement.

The record_route function causes OpenSER to insert its own address as a via header entry in the SIP message it is currently processing. This forces all further communication regarding this SIP transaction (that is, all intermediary and final responses to this SIP request method), to go via OpenSER. This is especially important for SIP request methods such as BYE's, which OpenSER will often need to keep track of in order to maintain accurate CDR's (Call Detail Records)

Loose Routing is defined in RFC 3261 as a means by which SIP servers soute SIP messages. Loose Routing is accomplished by using the same R-URI as the SIP message is passed on, and the Proxy (OpenSER in this case) will use the information supplied in the route headers of the sip message in order to know where to pass the message on to (i.e. it passes the message to the next route header, deleting its own entry in the list).

From this, you would be correct in assuming that the loose_route() function within OpenSER will return true if route headers are present. It also removes any route header entries that match OpenSER's own address(es).

Putting what we now know together, it is worthwhile pointing out that ecord_route(), previously discussed, adds route headers to a message (whether it has them already or not). Therefore, if your OpenSER calls record_route for SIP messages (i.e. you want all signalling to go via OpenSER), then almost all in-dialog messages (i.e messages relating to, or responsing to, a specific dialog or transaction), will be loose_routed by OpenSER.

In strict routing, a proxy must use the first URI in the Route header field to rewrite the Request-URI, which is then forwarded

append_hf() is a useful function within openser.cfg, that can be used to add a header field to the SIP message currently being processed. Some header fields are optional, and some a required to communicate with specific services.

The P-hint extension headers that are applied here (and later in this document), serve as informative tag's for OpenSER and future proxies in the chain of communication. As this are optional headers, the UAC will drop them if it does not understand them.

Our first call to a secondary route block. There is no designated or recommended way to use secondary route blocks, but it is a good idea (as with most things computer-related) to produce a modular system. For example, you may wish to put all NAT handling into one secondary route block. You may want to have one route block to take care of all INVITE messages.. it really is up to you.

One thing to note is that depending on what part of the configuration file you are in, certain commands may not be available to you. You should check this with the module documentation that is provided at http://www.openser.org/docs

This is a typical comparison operator that you will find very common within most openser.cfg scripts. The exclamation mark preceding the comparison statement, denotes a logical NOT operation upon the statement (read "If uri is not equal to myself"). The uri referenced here is the request URI.

the core function 'myself' in this comparison, compares the uri agains the list of hostnames, IP addresses, and aliases that have been set already in the global configuration section of your openser.cfg. Note: this function does not return a match against domains held in a database as part of the Domain module.

Therefore you can, with this statement, effectively establish whether a message is addressed to OpenSER itself or not.

The lookup() function searches OpenSER's user location tables, and tries to establish if the SIP message is destined for a local user to OpenSER (i.e. one that has registered to it) sl_send_reply() is a function exported from the sl modeule (the module responsible for state-less message transfer). This instructs OpenSER to send a reply to the source address of the SIP message, in a stateless fashion (i.e. no timers will be maintined in order to retransmit the request if an ACK is not recieved by OpenSER, etc). The type of messages you can send with this kind of function cover the majority of all available SIP messages. This specific one is a 404 not found

Note: many SIP return codes are comparable to thos of the HTTP protocol, demonstrated here by the 404 error code.

t_relay is a transactional-stateful method of message transfer. It maintains status of the transaction, and will relay any error messages from the donstream recipient of the initial message, upstream to the originating UAC. It maintains timers to ensure that the transaction is managed correctly. sl_send_error() is a function that is an example of what is Good Practice in configuring and running OpenSER. This function will transmit the last internal error generated by OpenSER (i.e. if the preceding t_relay statement failed internally, the resulting error would be the one which would be reported on here), back upstream to the originating UAC. No failure routes or reply routes have been defined here, but their position has been denoted for clarity.

Usage

To test out this configuration:

  1. change the listed IP address to match your network

  2. save your configuration to /usr/local/etc/openser/openser.cfg (which is the default location for the installation process. Make sure you update this path with the correct details if you have installed to somewhere other than the default location)

  3. check the syntax of your configuration file:

    /usr/local/sbin/openser -C

    This is will report any errors you may have, which you can then address.

  4. Run openser:

    /usr/local/sbin/openser
  5. configure your SIP phone's to register to the correct IP address (we do not perform authentication yet, so you do not need to enter passwords if prompted). We assume all your phones are on the same local network as shown in the topology diagram at the beginning of this section.

    Also, you are free to make up whatever extension name or number (as long as it is compliant with SIP standards), for each of your IP phones.

  6. make calls between phones, using the extensions you have made up.


Summary

This first script shows you how you can simply and efficiently handle SIP messages with OpenSER. The functionality provided, in the order in which it is executed, is as follows:

  1. Sanity Checks

  2. Force future requests to go via OpenSER (if the SIP message is a REGISTER request)

  3. Comply with the loose routing requirements of SIP

  4. Define if the message is destined for an address other than one OpenSER occupies itself, if so, insert some information into the message, and then send to the default outbound route block

  5. If the message is destined for one of OpenSER's addresses or aliases (i.e. it could be one of the users local to OpenSER),, then search the current userbase for a matching URI. If a match is not found, then send an error back to the originator of the message. If a match is found, then tag the message with appropriate information, and then send to the default outbound route block

You'll notice there are many things that should be implemented that are absent in our first script. For example, we have no authentication, and we effectively relay messages for all and any requests, to name but two flaws


MySQL and Authentication

Intro, script, walkthrough, and modus operandi


Objectives

The objectives of this chapter are:

  1. Provide authentication mechanisms for users, when they register

  2. Add database support for the logging and integrate the authentication process

The network diagram below shows the updated topolgy in which OpenSER is to operate.

Figure 1. MySQL and Authentication - Network Diagram


openser.cfg

This config is available for download <url>

# ----------- global configuration parameters ------------------------

debug=3            # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no    # (cmd line: -E)

/* Uncomment these lines to enter debugging mode 
fork=no
log_stderror=yes
*/

check_via=no
dns=no
rev_dns=no
port=5060
children=4

# --- module loading

mpath="/usr/local/lib/openser/modules/"

loadmodule "mysql.so"(1)
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "auth.so"(2)
loadmodule "auth_db.so"(3)
loadmodule "xlog.so"
loadmodule "mi_fifo.so"(4)
loadmodule "textops.so"

# --- setting module parameters

# -- FIFO params --

modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo")(5)

# -- DB url --

modparam("usrloc|auth_db","db_url","mysql://openser:openserrw@localhost/openser")(6)

# -- usrloc params --
modparam("usrloc", "db_mode", 1)(7)

# -- auth params --
modparam("auth_db", "calculate_ha1", yes)(8)
modparam("auth_db", "password_column", "password")(9)

# -- rr params --
modparam("rr", "enable_full_lr", 1)

# --- main routing logic
route{
if (!mf_process_maxfwd_header("10")) {
  sl_send_reply("483","Too Many Hops");
  exit;
};
if (msg:len >=  2048 ) {
  sl_send_reply("513", "Message too big");
  exit;
};

if (!method=="REGISTER")
  record_route();

if (loose_route()) {
  append_hf("P-hint: rr-enforced\r\n"); 
  route(1);
};

if (!uri==myself) {
  append_hf("P-hint: outbound\r\n"); 
  route(1);
};

if (uri==myself) {
  if (method=="REGISTER") {
    if (!www_authorize("", "subscriber")) {(10)
      www_challenge("", "0");(11)
      exit;
    };

    save("location");
    exit;
  };

  if (!lookup("location")) {
    sl_send_reply("404", "Not Found");
    exit;
  };
  
  append_hf("P-hint: usrloc applied\r\n"); 
};

route(1);
}


route[1] {

if (!t_relay()) {
  sl_reply_error();
};
exit;
}

openserctl - An introduction to the Mangement Interface

As of OpenSER 1.2, the management interface, which is archtecturally based around a FIFO implementation, also with support for XML-RPC, has been presented as a separate module.

A useful tool that ships with OpenSER is 'openserctl'. This tool makes use of the MI interface, and can be used to deliver commands to OpenSER, such as adding user information, querying status, and injecting commands. This utility can also interract with openser's many database back-end components, but of course must be told exacly what to connect to and how to connect. This si done via a configuration script called 'openserctl', and is located by default in the same directory as default openser.cfg. The settings we have used for this example, is outlined below:

 $Id: openserctlrc 1734 2007-03-02 17:41:38Z bogdan_iancu $
#
# openser control tool resource file
#
# here you can set variables used in the openserctl

## your SIP domain
 SIP_DOMAIN=mydomain.org

## database type: MYSQL or PGSQL, by defaulte none is loaded
 DBENGINE=MYSQL

## database host
 DBHOST=localhost

## database name
 DBNAME=openser

## database read/write user
 DBRWUSER=openser

## database read only user
 DBROUSER=openserro

## password for database read only user
 DBROPW=openserro

## database super user
 DBROOTUSER="root"

## type of aliases used: DB - database aliases; UL - usrloc aliases
## - default: none
#ALIASES_TYPE="DB"

## control engine: FIFO or UNIXSOCK
## - default FIFO
# CTLENGINE="FIFO"

## path to FIFO file
# OSER_FIFO="FIFO"

## check ACL names; default on (1); off (0)
# VERIFY_ACL=1

## ACL names - if VERIFY_ACL is set, only the ACL names from below list
## are accepted
# ACL_GROUPS="local ld int voicemail free-pstn"

## presence of serweb tables - default "no"
# HAS_SERWEB="yes"

## verbose - debug purposes - default '0'
# VERBOSE=1

## do (1) or don't (0) store plaintext passwords
## in the subscriber table - default '1'
# STORE_PLAINTEXT_PW=0

As can be seen, you do need to set all the available parameters. The important ones for this stage of the tutorial are the database one's.


Nathelper and RTP Proxy

Intro, script, walkthrough, and modus operandi


PBX/PSTN Gateway

Intro, script, walkthrough, and modus operandi


Call Forwarding

Intro, script, walkthrough, and modus operandi


Scalability and Resilience

discussion of approaches for resilience and HA


Discussion

The scalability and resilience of OpenSER is restricted somewhat by the nature of SIP. We will break this topic down into separate sections, discussing approaches, and outlining key issues of concern.

  1. Registrar


Software Installation and Configuration

This section introduces the applications referenced in this guide, and discusses any setup processes required.


OpenSER

TLS and no-tls, openserctl (BDB and non DB)


MySQL

schema required for the examples. links to existing docs.


FreeRadius

links to existing tutorials, or maybe embed tutorial in?


Reference Information

for everything relevent but too bulky to include in the main document


OpenSER Modules

The following table provides a brief description of the available modules for OpenSER that are distributed with the OpenSER source

Table 1. OpenSER Modules