OpenSIPS and SIP PATH Extension



RFC 3327 (SIP Path Extension) specifies a way to discover and record the sequence of proxies between the UA and the registrar. The constructed routing path will be stored in the database of the registrar along with the corresponding contact address. Each intermediate proxy (NOT terminating routing point) that wants to stay in the routing path, inserts its URI as a new “Path” header field (or as value in the “Path” header field). This mechanism is applied only to requests that are transiting or originating in the home domain. The constructed routing path will be carried as pre-loaded Route set in the upcoming initial requests. This mechanism is similar to the operation of Record-Route mechanism in dialog-initiating requests (In-dialog/Sequential requests) and it can be combined with it (Example – Invite Transaction).

In this article i will talk about SIP Path extension in OpenSIPS context.


Assume we have this scenario:

UA1 – – – – P1 (Outbound Proxy) – – – – P2 – – – – Registrar/Home-Proxy (OpenSIPS) – – – – UA2

The outgoing proxy is the first hop after client’s NAT . The home proxy is a terminal point for SIP routing. The requested path starts by the outgoing proxy and ends at the registrar/home proxy. It is not common that the UA adds a “Path” header field in the request.

OpenSIPS As Registrar/Home-Proxy

OpenSIPS “Registrar” module has “Path” support. When OpenSIPS receives a SIP Register request, it calls the function save(..), among others. Upon calling this function, the values of the Path header(s) along with the contact address will be stored in the database (User Location Table). The contact address will be stored in the column “contact” and the values of Path header(s) will be stored in the column “path”.

In our scenario, if the proxies P1 and P2 receive a Register request and want to be in the path vector, each one adds its own SIP address as a top most value in the “Path” header field and forward the request. When the request reached the registrar, the path vector will be: Path: <;lr>,<;lr>.

The function save(…) takes some flags as a single string parameter. Among others, we have these flags that are related to the “Path” support:

  • p0‘ (OFF Mode): The path vector will be saved in the user location table but it will not be included in the reply of the Register request.
  • p1‘ (Lazy Mode): The path vector will be saved in the user location table and it will be included in the reply only if the UA indicated path support in the request (add the tag “path” as a value in the “Supported” header field of the request: “Supported: path”).
  • p2‘ (Strict Mode): The path vector will be saved in the user location table only if the the UA indicated path support in the registration request (add the tag “path” as a value in the “Supported” header field of the request). If it is not indicated, the request is rejected with “420 – Bad Extension” and the header “Unsupported: path” will be included in the reply along with the received path vector.

The flags above enable “path” support in “registrar” module and specify the mode of this support as well.

According to all above and if the path vector {p2,p1} is sent in the response, the UA can use the path (as preloaded Route set) in the future requests if that is allowed by the policy. In addition to this, any request reached the home proxy can be routed based on that path {p2,p1} which is stored in the database of the registrar.

According to RFC 3327:

The intermediate proxies (not terminating points) should not add a “Path” header field to a request unless the UA add the tag “path” as a value in the “Supported” header field in that request. Here we say the UA indicated support for PATH extension. If the UA indicated path support and the intermediate proxy requires path support in the registrar, then the proxy adds the tag “path” as a value in the “Requires” header field in that request. If the UA has not indicated support for path and the proxy requires support for it in the registrar, the proxy should reject the request with 421 response. This nearly corresponds to using the flag ‘p2’ in the “save” function: save(“location”,”p2″).

The “save(…)” function has also flag ‘v‘ (path received). If this flag is set, the “received” parameter of the first Path URI of a registration {p1} is set as received-uri and the NAT branch flag is set for this contact. This will be explained further down.

To use multiple flags in the “save(…)” function, mix them as one string. Example: save(“location”,”p2v”).

The routing script will have these lines, among others:


if (method == “REGISTER”) {

save(“location”, “p2v”);

Registrar’s Lookup Operation

When for example UA2 wants to call UA1 (Send Invite request). When the request reached OpenSIPS that operates as a registrar/home proxy, it looks up (Call the function lookup(..)) the AOR of UA1 ( and returns:

  • Contact = <sip:UA1@>

  • Path vector= <;lr>,<;lr>

The Request-URI is overwritten by the registered contact address and the Path vector {p2,p1} is inserted as Route set in the same order {p2,p1} in the outgoing Invite request. The topmost Route header field (proxy: p2) is used for routing decision (next hop) in conjunction with the local policy. Calling this function, also sets the destination URI to the first Path URI (outbound proxy: p1).

OpenSIPS As Outbound Proxy with NAT Detection

OpenSIPS has a module named “path” which is designed to be used at intermediate SIP proxies (e.g. outgoing proxy, load balancer,..etc.). Assume we have this scenario:

UA1 – – – NAT – – – P1 (Outbound Proxy -OpenSIPS) – – – P2 – – – Registrar/Home-Proxy

P1 is OpenSIPS that operates as outgoing proxy with NAT detection. To use “path” module, it must be configured in the routing script to be loaded at startup (loadmodule “”). The module “rr” must be loaded before so it must be configured to be loaded before. To insert a path header into Register message, two functions are exported by this module:

  • The function “add_path(…)” which adds a path header in this form “Path: <sip:;lr>” .The IP address is the IP address of the proxy’s outgoing interface. A port is only added if it is not the default (5060). If it is called with username as parameter, then the username will be added to the URI “Path: <sip:username@;lr>“.
  • The function “add_path_received(…)” which adds a path header in this form:

Path: <sip:;received=sip:;lr>

In our scenario, the outbound proxy p1 will call the function “add_path_received” upon receiving a Register message. The received parameter of its Path URI contains the address where the request has been received (NAT’ed address). This is used to pass the NAT’ed address to the registrar through the next proxy if exists. If it is called with username then the username is added to the URI: “Path: <sip:username@;received=sip:;lr>“. Then the proxy will forward the message further to next hop on a way to the registrar.

If the parameter “use_received” exported from “path” module is set to 1 by the outgoing proxy (modparam(“path”, “use_received”, 1), then when the proxy receives a request, the “received” parameter of the its Route URI  (first Route URI ) is evaluated and used as destination URI(route the request to this address).

This behaviour of outbound proxy is considered as complement to registrar behaviour (SIP Path Extension-aware behaviour of Save(…) and Lookup(…)). So Keep the outbound proxy in the constructed path.

The routing script will have these lines, among others:

loadmodule “”

modparam(“path”, “use_received”, 1)

if (method == “REGISTER”) {
if (!add_path_received(“Outbound”))
sl_send_reply(“503”, “Internal Path Error”);



  • SIP “Path” extension is very useful for SIP loadbalancers that are in front of registrars and proxies. As it helps in drawing SIP routing paths.
  • If you like to manipulate the “received” parameter of the Path URI by yourself in the script (not recommended), you can use the script core variables: $Ri which is the IP address of the interface where the request has been received and $Rp which is the port number. Informations like these are detected by the transport of OpenSIPS (under the SIP layer).
  • If you do not understand the structure of the SIP URI. Go Here.

 More Information


SIP Stress Testing -Part 2 (SIPSAK)


This is part 2 of the “SIP Stress Testing” topic. In Part 1, I have talked about the definition of the stress, opensipsctl (command line tool) and OpenSIPS-CP (Web tool) and how they are used in testing. In this part, i will talk about SIPSAK. SIPSAK is a command line tool used by SIP administrators to test the performance and the security of the SIP servers or user agents. SIPSAK is a SIP traffic generator. It generates SIP requests and sends them to the target addressed by SIP-URI . To download SIPSAK on Fedora, simply:

 # yum install sipsak

SIPSAK runs in the following modes:

♣ Default mode: Using the OPTIONS SIP method, you can  ping a target addressed by SIP-URI.

♣ Traceroute mode (-T): This is useful for learning the request’s path. The number of SIP servers on the way to the destination is counted plus the round trip time of each request is printed out.

♣ Message mode (-M): Send a short message using MESSAGE SIP request. The content of the message will be set using the option (-B).

♣ Usrloc mode (-U): Register the user addressed by SIP-URI (Set by option -s).

♣ Randtrash mode (-R) :keeps sending randomly corrupted messages to torture a SIP server’s parser. OPTIONS requests with increasing numbers of randomly crashed characters are sent to the server.

♣ Flood Mode (-F): keeps sending requests to a SIP server at high pace. OPTIONS requests with increasing CSeq numbers are sent to the server.

Current SIPSAK is missing support for the Record-Route and Route headers and IPv6 is not supported. At the stressed SIP server’s side, you need monitoring and analyzing tool which display the state of the server as numbers and figures.


  • Ping the target “test1”: #sipsak -s In this tutorial i will ping the user test1@

Here is the messages sent by SIPSAK and captured by SIPTRACE. See the User-Agent header field in the traced SIP message (User-Agent: sipsak 0.9.6). The message is taken from OpenSIPPS-CP SIPTRACE page.

If the server allows pinging. It will relay the ping message (SIP OPTION Request) and the response from the pinged target will come back to SIPSAK through the SIP server. The response will look like:

sipsak3The User-Agent: Jitsi2.2.4603.9615Linux . The target user (test1) must be registered otherwise you will get an error response message sent from the server (in case the server is programmed to do this in its routing script). The test server in this tutorial sends “404 Not Found” SIP failure:

sipsak4The server is “OpenSIPS (1.11.2-notls (x86_64/linux))” as written in the server’s response.

If you put the option -F , SIPSAK will flood the server with SIP OPTION Requests.

# sipsak -F  -s

SIPSAK is also used to test the security of the SIP server. In the previous example, flooding the server with OPTIONS SIP Requests (a lot of ping messages) is considered attack because after a short time the SIP service will be not available and the server became unable to handle more SIP requests. The test server in this tutorial sends an error message ” 500 Internal Error” after short time of flooding.

sipsak5Pinging is a way to check that the server is awake and not down. It must be available only for administration’s purposes.

Other SIPSAK examples:

  • Trace a call: # sipsak –T –s
  • Send a message to the user “test1” :# sipsak –M –s –c –B “Message Text”
  • Register the user “test1” # sipsak –U –s

Nagios monitoring tool are good complement to SIPSAK traffic generator.

SO to test the server, generate requests and check the system’s response. If you get something you don’t like, change it and do it again (Make changes, Restart the server, Generate traffic , and Check the server’s response).

More Information


The Next Part will be about SIPp which is an emulation tool which generates SIP traffic and gives some statistics.