# opensips.cfg - OpenSIPS v.2.2 config for ViciNOC # # Copyright (C) 2018 James Pearson LICENSE: AGPLv2 # ####### Global Parameters ######### log_level=3 log_stderror=no log_facility=LOG_LOCAL0 log_name="opensips" children=4 ### Some core config stuff server_signature=no server_header="Server: Deluxe Club Sandwhich V2" #disable_tcp=yes #disable_tls=yes disable_dns_blacklist=yes auto_aliases=no dns_use_search_list=no rev_dns=off ### network information listen=udp:0.0.0.0:5060 mhomed=1 ### This might be needed for NAT traversal, handle with care #alias=sip.mycompany.com #advertised_port=5060 #advertised_address="X.X.X.X" ####### Modules Section ######## ### set module path mpath="/usr/lib64/opensips/modules/" ### Our modules to load loadmodule "proto_udp.so" loadmodule "db_mysql.so" loadmodule "signaling.so" loadmodule "sl.so" loadmodule "tm.so" loadmodule "rr.so" loadmodule "maxfwd.so" loadmodule "usrloc.so" loadmodule "textops.so" loadmodule "mi_fifo.so" loadmodule "uri.so" loadmodule "acc.so" loadmodule "options.so" loadmodule "permissions.so" loadmodule "nathelper.so" loadmodule "avpops.so" loadmodule "drouting.so" loadmodule "dialog.so" loadmodule "load_balancer.so" loadmodule "sipmsgops.so" loadmodule "topology_hiding.so" loadmodule "proto_udp.so" # ----------------- setting module-specific parameters --------------- ### Default MySQL Connection Info use by all modules unless specified otherwise db_default_url="mysql://opensips:opensips@localhost/opensips" modparam("permissions", "db_url", "mysql://opensips:opensips@localhost/opensips") ### For a slave setup you'll want the following to go to a different database ### The slave replication should be for all other tables. These are kept for local use #modparam("acc", "db_url", "mysql://opensips:opensips@localhost/opensips_local") #modparam("avpops","db_url","mysql://opensips:opensips@localhost/opensips_local") #modparam("dialog", "db_url", "mysql://opensips:opensips@localhost/opensips_local") # ----- mi_fifo params ----- modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo") # ----- rr params ----- modparam("rr", "append_fromtag", 1) # -- tm params -- modparam("tm", "fr_inv_timeout", 60) modparam("tm", "fr_timeout", 10) ### Load Balancer options modparam("load_balancer", "probing_interval", 60) modparam("load_balancer", "probing_method", "OPTIONS") modparam("load_balancer", "probing_from", "sip:lbprobe@sip.vicinoc.com") modparam("load_balancer", "probing_reply_codes", "501, 403, 404, 484") ### Dynamic Routing modparam("drouting", "rule_id_avp", '$avp(rule_id)') modparam("drouting", "ruri_avp", '$avp(dr_ruri)') modparam("drouting", "use_domain", 0) modparam("drouting", "probing_interval", 60) modparam("drouting", "probing_from", "sip:pinger@sip.vicinoc.com") modparam("drouting", "probing_reply_codes", "501, 403, 404, 200, 484") ### acc modparam("acc", "detect_direction", 1) #modparam("acc", "early_media", 1) modparam("acc", "report_cancels", 1) modparam("acc", "db_extra", "sip_from=$fu ; sip_to=$tu ; domain=$rd ; source_ip=$si ; direction=$avp(direction) ; route_info=$avp(route_info)") # ----- usrloc params ----- modparam("usrloc", "db_mode", 0) # ----- uri params ----- modparam("uri", "use_uri_table", 0) # Dialog params modparam("dialog", "dlg_match_mode", 1) modparam("dialog", "db_mode", 2) modparam("dialog", "profiles_with_value", "channelcount") ####### Routing Logic ######## ###### main routing block - everything starts here route{ ### Simple sanity checks before real processing begins # Max forwards to prevent loops if (!mf_process_maxfwd_header("10")) { sl_send_reply("483","Too Many Hops"); exit; } # Prevent buffer overflows if (msg:len > max_len) { sl_send_reply("513", "Message Overflow"); exit; } # Drop any unsupported METHODs here if (is_method("REGISTER|SUBSCRIBE|PUBLISH|MESSAGE|UPDATE")) { xlog("$rm $si $ru $ci - Dropping"); sl_send_reply("405", "Method Not Allowed"); exit; } # Reply to OPTIONS packets to let people know /we/ are alive, asterisk likes this if (is_method("OPTIONS")) { options_reply(); exit; } ### Process sequential requests in-dialog and forward if (has_totag()) { # sequential request within a dialog should take the path determined by record-routing if (loose_route() || match_dialog()) { # sequential request after routing and dialog matching if ($DLG_status!=NULL) { # request matched against a dialog $var(x) = validate_dialog() ; switch ( $var(x) ) { case -2: case -3: # invalid request, but fixable fix_route_dialog(); break; case -1: case -4: # invalid request, but not fixable send_reply("488","No such dialog"); exit; case 1: # ok break; default: # bug unknown ret code, so do nothing I guess } } if (is_method("ACK")) { if (t_check_trans()) { t_relay(); exit; } } else if (is_method("INVITE")) { sl_send_reply("100", "Trying"); route(topohiding); } # Route out based on our loose route route(1); } else { # Unsequential or orphan transactions, handle appropriately if ( is_method("ACK") ) { if ( t_check_trans() ) { # non 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 exit; } } sl_send_reply("404","Not here"); exit; } exit; } # Make sure we have a destination from them if ($rU==NULL) { # request with no Username in RURI sl_send_reply("484","Address Incomplete"); exit; } # CANCEL processing if (is_method("CANCEL")) { if (t_check_trans()) { t_relay(); exit; } } # See if we are stateful at this point, and if we are, load our runtime vars t_check_trans(); # preloaded route checking if (loose_route()) { xlog("L_ERR", "Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]"); if (!is_method("ACK")) sl_send_reply("403","Preload Route denied"); exit; } # At this point, if it's an invite handle it, or just route whatever the hell else we got if (is_method("INVITE")) { route(2); # Figure out what we got before we process exit; } else { if(!t_relay()) { sl_reply_error(); return(0); exit; } } } route[1] { # Basic stateful transaction relaying without progression # By default does all the work after initial routing until teardown if (!t_relay("0x01")) { sl_reply_error(); }; exit; } route[2] { # This is where we handle initial invites and figure out how to further route them # Basically if they are carriers, telephony servers, etc # Group 1 is termination from telephony servers to carriers if (check_source_address("1")) { sl_send_reply("100", "Trying"); route(term); exit; } # Group 1 is origination from carriers to telephony server if (check_source_address("2")) { sl_send_reply("100", "Trying"); route(orig); exit; } # We don't know who this is, so tell them to get lost, and be done with them. sl_send_reply("401", "Unauthorized"); exit; } route[term] { # Dynamic routing block for sending telephony servers to carriers # Normalize calls first route(normterm); # Create call dialog create_dialog("B"); set_dlg_profile("channelcount","$si"); avp_printf("$avp(direction)", "Term"); do_accounting("db", "cdr|missed|failed", "acc"); # Look up our dynamic routing entries courtesy of droute if (!do_routing("1")) { sl_send_reply("500", "DR do_routing failure"); exit; } #xlog("DR successfully done: ruri=$ru, destinations are: $ru $(avp(dr_ruri)[*])"); # Setup up response handling and route t_on_failure("term"); t_on_reply("stripcid"); route(topohiding); route(1); } failure_route[term] { # Dynamic routing failover xlog("DR failure $T_reply_code : destinations are: $ru $(avp(dr_ruri)[*])"); # If the transaction was cancelled, quit processing this route if (t_was_cancelled()) { exit; } # Treat a 486 from the carrier as legit if (t_check_status("486")) { t_reply("486", "Busy"); exit; } # Timeout from carrier, this is HORRIBLY bad, so give feedback and optionally do something if (t_check_status("408")) { xlog("Carrier timeout! This is bad!"); #t_reply("486", "Busy"); } # Redirects just get forwarded since it's likely taking us out of the way if (t_check_status("3[0-9][0-9]")) { exit; } # log the failed call route(failedcall); # If we got an error that wasn't some sort of far-end error, use another GW if (use_next_gw()) { # Since we have more gateways, keep coming back, and forward t_on_failure("term"); route(1); exit; } else { t_reply("503", "DROUTE use_next_gw failure no more gateways"); exit; } } route[orig] { # Load Balance block. Send calls from carriers to telephony servers # based upon the active number of calls each server is handling based # as a percentage of configured max trunks. # normalize calls first route(normorig); # Create call dialog create_dialog("B"); avp_printf("$avp(direction)", "Orig"); do_accounting("db", "cdr|missed|failed", "acc"); # Look up our dynamic routing entries courtesy of droute if (!load_balance("1","trunk")) { sl_send_reply("500", "LOADBALANCE failure"); exit; } # Since the LB call merely sets the destination IP without modifying the RURI # We have to modify it here so the remote end will like us $rd=$dd; set_dlg_profile("channelcount","$dd"); # Set up response handling and route t_on_failure("orig"); t_on_reply("stripcid"); route(topohiding); route(1); } failure_route[orig] { # Load Balance failover # 487's should just be relayed on through as part of the dialog if (t_check_status("487")) { t_relay(); exit; } # If the transaction was cancelled, quit processing this route if(!t_was_cancelled()) { exit; } # Treat a 486 from the carrier as legit if (t_check_status("486")) { t_reply("486", "Busy"); exit; } # Filter out redirects or basically do nothing if (t_check_status("3[0-9][0-9]")) { exit; } # log the failed call route(failedcall); # At this point we will use another GW if (load_balance("1","trunk","1")) { # Since we have more gateways, keep coming back, and forward $rd=$dd; t_on_failure("orig"); # Put our routing info in xlog("LOADBALANCE : Sending to $rd"); route(1); exit; } else { t_reply("503", "LOADBALANCE : FR4 no more destinations"); exit; } } route[normterm] { # Some basic normalization, validation and NANPA checks, for termination # Seven digits just isn't enough, be more helpful if (uri=~"^sip:[2-9]{1}[0-9]{6}@") { sl_send_reply("484", "Address Incomplete NANPA 10D only"); exit; } # We can guess with 10 digits, auto add 1, since we are in the US to normalize for further use if (uri=~"^sip:[0-9]{10}@") { prefix("1"); } # Allow E.164 style dialing in but strip the + to normalize if (uri=~"^sip:\+1[0-9]{10}@") { strip(1); } # If someone tries to dial information then kill call if (uri=~"^sip:1[0-9]{3}5551212@") { sl_send_reply("603", "Dont Dial Information"); exit; } # Valid NANPA format check 1 if (uri=~"^sip:1[0-1]{1}[0-9]{9}@") { sl_send_reply("484", "Invalid Area Code"); exit; } # Valid NANPA format check 2 if (uri=~"^sip:1[0-9]{3}[0-1]{1}[0-9]{6}@") { sl_send_reply("484", "Invalid Switch Code"); exit; } } route[normorig] { # Some basic normalization, validation and NANPA checks, for origination # Seven digits just isn't enough, be more helpful if (uri=~"^sip:[2-9]{1}[0-9]{6}@") { sl_send_reply("484", "Address Incomplete NANPA 10D only"); exit; } # Valid NANPA format check 1 if (uri=~"^sip:1[0-1]{1}[0-9]{9}@") { sl_send_reply("484", "Invalid Area Code"); exit; } # Valid NANPA format check 2 if (uri=~"^sip:1[0-9]{3}[0-1]{1}[0-9]{6}@") { sl_send_reply("484", "Invalid Switch Code"); exit; } # If we get 1+ NANPA format, strip the 1 to normalize if (uri=~"^sip:1[2-9]{1}[0-9]{2}[2-9]{1}[0-9]{6}@") { strip(1); } # Allow E.164 style dialing in but strip the +1 to normalize if (uri=~"^sip:\+1[2-9]{1}[0-9]{2}[2-9]{1}[0-9]{6}@") { strip(2); } } onreply_route[stripcid] { # A new trend for carriers is reverse Caller ID, or updating the Caller ID after connecting the call # Unfortunately Asterisk doesn't ignore this properly and it breaks the call tracking in vicidial # So instead we strip this header out on replies since they aren't needed or useful in vicidial if (is_present_hf("Remote-Party-ID")) { remove_hf("Remote-Party-ID"); } if (is_present_hf("P-Asserted-Identity")) { remove_hf("P-Asserted-Identity"); } if (is_present_hf("P-Preferred-Identity")) { remove_hf("P-Preferred-Identity"); } if (is_present_hf("Privacy")) { remove_hf("Privacy"); } } route[topohiding] { record_route(); # for initial invites we create dialog with topo hiding if ( is_method("INVITE") && !has_totag() ) { create_dialog("B"); # Should be previously set from route 3 and 4, but calling it again should be fine topology_hiding(); } } route[failedcall] { # Logs failed calls to the acc table for later $var(method)=$(rm{s.escape.common}); $var(fromtag)=$(ft{s.escape.common}); $var(totag)=$(tt{s.escape.common}); $var(callid)=$(ci{s.escape.common}); $var(sipcode)=$(T_reply_code{s.escape.common}); $var(sipreason)=$(err.rreason{s.escape.common}); $var(currtime)=$time(%Y-%m-%d %H-%M-%S); $var(sipfrom)=$(fu{s.escape.common}); $var(sipto)=$(tu{s.escape.common}); $var(destinationip)=$(rd{s.escape.common}); $var(sourceip)=$(si{s.escape.common}); xlog("$rm $si $ru $ci - Call failed, inserting"); avp_db_query("insert into opensips_local.acc (method, from_tag, to_tag, callid, sip_code, sip_reason, time, duration, setuptime, created, sip_from, sip_to, destination_ip, source_ip, direction, failure) values ('$var(method)', '$var(fromtag)', '$var(totag)', '$var(callid)', '$var(sipcode)', '$var(sipreason)', '$var(currtime)', '0', '0', '$var(currtime)', '$var(sipfrom)', '$var(sipto)', '$var(destinationip)', '$var(sourceip)', '$avp(direction)', 'Y');"); }