Kamailio: Basic SIP Proxy (all requests) Setup

In this example, I will share how to setup Kamailio to proxy SIP requests to a SIP switch (such as FreeSWITCH or Asterisk).
192.168.1.101 is the IP of Kamailio
192.168.1.102 is the IP of FreeSWITCH or Asterisk
Here are snippets from the main config script, kamailio.cfg:

...
 

#!define IPADDRESS "192.168.1.101"

#!define SWITCH_IPADDRESS "192.168.1.102"


#!define FLAG_FROM_SWITCH 1
#!define FLAG_FROM_USER 2

# ------------------ module loading ----------------------------------
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "sl.so"
loadmodule "maxfwd.so"
loadmodule "nathelper.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "path.so"

# ----------------- setting module-specific parameters ---------------
modparam("nathelper|registrar", "received_avp", "$avp(s:rcv)")
# -------------------------  request routing logic -------------------
# main routing logic

route {

        # per request initial checks
        route(SANITY_CHECK);

        # CANCEL processing
        if (is_method("CANCEL")) {
                if (t_check_trans()) {
                        t_relay();
                }
                exit;
        }

        route(CHECK_SOURCE_IP);

        ##################################
        ### HANDLE SEQUENTIAL REQUESTS ###
        route(WITHINDLG);

        ###############################
        ### HANDLE INITIAL REQUESTS ###
        t_check_trans();

        if (is_method("INVITE|REFER")) {
                record_route();
        }
       
        if (is_method("REGISTER")) {
            add_path();
        }

        if (isflagset(FLAG_FROM_SWITCH)) {
                # don't send INVITE from SWITCH back to SWITCH, set reply route to handle NAT and forward them along
                t_on_reply("EXTERNAL_REPLY");
        } else {
                # set destination to your SWITCH
                $du = "sip:192.168.1.102:5060";
        }

        route(RELAY);


}


route[SANITY_CHECK]
{
        if (!sanity_check()) {
                #xlog("L_WARN", "$ci|end|message is insane");
                exit;
        }

        if (!mf_process_maxfwd_header("10")) {
                #xlog("L_WARN", "$ci|end|too much hops, not enough barley");
                send_reply("483", "Too Many Hops");
                exit;
        }

        if ($ua == "friendly-scanner" ||
                $ua == "sundayddr" ||
                $ua =~ "sipcli" ) {
                #xlog("L_WARN", "$ci|end|dropping message with user-agent $ua");
                exit;
        }

        if ($si == IPADDRESS) {
                #xlog("L_WARN", "$ci|end|dropping message");
                exit;
        }

}


route[CHECK_SOURCE_IP]
{
        if ($si == SWITCH_IPADDRESS) {
                setflag(FLAG_FROM_SWITCH);
        } else {
                setflag(FLAG_FROM_USER);
        }
}

# Handle requests within SIP dialogs
route[WITHINDLG]
{
        if (has_totag()) {
                # sequential request withing a dialog should
                # take the path determined by record-routing
                if (loose_route()) {
                        route(RELAY);
                } else {
                        if (is_method("NOTIFY")) {
                                route(RELAY);
                        }
                        if (is_method("SUBSCRIBE") && uri == myself) {
                                # in-dialog subscribe requests
                                exit;
                        }
                        if (is_method("ACK")) {
                                if (t_check_trans()) {
                                        # no loose-route, but stateful ACK;
                                        # must be an ACK after a 487
                                        # or e.g. 404 from upstream server
                                        t_relay();
                                        exit;
                                } else {
                                        # ACK without matching transaction ... ignore and discard
                                        #xlog("ACK without matching transaction ... ignore and discard");
                                        exit;
                                }
                        }
                        sl_send_reply("404","Not here");
                }
                exit;
        }
}

onreply_route[EXTERNAL_REPLY]
{
        route(NAT_TEST_AND_CORRECT);
}


route[NAT_TEST_AND_CORRECT]
{
        if (nat_uac_test("3")) {
                if (is_method("REGISTER")) {
                        fix_nated_register();
                } else {
                        fix_nated_contact();
                }
                force_rport();
        }
        if (has_body("application/sdp") && nat_uac_test("8")) {
                fix_nated_sdp("10");
        }
}

route[RELAY]
{
        if (!t_relay()) {
                sl_reply_error();
        }
        exit;
}

This example will proxy all SIP requests to the switch. Typically, this is not recommended as Kamailio is able to handle the SIP REGISTERs but I’ll save that for another tutorial.

6 thoughts on “Kamailio: Basic SIP Proxy (all requests) Setup”

  1. Hello,

    Is there a way to implement failover to a different upstream register if 192.168.1.102 fails?

    1. Hello,
      Yes, you can use a module such as dispatcher to check health of the B2BUA and route accordingly.

    1. You generally have to enable multihome mode with
      mhomed=1
      It also requires a bit more tweaking. You may need to use force_send_socket() in places as well. I’d be happy to assist more if you can provide a bit more detail on your setup. Feel free to email me direct, eschmidbauer@gmail.com

Leave a Reply

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

Time limit is exhausted. Please reload CAPTCHA.