- SBC ( Session Border Controller )
- Block user based on excessive REGISTER request till an expiry time
- Anti Flood with Pike Module
- Access Control List with Permission Module
- Call Routing Functions
- Registration permissions
- URI permissions
- Address permissions
- Trusted Requests
- Perform Load Balancing with Dispatcher Module
- Kamailio basic setup as proxy for FreeSWITCH
SBC ( Session Border Controller )
A typical voice core network consists of a B2BUA SIP server with media proxy and media processing units/servers along with components for billing, user profile management, shared memory/ cache, transcoders, call routing logic etc. However, a VOIP provider would not want to interface these critical servers to the outside world directly. An SBC ( Session Border Controller ) helps to abstract the core VoIP platform from public access and traffic.
The role of an SBC is to shield the core network from external entities such as user agent’s, carrier networks (topology hiding) while also providing security, auth and accounting services. In many cases, SBC also provides NAT traversal and policy control features ( such as rate-limiting, ACL etc ). In advanced cases, transcoding, topology concealment and load balancing are also achievable via an SBC such as Kamailio.

Following sections are usecases / features kamailio can extend to. Routing scripts at https://github.com/altanai/kamailioexamples
Block user based on excessive REGISTER request till an expiry time
For instance to block DDOS attacks, kamailio can check for the number of register requests a user sends and block above a threshold number subsequently .
if($sht(auth_block_list=>$au::auth_count)==30){
$var(block) = $Ts - 900;
$var(expire) = $Ts - 300;
if($sht(auth_block_list=>$au::last_block) > $var(block)){
xlog("L_INFO", "$fU@$fd - REGISTER - $au User Already Blocked for Exceeded Register Requests.\n");
sl_send_reply("403", "Already Blocked Forbidden");
exit;
} else if($sht(auth_block_list=>$au::last_auth) > $var(expire)) {
$sht(auth_block_list=>$au::last_block) = $Ts;
xlog("L_INFO", "$fU@$fd - REGISTER - $au User Blocked for Exceeded Register Requests.\n");
sl_send_reply("403", "Blocked Forbidden");
exit;
} else {
$sht(auth_block_list=>$au::auth_count) = 0;
}
}
More information on kamailio security can be found on https://telecom.altanai.com/2018/02/17/kamailio-security/. It includes Sanity checks for incoming SIP requests ,Access Control Lists and Permissions, Hiding Topology Details, Anti Flood and Traffic Monitoring and Detection.
Anti Flood with Pike Module
To be on edge of a voip pltform, a SIP server must keep track of all incoming request and their sources. Blocking the ones which exceed the limit or appear like a dos attack. Pike module reports high traffic from an IP if detected.
A sample script to detect high traffic from an IP and add it to ban list for a while . But exclude the known IP sources such as PSTN gateways etc
#!ifdef WITH_ANTIFLOOD
loadmodule "htable.so"
loadmodule "pike.so"
#!endif
...
# ----- pike params -----
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 16)
modparam("pike", "remove_latency", 4)
...
route[REQINIT] {
...
if(src_ip!=myself) {
if($sht(ipban=>$si)!=$null) {
# ip is already blocked
xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
exit;
}
if (!pike_check_req()) {
xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
$sht(ipban=>$si) = 1;
exit;
}
}
Access Control List with Permission Module
permission module handles ACL by storing permission rules in plaintext configuration files , hosts.allow and hosts.deby by tcpd.
#!ifdef WITH_IPAUTH
loadmodule "permissions.so"
#!endif
...
# ----- permissions params -----
#!ifdef WITH_IPAUTH
modparam("permissions", "db_url", DBURL)
modparam("permissions", "db_mode", 1)
#!endif
..
#!ifdef WITH_IPAUTH
if((!is_method("REGISTER")) && allow_source_address()) {
# source IP allowed
return;
}
#!endif
Call Routing Functions
if (allow_routing("rules.allow", "rules.deny")) {
t_relay();
};
Registration permissions
if (method=="REGISTER") {
if (allow_register("register")) {
save("location");
exit;
} else {
sl_send_reply("403", "Forbidden");
};
};
URI permissions
if (allow_uri("basename", "$rt")) { // Check Refer-To URI
t_relay();
};
Address permissions
// check if sourec ip/port is in group 1
if (!allow_address("1", "$si", "$sp")) {
sl_send_reply("403", "Forbidden");
};
Trusted Requests
if (allow_trusted("$si", "$proto")) {
t_relay();
};
Checks protocols which could be one of the “any”, “udp, “tcp”, “tls”, “ws”, “wss” and “sctp”.
Perform Load Balancing with Dispatcher Module
Load balancing is critical to a production ready system to provide High availability and load sharing among available servers. This could be either stateless or stateful where they use call state tracking
Dispatcher module in Kamailio lends capabilities of SIP traffic dispatcher to it. It can load routes to gateways or destination sets from any storage source such as mysql , psql database or even plain text file (modparam("dispatcher", "db_url", <datasource_name>
).
It can also assign priority for routing sip traffic to it ( modparam("dispatcher", "priority_col", "dstpriority")
)
To discover active of inactive gateways it uses TM module. One can choose one among many algorithms to share the load , like
- 0 – hash over callid
- 1 – hash over from URI
- 2 – hash over to URI
- 3 – hash over request-URI
- 4 – round-robin (next destination)
- 5 – hash over authorization-username
- 6 – random destination (using rand())
- 7 – hash over the content of PVs string
- 8 – select destination sorted by priority attribute value (serial forking ordered by priority).
- 9 – use weight based load distribution . Needs attribute ‘weight’ per each address
- 10 – call load distribution ie route to one that has the least number of calls associated
- 11 – relative weight based load distribution(rweight)
- 12 – dispatch to all destination in setid at once (parallel forking).
- x – if the algorithm is not implemented, the first entry in set is chosen.
Some attributes passed with each destination set
- duid – identify a destination (gateway address). Practically the load within the group is associated with this value.
- maxload – upper limit of active calls per destination
- weight – percent of calls to be sent to that gateways
- rweight – relative weight based load distribution.
- socket – sending socket for the gateway including keepalives
- ping_from – from URI in OPTIONS keepalives
Active host usage probability is, rweight/(SUM of all active host rweights in destination group). recalculation is fired as host enables or disables.
Every destination has congestion threshold(weight) and after enabling c (congestion control), rweight is also used to control congestion tolerance lowering the weight by 1 as congestion is detected.
EWMA ( exponential weighted moving average ) is speed at which the older samples are dampened.
name | type | size | default | null | key | extra |
id | unsigned int | 10 | no | primary | auto increment | |
setid | int | not specified | 0 | no | ||
destination | string | 192 | “” | no | ||
flag | int | not specified | “” | no | ||
priority | int | not specified | 0 | no | ||
attrs | string | 198 | 0 | no | ||
description | string | 64 | “” | no |
To insert into dispatcher
INSERT INTO "dispatcher" VALUES(1,1,'sip:192.168.0.1:5060',0,12,'rweight=50;weight=50;cc=1;','');
set ping gateway once per second
modparam("dispatcher", "ds_ping_interval", 1)
enabling congestion metrics
modparam("dispatcher", "ds_ping_latency_stats", 1)
latency estimator
modparam("dispatcher", "ds_latency_estimator_alpha", 900)
loadmodule "dispatcher.so" ... # ----- dispatcher params ----- modparam("dispatcher", "db_url", DBURL) modparam("dispatcher", "table_name", "dispatcher") modparam("dispatcher", "flags", 2) modparam("dispatcher", "dst_avp", "$avp(AVP_DST)") modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)") modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)") modparam("dispatcher", "sock_avp", "$avp(AVP_SOCK)") ... request_route { # do checks , indialog etc ... # dispatch destinations route(DISPATCH); } # Dispatch requests route[DISPATCH] { # round robin dispatching on gateways group '1' if(!ds_select_dst("1", "4")) { send_reply("404", "No destination"); exit; } xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n"); t_on_failure("RTF_DISPATCH"); route(RELAY); exit; } # Try next destinations in failure route, except if session gets cancelled failure_route[RTF_DISPATCH] { if (t_is_canceled()) { exit; } # next DST - only for 500 or local timeout if (t_check_status("500") or (t_branch_timeout() and !t_branch_replied())) { if(ds_next_dst()) { t_on_failure("RTF_DISPATCH"); route(RELAY); exit; } } }
More on Kamailio Call routing and Control
Kamailio basic setup as proxy for FreeSWITCH
I have added a detailed description of how kamalio based SIP servers can function as proxy / SBC for SIP Application server which could be an enterprise PBX or a full fledged Telecom Application Server such as Asterix , Freeswitch , Oracle Weblogic, telestax sip server etc

References
- https://freeswitch.org/confluence/display/FREESWITCH/Kamailio+basic+setup+as+proxy+for+FreeSWITCH
- https://github.com/altanai/kamailioexamples/blob/master/webrtc_to_sip_ipv4_ipv6_with_rtpengine/webrtc_to_sip_kamailio.cfg