## NOTE: DO NOT CHANGE THIS FILE, EDIT local.cfg ## #### Preprocessor Directives ######### #!define L_ALERT -5 #!define L_BUG -4 #!define L_CRIT2 -3 #!define L_CRIT -2 #!define L_ERR -1 #!define L_WARN 0 #!define L_NOTICE 1 #!define L_INFO 2 #!define L_DBG 3 #!define AVP_RECV_PARAM "recv_param" #!define AVP_LOG_LEVEL "log_level" #!define AVP_ROUTE_CNT "route_cnt" #!define AVP_ASSOCIATED_SERVER "associated_server" #!define AVP_ASSOCIATE_CONTACT "associate_contact" #!define AVP_REDIRECT_KEY "redirect_key" ####### Flags ####### flags FLAG_INTERNALLY_SOURCED: 1, FLAG_ASSOCIATE_SERVER: 2, FLAG_SKIP_NAT_CORRECTION: 3, FLAG_ASSOCIATE_USER: 4, FLAG_TRUSTED_SOURCE: 5, FLAG_SESSION_PROGRESS: 6; #!define FLB_NATB 1 #!define FLB_NATSIPPING 2 #!define FLB_UAC_REDIRECT 3 #!define TRUSTED_ADR_GROUP 1 ####### Global Parameters ######### fork = yes children = 25 server_signature = no server_header = "Server: Kazoo" user_agent_header = "User-Agent: Kazoo" shm_force_alloc = yes mlock_pages = yes phone2tel = 1 max_while_loops = 500 ####### Logging Parameters ######### debug = L_INFO memdbg = 10 memlog = 10 corelog = L_ERR log_stderror = no log_facility = LOG_LOCAL0 log_name="kamailio" ####### Alias Parameters ######### auto_aliases = yes ####### Binding Parameters ######### tos = IPTOS_LOWDELAY ####### TCP Parameters ######### tcp_children = 25 disable_tcp = no tcp_max_connections = 4096 tcp_connection_lifetime = 3605 tcp_accept_aliases = no tcp_async = yes tcp_connect_timeout = 10 tcp_conn_wq_max = 65536 tcp_crlf_ping = yes tcp_delayed_ack = yes tcp_fd_cache = yes tcp_keepalive = yes tcp_keepcnt = 3 tcp_keepidle = 30 tcp_keepintvl = 10 tcp_linger2 = 30 tcp_rd_buf_size = 4096 tcp_send_timeout = 10 tcp_wq_blk_size = 2100 tcp_wq_max = 10485760 ####### UDP Parameters ######### udp4_raw = -1 ####### DNS Parameters ######### dns = no rev_dns = no dns_try_ipv6 = no use_dns_cache = on dns_cache_del_nonexp = no dns_cache_flags = 1 dns_cache_gc_interval = 120 dns_cache_init = 1 dns_cache_mem = 1000 dns_cache_negative_ttl = 60 dns_try_naptr = no use_dns_failover = off dns_srv_lb = off ####### TLS Parameters ######### enable_tls = yes ####### SCTP Parameters ######### disable_sctp = yes ####### Custom Parameters ######### ####### Modules Section ######## mpath="/usr/lib64/kamailio/modules/" ######## Kamailio core extensions module ######## loadmodule "kex.so" ######## Transaction (stateful) module ######## loadmodule "tm.so" loadmodule "tmx.so" modparam("tm", "auto_inv_100", 1) modparam("tm", "auto_inv_100_reason", "Attempting to connect your call") modparam("tm", "cancel_b_method", 2) modparam("tm", "ruri_matching", 0) modparam("tm", "failure_reply_mode", 3) # modparam("tm", "fr_timer", 30000) # modparam("tm", "fr_inv_timer", 120000) ######## Stateless replier module ######## loadmodule "sl.so" ######## Record-Route and Route module ######## loadmodule "rr.so" modparam("rr", "enable_full_lr", 1) modparam("rr", "enable_double_rr", 0) ######## Max-Forward processor module ######## loadmodule "maxfwd.so" modparam("maxfwd", "max_limit", 50) ######## SIP utilities [requires sl] ######## loadmodule "siputils.so" ######## SIP message formatting sanity checks [requires sl] ######## loadmodule "sanity.so" # sip_version, scheme, req_headers, cseq_method/value # content_length, parse_uri, digest modparam("sanity", "default_checks", 3303) modparam("sanity", "uri_checks", 3) modparam("sanity", "autodrop", 0) ######## Text operations module ######## loadmodule "textops.so" loadmodule "textopsx.so" ######## Generic Hash Table container in shared memory ######## loadmodule "htable.so" modparam("htable", "htable", "associations=>size=16;autoexpire=7200") modparam("htable", "htable", "redirects=>size=16;autoexpire=5") ######## Pseudo-Variables module ######## loadmodule "pv.so" ######## Advanced logger module ######## loadmodule "xlog.so" ####### FIFO support for Management Interface ######## loadmodule "mi_fifo.so" modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo") ######## UAC Redirection module ######## loadmodule "uac_redirect.so" ######## DoS prevention mdule ######## loadmodule "pike.so" ####### Role Configurations ########## #!ifdef DISPATCHER-ROLE include_file "dispatcher-role.cfg" #!endif #!ifdef REGISTRAR-ROLE include_file "registrar-role.cfg" #!endif #!ifdef PRESENCE-ROLE include_file "presence-role.cfg" #!endif #!ifdef NAT-TRAVERSAL-ROLE include_file "nat-traversal-role.cfg" #!endif ####### Kazoo Integration module ########## #!ifdef INCLUDE-DB-KAZOO loadmodule "db_kazoo.so" #!endif ####### DB Text module ########## loadmodule "db_text.so" modparam("db_text", "db_mode", 1) ####### Permissions module ########## loadmodule "permissions.so" modparam("permissions", "db_url", "text:///etc/kazoo/kamailio/dbtext") modparam("permissions", "db_mode", 1) ####### Routing Logic ######## route { # log the basic info regarding this call xlog("L_INFO", "$ci|start|recieved $oP request $rm $ou"); xlog("L_INFO", "$ci|log|source $si:$sp"); xlog("L_INFO", "$ci|log|from $fu"); xlog("L_INFO", "$ci|log|to $tu"); remove_hf_re("Diversion: .*"); route(SANITY_CHECK); #!ifdef DISPATCHER-ROLE route(DISPATCHER_CLASSIFY_SOURCE); #!endif #!ifdef TRAFFIC-FILTER-ROLE route(DOS_PREVENTION); #!endif route(HANDLE_OPTIONS); route(HANDLE_NOTIFY); route(HANDLE_MESSAGE); route(HANDLE_MOVE_REQUEST); #!ifdef PRESENCE-ROLE route(HANDLE_SUBSCRIBE); route(HANDLE_PUBLISH); #!endif #!ifdef REGISTRAR-ROLE route(HANDLE_REGISTER); #!endif route(HANDLE_IN_DIALOG_REQUESTS); route(PREPARE_INITIAL_REQUESTS); if (isflagset(FLAG_INTERNALLY_SOURCED)) { route(INTERNAL_TO_EXTERNAL_RELAY); exit(); } #!ifdef DISPATCHER-ROLE route(DISPATCHER_FIND_ROUTES); #!endif route(EXTERNAL_TO_INTERNAL_RELAY); } route[SANITY_CHECK] { 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 ( msg:len > 6144 ) { xlog("L_WARN", "$ci|end|message too large"); send_reply("513", "Message too large"); exit; } if (!sanity_check()) { xlog("L_WARN", "$ci|end|message is insane"); exit; } if ($ua == "friendly-scanner" || $ua == "sundayddr" || $ua =~ "sipcli" ) { xlog("L_WARN", "$ci|end|dropping message with user-agent $ua"); exit; } } route[HANDLE_OPTIONS] { if (is_method("OPTIONS")) { if (isflagset(FLAG_INTERNALLY_SOURCED)) { route(INTERNAL_TO_EXTERNAL_RELAY); #!ifdef TRAFFIC-FILTER-ROLE } else if (!isflagset(FLAG_TRUSTED_SOURCE) && $rd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") { xlog("L_WARN", "$ci|end|dropping OPTIONS request with IP domain"); #!endif } else { sl_send_reply("200", "Rawr!!"); } exit; } } route[HANDLE_NOTIFY] { if (is_method("NOTIFY")) { if (isflagset(FLAG_INTERNALLY_SOURCED)) { route(INTERNAL_TO_EXTERNAL_RELAY); #!ifdef TRAFFIC-FILTER-ROLE } else if (!isflagset(FLAG_TRUSTED_SOURCE) && $rd =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}") { xlog("L_WARN", "$ci|end|dropping OPTIONS request with IP domain"); #!endif } else { sl_send_reply("200", "Rawr!!"); } exit; } } route[HANDLE_MESSAGE] { if (is_method("MESSAGE")) { if (isflagset(FLAG_INTERNALLY_SOURCED)) { route(INTERNAL_TO_EXTERNAL_RELAY); } else { sl_send_reply("202", "delivered to /dev/null"); exit; } } } route[HANDLE_MOVE_REQUEST] { if (is_method("INVITE") && $rU == "*6683*") { $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); if ($sht(associations=>$var(contact_uri)) != $null) { $sht(associations=>$var(contact_uri)) = $null; xlog("L_INFO", "$ci|log|removed contact association for $var(contact_uri) with media server $sht(associations=>$var(contact_uri))"); } send_reply("503", "Removed association"); exit; } } route[HANDLE_IN_DIALOG_REQUESTS] { if (has_totag()) { if (loose_route()) { xlog("L_INFO", "$ci|log|loose_route in-dialog message"); # Called on in-dialog requests # If the request in an Invite for on hold from external to internal, # associate the contact with the media server # if Invite for on hold, we need to associate the contact URI with the next hop if (is_method("INVITE") && !isflagset(FLAG_INTERNALLY_SOURCED) && is_audio_on_hold()) { setflag(FLAG_ASSOCIATE_USER); } route(RELAY); } else if (isflagset(FLAG_INTERNALLY_SOURCED)) { xlog("L_INFO", "$ci|log|relay internally sourced in-dialog message without loose_route"); route(RELAY); } else if (t_check_trans()) { xlog("L_INFO", "$ci|log|allow message for a known transaction"); route(RELAY); } else { xlog("L_INFO", "$ci|log|message had a to-tag but can't be loose routed"); sl_send_reply("481", "Call Leg/Transaction Does Not Exist"); } exit(); } } route[PREPARE_INITIAL_REQUESTS] { if (is_method("CANCEL")) { if (t_check_trans()) { route(RELAY); } else { sl_send_reply("481", "Call Leg/Transaction Does Not Exist"); } exit(); } else if (is_method("ACK")) { if (t_check_trans()) { route(RELAY); } exit(); } t_check_trans(); if (loose_route()) { xlog("L_WARN", "$ci|end|denying initial request with route-set"); sl_send_reply("403", "No pre-loaded routes"); exit(); } if (!is_method("MESSAGE")) { record_route(); } } route[RELAY] { if (isflagset(FLAG_INTERNALLY_SOURCED)) { route(INTERNAL_TO_EXTERNAL_RELAY); } else { route(EXTERNAL_TO_INTERNAL_RELAY); } exit(); } route[INTERNAL_TO_EXTERNAL_RELAY] { remove_hf_re("X-.*"); t_on_reply("EXTERNAL_REPLY"); t_set_fr(0, 10000); t_relay(); } route[EXTERNAL_TO_INTERNAL_RELAY] { #!ifdef NAT-TRAVERSAL-ROLE if (!isflagset(FLAG_INTERNALLY_SOURCED)) { route(NAT_TEST_AND_CORRECT); } #!endif remove_hf_re("X-.*"); append_hf("X-AUTH-IP: $si\r\n"); t_on_reply("INTERNAL_REPLY"); t_on_failure("INTERNAL_FAULT"); t_set_fr(0, 1000); t_relay(); } route[DOS_PREVENTION] { # allow request from internal network or from whitelist if (isflagset(FLAG_INTERNALLY_SOURCED) || allow_source_address(TRUSTED_ADR_GROUP)) { xlog("L_INFO", "$ci|log|request from trusted IP"); setflag(FLAG_TRUSTED_SOURCE); return; } # drop requests with no To domain or IP To domain (friendly-scanner) if (is_method("REGISTER|SUBSCRIBE|OPTIONS") && ($td == $null || $td=~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}")) { xlog("L_WARN", "$ci|log|dropping request with IP domain in To header"); exit; } # drop Invite with IP auth realm if (is_method("INVITE") && is_present_hf("Proxy-Authorization") && $ar =~ "[0-9]{1,3}\.[0-9]{1,3}.[0-9]{1,3}\.[0-9]{1,3}" ) { xlog("L_WARN", "$ci|log|dropping request with IP domain in Proxy-Authorization header"); exit; } # use pike check for the others if (!pike_check_req()) { # If it is a new flood, emit a log if($rc == -2) { xlog("L_WARN", "$ci|log|dropping due to rate of requests from IP"); } exit; } } onreply_route[EXTERNAL_REPLY] { xlog("L_INFO", "$ci|log|external reply $T_reply_code"); #!ifdef NAT-TRAVERSAL-ROLE route(NAT_TEST_AND_CORRECT); #!endif } onreply_route[INTERNAL_REPLY] { # this route handles replies that are comming from our media server xlog("L_INFO", "$ci|start|recieved internal reply $T_reply_code $rr"); xlog("L_INFO", "$ci|log|source $si:$sp"); if (is_method("INVITE") && !isflagset(FLAG_SESSION_PROGRESS) && t_check_status("(180)|(183)|(200)") ) { if ($avp(AVP_REDIRECT_KEY) != $null && $sht(redirects=>$avp(AVP_REDIRECT_KEY)) != $null ) { xlog("L_INFO", "$ci|log|removing redirect mapping $avp(AVP_REDIRECT_KEY)"); $sht(redirects=>$avp(AVP_REDIRECT_KEY)) = $null; } xlog("L_INFO", "$ci|log|call setup, now ignoring abnormal termination"); setflag(FLAG_SESSION_PROGRESS); } if ($rs < 300) { xlog("L_INFO", "$ci|pass|$T_req($si):$T_req($sp)"); } $var(reply_reason) = $rr; } failure_route[INTERNAL_FAULT] { # this branch handles failures (>=300) to our media servers, # which we can sometimes overcome by routing to another server # if the failure cause was due to the transaction being # cancelled then we are complete if (t_is_canceled()) { xlog("L_INFO", "$ci|log|transaction was cancelled"); exit; } # Handle redirects if (t_check_status("302")) { $var(redirect) = @from.uri.user + "@" + @from.uri.host + "->" + $T_rpl($(ct{tobody.user})) + "@" + $T_rpl($(ct{tobody.host})); if($T_rpl($hdr(X-Redirect-Server)) != $null) { $sht(redirects=>$var(redirect)) = $T_rpl($hdr(X-Redirect-Server)); xlog("L_INFO", "$ci|log|stored redirect mapping $var(redirect) to $T_rpl($hdr(X-Redirect-Server))"); } } else if (!t_check_status("407") && $avp(AVP_REDIRECT_KEY) != $null && $sht(redirects=>$avp(AVP_REDIRECT_KEY)) != $null ) { xlog("L_INFO", "$ci|log|removing redirect mapping $avp(AVP_REDIRECT_KEY)"); $sht(redirects=>$avp(AVP_REDIRECT_KEY)) = $null; } remove_hf_re("X-.*"); # change 6xx to 4xx if (t_check_status("6[0-9][0-9]")) { $var(new_code) = "4" + $(T_reply_code{s.substr,1,0}); xlog("L_INFO", "$ci|log|sending 6XX reply as $var(new_code) $var(reply_reason)"); t_reply("$(var(new_code){s.int})", "$var(reply_reason)"); # if the failure case was something that we should recover # from then try to find a new media server } else if ("$var(reply_reason)" =~ "call barred") { xlog("L_INFO", "$ci|log|failure route ignoring call barred"); } else if (isflagset(FLAG_SESSION_PROGRESS)) { xlog("L_INFO", "$ci|log|failure route ignoring failure after session progress"); } else if (t_check_status("(401)|(407)|(486)|(403)")) { xlog("L_INFO", "$ci|log|failure route ignoring auth reply $T_reply_code $var(reply_reason)"); } else if (t_check_status("402")) { xlog("L_INFO", "$ci|log|failure route overriding reply code 402 with 486"); send_reply("486", "Insufficient Funds"); } else if (t_check_status("(4[0-9][0-9])|(5[0-9][0-9])")) { xlog("L_INFO", "$ci|start|received failure reply $T_reply_code $rr"); #!ifdef DISPATCHER-ROLE route(DISPATCHER_NEXT_ROUTE); #!endif send_reply("486", "Unable to Comply"); } else { xlog("L_INFO", "$ci|log|failure route ignoring reply $T_reply_code $rr"); } xlog("L_INFO", "$ci|pass|$si:$sp"); } onsend_route { if (isflagset(FLAG_ASSOCIATE_USER)) { $var(contact_uri) = $(ct{tobody.user}) + "@" + $(ct{tobody.host}); xlog("L_INFO", "$ci|log|associate user $var(contact_uri) with media server sip:$sndto(ip):$sndto(port)"); $sht(associations=>$var(contact_uri))= "sip:" + $sndto(ip) + ":" + $sndto(port); } xlog("L_INFO", "$ci|pass|$sndfrom(ip):$sndfrom(port) -> $sndto(ip):$sndto(port)"); } # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab