This three-part article reviews the SIP entities that identify a user, a handset or service and looks at how they are used to register devices, authenticate and identify users and route calls. The subtle differences in the use of these entities can be confusing, even to an experienced SIP technician. Handling of the entities in a live ITSP environment, especially when dealing with a mix of simple single-line devices alongside multi-channel SIP trunks, is quite challenging.
In part 1 of this article we will review the basic concepts of device identification and authentication. A more detailed examination of the registration process then follows. Part 2 looks at the handling of inbound calls and part 3 at outbound calls. Throughout, I will consider the mechanisms used for handling and securing requests to and from simple single-line devices and SIP trunks, providing examples of code and explanations to assist anyone wishing to use OpenSIPS as an ITSP front end server.
The Internet Telephony Service Provider (ITSP) Model
The inspiration for this article came from working on a project for a North American VoIP service provider. My client wanted to use OpenSIPS as a front-end SIP Proxy server for a range of different customers. The devices used by his customers ranged from a simple single-line IP phone to an Asterisk (or similar) IP-PBX. In other words he was providing a mix of Centrex-style hosted telephony services and SIP trunks through a common portal as illustrated in figure 1.
Figure 1
This model for an ITSP front-end server is a useful reference for the following discussion of SIP identification entities because it covers the majority of cases that will be encountered in the real world.
Key Entities
There are four key entities associated with a SIP user account:
- SIP User ID or username
- Auth User ID or Auth-ID
- DID (in the UK, this is known as DDI) associated with inbound calls to the SIP device
- Caller ID associated with outbound calls from the device
The last item, Caller ID, will not always be explicitly defined. However, there is often a field called “Display Name” and this is generally used in conjunction with the SIP User ID to construct a SIP header that is subsequently used for caller identification.
How are these entities configured on a typical IP Phone?
The configuration parameters for most IP phones and VoIP adaptors can either be set from a text/XML file (often by reading the file from a TFTP server) or you can configure the settings directly on the device using its web interface.
Figure 2 shows the web-based settings for an Aastra IP phone.
Figure 2
In the above illustration, the SIP User ID (labelled Phone Number) has been set to 1003, the Caller ID is set to 01727221221 and the Auth-ID is set to JBond007. These entities can all share the same value or they can be different, as in this example.
Figure 3 shows a similar section from the configuration screen for a Linksys ATA.
Figure 3
Here the SIP User ID is set to 01727238471 and the Auth-ID is 2468. There is no field for Caller ID, but there is one for Display Name.
Anatomy of a SIP request
To understand how the account entities are transmitted to a SIP server, you will need to have some understanding of the structure and components within a typical SIP request. By way of an example, here is an edited copy of the REGISTER request from the Linksys device:
REGISTER sip:123.45.67.89 SIP/2.0 Via: SIP/2.0/UDP 192.168.0.12:5076;branch=z9hG4bK-6fd12dac;rport From: Smartvox Test <sip:01727238471@123.45.67.89>;tag=224430a02dcdbc49o0 To: Smartvox Test <sip:01727238471@123.45.67.89> Call-ID: 217edcfa-3c466a22@192.168.0.12 CSeq: 65321 REGISTER Authorization: Digest username="2468",realm="123.45.67.89", nonce="5022822e324da6",uri="sip:123.45.67.89",algorithm=MD5, response="ba0efcfa2594fb1b3d8f11dd892d0221",qop=auth,cnonce="2798e295" Contact: Smartvox Test <sip:01727238471@192.168.0.12:5076>;expires=900 User-Agent: Linksys/SPA3102-5.1.10(GW) Content-Length: 0
The entities defined in the configuration screen of the device are used to populate various headers in the SIP request. For example, the From header has been populated from the “Display Name” field and the “User ID” field. The field labelled “Auth ID” is used only in the Authorization header.
Other SIP packets have a very similar construction, but there are some subtle differences between REGISTER and INVITE requests so here is an example (slightly edited) of an INVITE request:
INVITE sip:2456@192.168.0.67:5060;transport=udp SIP/2.0 Via: SIP/2.0/UDP 192.168.0.12:5076;received=192.168.0.12;rport=5076 From: Smartvox Test <sip:01727238471@123.45.67.89>;tag=4dd69cbbee9a30a0o0 To: <sip:2456@123.45.67.89> Call-ID: 5d590717-b39569f4@192.168.0.12 CSeq: 102 INVITE Contact: Smartvox Test <sip:01727238471@192.168.0.12:5076> User-Agent: Linksys/SPA3102-5.1.10(GW) Content-Length: 442 Content-Type: application/sdp
Of particular interest in the above example is the format of the first line. The number 2456 was the number that was dialled and the component “sip:2456@192.168.0.67” is called the Request URI (or R-URI for short). Also notice how the To header in the REGISTER request uses the ‘SIP User ID’ of the registering phone, whereas the To header in the INVITE request shows the number that was dialled, 2456.
SIP Proxy ‘use cases’
The use-cases associated with a SIP user account that must be handled by a typical SIP Proxy server include:
- Registration of the SIP device
- Routing of inbound calls to the SIP device
- Authentication of outbound calls from the SIP device
- Routing of outbound calls from the SIP device, including management of Caller ID information
It is possible to make some generalisations about which entities are most relevant to each of the above cases:
- Registration (a) uses SIP User ID and Auth-ID (see below and fig. 4)
- Routing of inbound calls (b) uses DID and SIP User ID (see part 2)
- Authentication of outbound calls (c) uses SIP User ID and Auth-ID (see part 3)
- Routing of outbound calls (d) involves use of the Caller ID (see part 3)
Several of the above cases are explained in more detail in parts 2 and 3 of this article, but in this part we will now take a closer look at SIP Registration.
Registration
It is important to understand that SIP registration is primarily a mechanism that allows a Proxy server to know the location (i.e. the IP address) of various end-user devices. This means that, while it may be essential for the receipt of inbound calls from the service provider, successful registration is not essential for the user device to be able to make outbound calls.
Most SIP Registrar servers will only accept a registration request if the user credentials match pre-defined values that are stored in a database. Each registration is given an expiry time – typically 30 or 60 minutes – after which the registration details are erased. This means the user device must re-register before the expiry time is reached, thereby resetting the timeout and ensuring the registration is always present in the location table.
The SIP registration mechanism
It is normal for Registrations to be authenticated by a challenge process. The registering device sends a REGISTER request with minimal credentials and the Registrar server sends back a “401 Unauthorised” response. The device then re-sends the registration request, but this time it adds an “Authorization” header containing a digest of user information and an encrypted version of the password (see the example SIP message earlier in this article).
Assuming the credentials correctly match those of a known user, the registration will be accepted and a record is written to the location table.
The registration process is illustrated in figures 4a to 4c below:
Figures 4a, 4b, 4c and 4d
Registration for SIP Trunks
The above description was for a simple SIP device like an IP phone or ATA. Registration may also be required for an IP-PBX using a SIP trunk. Note that only one registration is required for a SIP trunk even if it provides a conduit for many different DID’s and many simultaneous calls. The mapping of DID’s to a specific registration record in OpenSIPS is discussed in part 2.
SIP trunks do not always require registration – sometimes the IP-PBX is located at a static IP address and the Proxy server can be made aware of that address either using a static entry in the location table (i.e. one that never expires) or by some other table-based lookup controlled by the service provider.
IP-PBX’s like Asterisk (including FreePBX) allow for registration details to be entered – these are located in sip.conf or are added to a field in the setup screen for the SIP trunk.
OpenSIPS code to accept registrations
The simplest solution in OpenSIPS uses the “subscriber” database table to store a list of user credentials. It is also possible for the server to check the credentials against other databases using LDAP, Radius, etc.
When using the standard OpenSIPS subscriber table, be aware that the ‘username’ field in this table stores the value of Auth-ID, not the SIP User ID. The User ID is stored in the location table when a device registers, but it is not explicitly stored in the subscriber table.
If you want to use the subscriber table within a MySQL database, opensips.cfg must include code to load and initialise the following modules:
- db_mysql.so – permits storage of data in a MySQL database
- auth_db.so – functions & settings for authentication against user credentials in the subscriber table
- usrloc.so – settings to define the structure of, and connection to, the location table
- registrar.so – functions & rules used when accessing the location table
The opensips.cfg code, having identified a REGISTER request, would most likely send control to a route-block specifically designed to handle such requests. This block of code would authenticate the request and store details in the location table. Here is a snippet of code that is typical for the handling of REGISTER requests:
if (is_uri_host_local()) { if (!www_authorize("", "subscriber")) { www_challenge("", "1"); exit; }; if (!db_check_to()) { sl_send_reply("403", "Forbidden"); exit; }; if (!save("location")) { xlog("L_WARN", "**REGISTER: save failed for $ct.fields(uri)\n"); sl_reply_error(); } else { xlog("L_WARN", " REGISTER rcvd $si:$sp Contact=$ct.fields(uri)\n"); }; exit; } else { sl_send_reply("403", "Forbidden"); };
OpenSIPS Interpretation of the components in a REGISTER request
Headers in the REGISTER request are used during authentication or they are interpreted into data stored in fields of the location table. The following list summarises how different parts of the REGISTER request are inspected and used in a typical OpenSIPS registrar server:
- The R-URI usually controls where the REGISTER request was sent – most likely your server. It may be used in initial authentication checks such as is_uri_host_local().
- The To header defines the AOR (address of record) and populates ‘username’ and ‘domain’ fields of the location table
- The From header may be used during initial authentication checks
- The Authorization header contains the encrypted authentication credentials sent in response to a challenge (see steps 2 and 3 in the registration sequence shown above)
- The Contact header defines the contact URI of the registering device. It is an extremely important piece of data and is stored in the ‘contact’ field. This contact URI is used in subsequent INVITE requests to reach the registered device
- Call-ID and User-Agent headers will directly populate ‘callid’ and ‘user_agent’ fields
- The ‘received’ field in the OpenSIPS location table shows the address where the REGISTER came from in cases where this differed from the address in the Contact URI. Just to clarify, “address” here means both IP and port and can also include transport as a parameter.
What if the SIP User ID, Auth-ID and Caller ID are not identical?
Most of the time the User ID and the Auth-ID are both set to the same value. This keeps things simple. However, situations can arise where you may find it convenient to use different values. For example, a VoIP service provider may wish to allow a customer to use one username-password pair for authentication across several SIP accounts rather than having to give them different credentials for each account.
On simple SIP devices
The case for being able to use different User ID and Auth ID values is strongest when looking at simple SIP devices. This arises from the fact that the Caller ID on an outbound call will usually be set by the device to match the SIP User ID. Furthermore, if the device supports multiple lines or accounts, then ideally you want to assign each line its own unique User ID. At the same time, you may also prefer it if they are all able to share one Auth-ID and password. Clearly, in these circumstances it is preferable if the Auth-ID is not the same as the SIP User ID.
When the SIP User ID and the Auth-ID are different, the security check on the To header (included in the above OpenSIPS sample registration code) will fail. This is because the function db_check_to() checks to make sure the username given in the To header matches a known value in the subscriber table. Since the subscriber table contains Auth-ID, the check will fail whenever Auth-ID and User ID are different.
We will re-visit this issue in part 3 when we look at methods for setting Caller ID on outbound calls.
On SIP trunks
The facilities to set the Caller ID on an outbound call within most IP-PBX’s (including Asterisk/FreePBX) are usually extensive. Consequently, there is generally little or no reason to want to use different values for User ID and Auth-ID on a SIP Trunk registration. When an IP-PBX registers with the ITSP’s Proxy server, the User ID and Auth-ID are almost always identical.
Although I cannot think of a good reason to wish to do so, your IP-PBX should allow different values to be defined for SIP Trunk registrations. For example, in Asterisk, the register command in sip.conf actually supports a wide range of parameters including separate values for User ID and Auth-ID.
Asterisk documentation, taken from the optional sample sip.conf file supplied as part of the source package in version 1.6.1, shows that the full set of parameters available with the register command is as follows:
register => [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
Here is an explanation of some of these parameters:
- ‘transport’ – udp or tcp
- ‘user’ – the SIP User ID
- ‘secret’ – the account password
- ‘authuser’ – the Auth ID
Thus it is possible to specify different values for User ID and Auth-ID when Asterisk is registering a SIP trunk connection.
Unfortunately, if you use the sample OpenSIPS code given above and you specify different values for User ID and Auth-ID, the registration will fail. As with the simple SIP devices mentioned above, the problem is in the db_check_to() checks. We will re-visit this issue of differing Auth-ID and User ID in part 3, including a suggested solution to use in your opensips.cfg script.
Summing up
When I started writing this article, I planned to make it quite short – just covering a simple topic I thought. However, as I put ‘pen to paper’ it soon became apparent that the topic could expand almost as fast as the universe did after Big Bang. So it gradually went from a short one-part article to a long one, then a two-part article and finally a three-part one. I hope it will ultimately be useful both as an OpenSIPS beginners’ tutorial and a reference for more experienced coders.
As usual, feedback is welcome using the coloured voting buttons below or leave a comment. However, you may wish to reserve judgement until you have read the other two parts. Part 2 examines inbound call handling while part 3 looks at how outbound calls can be handled in an OpenSIPS Proxy server.
Very nice; A++
First time ever I’m able to understand the difference between SIP user and Auth ID.
Brilliant 🙂
good