Menu Close

Configuring Kamailio 4.x for WebSocket

Author: Patrik Formanek 2014


This tutorial instruct how to add the WebSocket support for your kamailio SIP server. As the prerequisities we need to have successfully installed and working kamailio server (described within several tutorials in this site, for example Installing Kamailio 3.1 within SIP/Kamailio section of this site).

As the first step we need to install websocket modules:

apt-get update
apt-get install kamailio-websocket-modules

Then we have to edit the kamailio.cfg file which is located at etc/kamailio/kamailio.cfg

In section with defined values add lines:

#!substdef "!MY_IP_ADDR!<SERVER_IP>!g"
#!substdef "!MY_DOMAIN!<SERVER_IP>!g"
#!substdef "!MY_WS_PORT!8080!g"
#!substdef "!MY_WSS_PORT!4443!g"
#!substdef "!MY_WS_ADDR!tcp:MY_IP_ADDR:MY_WS_PORT!g"
#!substdef "!MY_WSS_ADDR!tls:MY_IP_ADDR:MY_WSS_PORT!g"

#!define WITH_WEBSOCKETS

Where we have to rewrite values :

  • <SERVER_IP> : IP address of your server (e.i.  #!substdef “!MY_IP_ADDR!192.168.1.13!g”)
  • MY_WS_PORT : port on which will be kamailio listening for ws connections (default is 8080 )

In section global parameters add lines:

listen=MY_IP_ADDR
#!ifdef WITH_WEBSOCKETS
listen=MY_WS_ADDR
#!ifdef WITH_TLS
listen=MY_WSS_ADDR
#!endif
#!endif

tcp_connection_lifetime=3604
tcp_accept_no_cl=yes
tcp_rd_buf_size=16384
And comment line:
#tcp_connection_lifetime=3605

Within modules section we load modules needed by the websocket:

#!ifdef WITH_WEBSOCKETS
loadmodule "xhttp.so"
loadmodule "websocket.so"
loadmodule "nathelper.so"
#!endif

In section setting module-specific parameters we will add :

#!ifdef WITH_WEBSOCKETS
# ----- nathelper params -----
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
# Note: leaving NAT pings turned off here as nathelper is _only_ being used for
#       WebSocket connections.  NAT pings are not needed as WebSockets have
#       their own keep-alives.
#!endif

 

In section routing-logic in block request_route we add lines like this:

request_route {

# per request initial checks
route(REQINIT);

#!ifdef WITH_WEBSOCKETS
if (nat_uac_test(64)) {
  # Do NAT traversal stuff for requests from a WebSocket
  # connection - even if it is not behind a NAT!
  # This won't be needed in the future if Kamailio and the
  # WebSocket client support Outbound and Path.
  force_rport();
  if (is_method("REGISTER")) {
   fix_nated_register();
  } else {
   fix_nated_contact();
   if (!add_contact_alias()) {
    xlog("L_ERR", "Error aliasing contact <$ct>\n");
    sl_send_reply("400", "Bad Request");
    exit;
   }
  }
}
#!endif
....

 

We add some lines in route[WITHINDLG] and it should looks like this:

route[WITHINDLG] {
if (has_totag()) {
  # sequential request withing a dialog should
  # take the path determined by record-routing
  if (loose_route()) {
#!ifdef WITH_WEBSOCKETS
   if ($du == "") {
    if (!handle_ruri_alias()) {
     xlog("L_ERR", "Bad alias <$ru>\n");
     sl_send_reply("400", "Bad Request");
     exit;
    }
   }
#!endif
....

At the end of config file we add:

#!ifdef WITH_WEBSOCKETS
onreply_route {
if ((($Rp == MY_WS_PORT || $Rp == MY_WSS_PORT)
  && !(proto == WS || proto == WSS))) {
  xlog("L_WARN", "SIP response received on $Rp\n");
  drop;
  exit;
}

if (nat_uac_test(64)) {
  # Do NAT traversal stuff for replies to a WebSocket connection
  # - even if it is not behind a NAT!
  # This won't be needed in the future if Kamailio and the
  # WebSocket client support Outbound and Path.
  add_contact_alias();
}
}

event_route[xhttp:request] {
set_reply_close();
set_reply_no_connect();

if ($Rp != MY_WS_PORT
#!ifdef WITH_TLS
     && $Rp != MY_WSS_PORT
#!endif
) {
  xlog("L_WARN", "HTTP request received on $Rp\n");
  xhttp_reply("403", "Forbidden", "", "");
  exit;
}

xlog("L_DBG", "HTTP Request Received\n");

if ($hdr(Upgrade)=~"websocket"
   && $hdr(Connection)=~"Upgrade"
   && $rm=~"GET") {

  # Validate Host - make sure the client is using the correct
  # alias for WebSockets
  if ($hdr(Host) == $null || !is_myself("sip:" + $hdr(Host))) {
   xlog("L_WARN", "Bad host $hdr(Host)\n");
   xhttp_reply("403", "Forbidden", "", "");
   exit;
  }

  # Optional... validate Origin - make sure the client is from an
  # authorised website.  For example,
  #
  # if ($hdr(Origin) != "http://communicator.MY_DOMAIN"
  #     && $hdr(Origin) != "https://communicator.MY_DOMAIN") {
  # xlog("L_WARN", "Unauthorised client $hdr(Origin)\n");
  # xhttp_reply("403", "Forbidden", "", "");
  # exit;
  # }

  # Optional... perform HTTP authentication

  # ws_handle_handshake() exits (no further configuration file
  # processing of the request) when complete.
  if (ws_handle_handshake())
  {
   # Optional... cache some information about the
   # successful connection
   exit;
  }
}

xhttp_reply("404", "Not Found", "", "");
}

event_route[websocket:closed] {
xlog("L_INFO", "WebSocket connection from $si:$sp has closed\n");
}
#!endif

 

Save and exit config file. Now you should use command to check for erros:

kamailio -c kamailio.cfg

If is everything ok and no errors are shown you can restart server with
service kamailio restart

You should see something like this:

Listening on
udp: 192.168.1.13:5060
  tcp: 192.168.1.13:5060
  tcp: 192.168.1.13:8080
Aliases:
  tcp: debi.local:8080
  tcp: debi.local:5060
  udp: debi.local:5060

 

 

Rate this post

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.