Tag Archives: kamailio-UAC-module

Kamailio Bytes – UAC – Authenticate Outbound Calls

Sometimes you need Kamailio to serve as a User Agent Client, we covered using UAC to send SIP REGISTER messages and respond with the authentication info, but if you find you’re getting 401 or 407 responses back when sending an INVITE, you’ll need to use the UAC module, specifically the uac_auth() to authenticate the INVITE,

When Kamailio relays an INVITE to a destination, typically any replies / responses that are part of that dialog will go back to the originator using the Via headers.

This would be fine except if the originator doesn’t know the user name and password requested by the carrier, but Kamailio does,

Instead what we need Kamailio to do is if the response to the INVITE is a 401 Unauthorised Response, or a 407 Proxy Authentication required, intercept the request, generate the response to the authentication challenge, and send it to the carrier.

To do this we’ll need to use the UAC module in Kamailio and set some basic params:

loadmodule "uac.so"
modparam("uac", "reg_contact_addr", "10.0.1.252:5060")
modparam("uac", "reg_db_url", DBURL)
modparam("uac","auth_username_avp","$avp(auser)")
modparam("uac","auth_password_avp","$avp(apass)")
modparam("uac","auth_realm_avp","$avp(arealm)")

Next up when we relay the INVITE (using the Transaction module because we need the response to be transaction stateful).

Before we can call the t_relay() command, we need to specify a failure route, to be called if a negative response code comes back, we’ll use one called TRUNKAUTH and tell the transaction module that’s the one we’ll use by adding t_on_failure(“TRUNKAUTH”);

	$du = "sip:sip.nickvsnetworking.com:5060";
	if(is_method("INVITE")) {
		t_on_failure("TRUNKAUTH");
		t_relay();
		exit;
	   }

What we’ve done is specified to rewrite the destination URI to sip.nickvsnetworking.com, if the request type is an INVITE, it’ll load a failure route called TRUNKAUTH and proxy the request with the transaction module to sip.nickvsnetworking.com.

What we get is a 401 response back from our imaginary carrier, and included in it is a www-auth header for authentication.

To catch this we’ll create an on failure route named “TRUNKAUTH”

failure_route[TRUNKAUTH] {
    xlog("trunk auth");
    }

We’ll make sure the transaction hasn’t been cancelled, and if it has bail out (no point processing subsequent requests on a cancelled dialog).

failure_route[TRUNKAUTH] {
    xlog("trunk auth");
    if (t_is_canceled()) {
        exit;
    }

And determine if the response code is a 401 Unauthorised Response, or a 407 Proxy Authentication required (Authentication requests from our upstream carrier):

failure_route[TRUNKAUTH] {
    xlog("trunk auth");
    if (t_is_canceled()) {
        exit;
    }
	xlog("Checking status code");
    if(t_check_status("401|407")) {
	xlog("status code is valid auth challenge");
    }
}

Next we’ll define the username and password we want to call upon for this challenge, and generate an authentication response based on these values using the uac_auth() command,

failure_route[TRUNKAUTH] {
    xlog("trunk auth");
    if (t_is_canceled()) {
        exit;
    }
	xlog("Checking status code");
    if(t_check_status("401|407")) {
	xlog("status code is valid auth challenge");
        $avp(auser) = "test";
        $avp(apass) = "test";
        uac_auth();

    }
}

Then finally we’ll relay that back to the carrier with our www-auth header populated with the challenge response;

failure_route[TRUNKAUTH] {
    xlog("trunk auth");
    if (t_is_canceled()) {
        exit;
    }
	xlog("Checking status code");
    if(t_check_status("401|407")) {
	xlog("status code is valid auth challenge");
        $avp(auser) = "test";
        $avp(apass) = "test";
        uac_auth();
	xlog("after uac_auth");
        t_relay();
        exit;
    }
}

And done!

We can get this data from the UAC database so we don’t need to load these values directly into our config file too using the SQLops module.

As always I’ve put the running code example on my GitHub.

Kamailio Bytes – UAC for Remote User Registration to external SIP Server (Originating SIP REGISTER)

I’ve talked about using the UAC module, but as promised, here’s how we can use the UAC module to send SIP REGISTER requests to another SIP server so we can register to another SIP proxy.

Let’s say we’re using Kamailio to talk to a SIP Trunk that requires us to register with them so they know where to send the calls. We’d need to use Kamailio UAC module to manage SIP Registration with our remote SIP Trunk.

But Kamailio’s a proxy, why are we sending requests from it? A proxy just handles messages, right?
Proxies don’t originate messages, it’s true, and Kamailio can be a proxy, but with the UAC module we can use Kamailio as a Client instead of a server. Keep in mind Kamailio is what we tell it to be.

Getting Started

Before we can go spewing registrations out all over the internet we need to start by getting a few things in place;

First of which is configuring UAC module, which is something I covered off in my last post,

We’ll also need to have a database connection in place, again I’ve covered off connecting to a MySQL database in Kamailio here.

Once we’ve got that done we’ll need to tell the UAC module our IP Address for the from address for our Contact field, and the database URL of what we’ve setup.

modparam("uac", "reg_contact_addr", "192.168.1.99:5060")
modparam("uac", "reg_db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")

I haven’t used a variable like DBURL for the database information, but you could.

Finally a restart will see these changes pushed into Kamailio.

/etc/init.d/kamailio restart

This is the end of the Kamailio config side of things, which you can find on my GitHub here.

Defining the Registration parameters

Once we’ve got a database connection in place and UAC module loaded, then we can configure an entry in the uacreg table in the database, in my example I’m going to be registering to an Asterisk box on 192.168.1.205, so I’ll insert that into my database:

mysql> INSERT INTO `uacreg` VALUES (NULL,'myusername','myusername','192.168.1.205','myusername','192.168.1.205','asterisk','myusername','mypassword','','sip:192.168.1.205:5060',60,0,0);

Note: If you’re using a later version of Kamailio (5.4+) then the DB schema changes and you may want something like this:

insert into uacreg values ('', 'myusername', 'myusername', 'mydomain', 'myusername', 'mydomain', 'asteriskrealm', 'myusername', 'mypassword', '', 'sip:remoteproxy.com:5060', 60, 0, 0, 0)

Having a look at the fields in our table makes it a bit clearer as to what we’ve got in place, setting flags to 0 will see Kamailio attempt registration. Make sure the auth_proxy is a SIP URI (Starts with sip:) and leave the auth_ha1 password empty as we haven’t calculated it.

mysql> SELECT * FROM 'uacreg' \G
            id: 2
        l_uuid: myusername
    l_username: myusername
      l_domain: 192.168.1.205
    r_username: myusername
      r_domain: 192.168.1.205
         realm: asterisk
 auth_username: myusername
 auth_password: mypassword
      auth_ha1:
    auth_proxy: sip:192.168.1.205:5060
       expires: 60
         flags: 0
     reg_delay: 0

Putting it into Play

After we’ve got our database connection in place, UAC module configured and database entries added, it’s time to put it into play, we’ll use Kamcmd to check it’s status:

kamcmd> uac.reg_reload
kamcmd> uac.reg_dump

Unfortunately from Kamcmd we’re not able to see registration status, but Sngrep will show us what’s going on:

From Sngrep we can see the REGISTRATION going out, the authentication challenge and the 200 OK at the end.

Make sure you’ve got your Realm correct, otherwise you may see an error like this:

RROR: {2 10 REGISTER [email protected]} uac [uac_reg.c:946]: uac_reg_tm_callback(): realms do not match. requested realm: [localhost]

If you’re not familiar with the SIP Registration process now’s a good time to brush up on it by having a read of my post here. – “What is a SIP Registrar?”

Kamailio Bytes – SIP UAC Module to act as a UAC / SIP Client

Kamailio is a great SIP proxy, but sometimes you might want to see requests originate from Kamailio.

While this isn’t typical proxy behaviour, RFC definitions of a proxy and technical requirements are often two different things. The UAC module allows us to use Kamailio to act as a User Agent Client instead of just a UAS.

There’s one feature I won’t cover in this post, and that’s initiating and outbound SIP Registration using the UAC module, that will get a post of it’s own in the not to distant future.

You may already be sort of using Kamailio is a UAC, if you’re using Dispatcher and sending SIP Pings, then Kamailio is sending SIP OPTIONS messages to the dispatcher destinations. If you’re using the NAT module and sending Keepalives, then you’re also using Kamailio as a UAC. The only difference is the Dispatcher and NAT Helper modules do this for us, and we’re going to originate our own traffic.

There’s a bit of a catch here, when Kamailio receives a request it follows a set of logic and does something with that request. We’re going to remain constrained by this for our example, just to keep things simple.

So let’s work on an example, if a user on our network dials a call to an emergency services number, we’ll send a text message to my IP phone to let me know who’s dialed the emergency services number.

So to start with we’ll need to load the Kamailio UAC module, using LoadModule as we would with any other module:

loadmodule "uac.so"

If you’re working on the default config file that ships with Kamailio you’ll probably have to change how record routing is handled to support UAC,

modparam("rr", "append_fromtag", 1)

Now we should have UAC support added in Kamailio, I’m going to do a bare bones example of the routing logic below, but obviously if you wanted to put this into practice in real life you’d want to actually route the SIP INVITE to an emergency services destination.

First we’ll need to find if the request is an INVITE with the Request URI to an emergency services number, I’ve programmed this in with the Australian emergency services numbers:

if(is_method("INVITE") && ($rU == "000" or $tU == "112" or $tU == "116")){      
  #Matches any INVITEs with the Request URI to Address as 000, 112 or 116
  xlog("Emergency call from $fU to $rU (Emergency number) CSeq is $cs ");
}

Now calls to 000, 112 or 116 will see the alert apear in Xlog:

07:22:41 voice-dev3 /usr/sbin/kamailio[10765]: ERROR: : Emergency call from Test to 112 (Emergency number)

So next up we need to handle the sending a SIP MESSAGE request to my IP phone on the IP 10.0.1.5 – You’re probably thinking we could use the Registrar module to lookup my registered IP address, and you’re right, but to keep things simple I’m just hardcoding it in.

So to keep our routing neat we’ll send calls to the route route(“EmergencyNotify”); and so the demo works I’ll send back a 200 OK and exit – In real life you’d want to handle this request and forward it onto emergency services.

if(is_method("INVITE") && ($rU == "000" or $tU == "112" or $tU == "116")){      
#Matches any INVITEs with the Request URI to Address as 000, 112 or 116
  xlog("Emergency call from $fU to $rU (Emergency number) CSeq is $cs ");
  route("EmergencyNotify");
  #You obviously would want this to route to an emergency services destination...
  sl_reply("200", "ok");
  exit;
}

if(is_method("INVITE")){                                                                                
  #Matches everything else
  xlog("Just a regular call from $fU to $rU");
}

Obviously we need to now create a route called route[“EmergencyNotify”]{ } where we’ll put our UAC logic.

For the UAC module we need to craft the SIP Request we’re going to send; we’re going to be sending a SIP MESSAGE request,

route["EmergencyNotify"]{
  xlog("Emergency Notify Route");
  $uac_req(method)="MESSAGE";
  $uac_req(ruri)="sip:10.0.1.5:5060";
  $uac_req(furi)="sip:Emergency Alert";
  $uac_req(turi)="sip:thisphone";
  $uac_req(callid)=$(mb{s.md5});
  $uac_req(hdrs)="Subject: Emergency Alert\r\n";
  $uac_req(hdrs)=$uac_req(hdrs) + "Content-Type: text/plain\r\n";
  $uac_req(body)="Emergency call from " + $fU + " on IP Address " + $si + " to " + $rU + " (Emergency Number)";
  $uac_req(evroute)=1;
  uac_req_send();
}

So now we’ve sort of put it all together, when a call comes into an emergency destination, like 000, the route EmergencyNotify is called which sends a SIP MESSAGE request to my IP Phone to alert me.

When a caller dials 000 I can see Kamailio sends a SIP MESSAGE to my IP Phone:

Let’s have a look at how this looks on my IP Phone:

I’ve fleshed out the code a little more to handle SIP REGISTER requests etc, and put the full running code on GitHub which you can find here.