[SR-Users] Problem implementing Outbound Proxy

Christoph Russow russow at emtex.de
Tue Nov 23 15:26:55 CET 2021


Hi all,

im currently trying to add a Outbound Proxying to our system which right 
now does inbound loadbalancing for our application servers.

Current:
Inbound SIP Trunk -> Kamailio -> dispatcher -> ApplicationServer 1..n

i now want to add the ability for our internal Application Servers to 
terminate their outbound calls through the kamailio system.

currently i've setup a gateway in the (freeswitch) application server 
that has the kamailio system set as outbound-proxy. this leads to sip 
calls started with

originate sofia/gateway/kamailio/<number>@<outbound carrier IP>

to be sent to the kamailio system which then forwards it to the given 
carrier IP. Sadly our main carrier answers with "503 service unavailable 
- no bandwith available". (maybe due to the internal ip-addresses within 
some of the headers?)

i've attached our current kamailio configuration and also a pcap of a 
call i tried to start with our main carrier.

i tried this way as it seemed to be the easiest way so our application 
servers still can select the outbound carrier within their flow.

maybe i'm on the wrong way here and need to solve this problem in a 
completely different way i don't know.

TLDR: sip proxying does not work as expected. need a way to achieve 
outbound calls routed through kamailio from internal application servers

any hint/help into the right direction is appreciated

Best Regards
Christoph Russow

-- 
________________________________________________________________

EMTEX GmbH
Christoph Russow
Software Engineer

Bischof-Otto-Weg 9
D-91086 Aurachtal
                            Geschäftsführer:       Markus Enzinger
Tel. +49 9132 7490 0      Sitz der Gesellschaft: 91086 Aurachtal
Fax. +49 9132 7490 900    Amtsgericht Fürth:     HRB6804
________________________________________________________________
-------------- next part --------------
#!KAMAILIO
#
# Kamailio SBC Configuration 
# Emtex 07-2020
# <cr>
#
# Simple routing of all inbound calls to all configured application servers
# application servers configured in mysql database
#
#
# Configuration
#!define DBURL "mysql://kamailio:xxxxxxxxxxxx@localhost/kamailio"
# !define WITH_DEBUG
mpath="/usr/lib/x86_64-linux-gnu/kamailio/modules"


#!define INTERNAL_IP 192.168.10.180
#!define EXTERNAL_IP 88.198.223.80


#
# Program Config
# 

#!ifdef WITH_DEBUG
debug=4
log_stderror=yes
#!else
debug=2
log_stderror=no
#!endif

memdbg=5
memlog=5

log_facility=LOG_LOCAL0

fork=yes
children=4

# we want UDP only
disable_tcp=yes

# no aliases ?!
auto_aliases=no

# local domains
alias="88.198.223.80"

port=5060

listen=udp:EXTERNAL_IP:5060
listen=udp:INTERNAL_IP:5060

sip_warning=no

loadmodule "db_mysql.so"
# loadmodule "mi_fifo.so"
loadmodule "kex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
#loadmodule "mi_rpc.so"
loadmodule "acc.so"
loadmodule "dispatcher.so"
loadmodule "jsonrpcs.so"
loadmodule "sqlops.so"

#
# Module specific Parameters
#
# ----- mi_fifo params -----
# modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")

# ----- rr params -----
# add value to ;lr param to cope with most of the UAs
modparam("rr", "enable_full_lr", 1)
# do not append from tag to the RR (no need for this script)
modparam("rr", "append_fromtag", 0)

# ----- acc params -----
modparam("acc", "log_flag", 1)
modparam("acc", "failed_transaction_flag", 3)
modparam("acc", "log_extra", "src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si")

# ----- tm params -----
modparam("tm", "fr_timer", 2000)
modparam("tm", "fr_inv_timer", 40000)

# ----- 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", "ds_ping_from", "sip:sbc at primary.sip.intra.emtex.net") 
modparam("dispatcher", "ds_ping_interval", 5) # default: 0
#modparam("dispatcher", "ds_probing_threshold", 10) # default: 1
modparam("dispatcher", "ds_inactive_threshold", 6) # default: 1
modparam("dispatcher", "ds_probing_mode", 1) # default: 0
modparam("dispatcher", "ds_ping_latency_stats", 1) # default: 0

modparam("sqlops","sqlcon","altdb =>mysql://kamailio:xxxxxxxxxxxx@192.168.10.68/MASTER")

#
# Call Routing
#

# main request routing logic

route {

	# per request initial checks
	route(REQINIT);

	# handle requests within SIP dialogs
	route(WITHINDLG);

	### only initial requests (no To tag)

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

	t_check_trans();

	# record routing for dialog forming requests (in case they are routed)
	# - remove preloaded route headers
	remove_hf("Route");
	if (is_method("INVITE|SUBSCRIBE"))
		record_route();

	# account only INVITEs
	if (is_method("INVITE")) {
		setflag(1); # do accounting
	}

	# handle presence related requests
	route(PRESENCE);

	# handle registrations
	route(REGISTRAR);

	if (uri==myself) {
		if ((method==OPTIONS) && (! uri=~"sip:.*[@]+.*")) {
			options_reply();
		}
	}

	if ($rU==$null) {
		# request with no Username in RURI
		sl_send_reply("484","Address Incomplete");
		exit;
	}

	# Route Outbound
	route(SIPOUT);

	# dispatch destinations
	route(DISPATCH);

	route(RELAY);
}


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

# Per SIP request initial checks
route[REQINIT] {
	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}

	if(!sanity_check("1511", "7")) {
		xlog("Malformed SIP message from $si:$sp\n");
		exit;
	}
}

# 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()) {
			if (is_method("BYE")) {
				setflag(1); # do accounting ...
				setflag(3); # ... even if the transaction fails
			}
			route(RELAY);
		} else {
			if (is_method("SUBSCRIBE") && uri == myself) {
				# in-dialog subscribe requests
				route(PRESENCE);
				exit;
			}
			if ( is_method("ACK") ) {
				if ( t_check_trans() ) {
					# non loose-route, but stateful ACK;
					# must be 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;
	}
}

# Handle SIP registrations
route[REGISTRAR] {
	if(!is_method("REGISTER"))
		return;
	sl_send_reply("404", "No registrar");
	t_relay();
	
	exit;
}

# Presence server route
route[PRESENCE] {
	if(!is_method("PUBLISH|SUBSCRIBE"))
		return;

	sl_send_reply("404", "Not here");
	exit;
}

# Route Outbound Calls
route[SIPOUT] {
        if (uri==myself) return;

	# only allow outbound routing if packet comes over our internal ip
	if ($Ri!=$def(INTERNAL_IP)) {
		send_reply("403", "you shall not pass!");
		exit;
	}

        append_hf("P-hint: outbound\r\n");
	force_send_socket(udp:EXTERNAL_IP:5060);
        route(RELAY);
        exit;
}



# Dispatch requests
route[DISPATCH] {
	# check if requested number is active on the old cluster system
	$var(foo) = sql_xquery("altdb", "select LAUF, char_length(KDRUFNUMMER) as RN_LEN from PROGTABLE where '$(tU{s.numeric})' like CONCAT(KDRUFNUMMER, '%') and AKTIV_AB < NOW() and AKTIV_BIS > NOW() order by RN_LEN desc", "resultset");
	xlog("L_INFO", "sql_xquery result = $var(foo) \n");
	if ($var(foo) == 1)  {
		# number IS active -> route to old system (dispatcher group 2)
		xlog("L_INFO", "Routing to old System dispatcher\n");
		if(!ds_select_dst(2, 4)) {
			# no active system found (not answerering to OPTIONS)
			xlog("L_ERR", "Failed to route to old System!");
			send_reply("503", "Service temporary not available");
			exit;
		}
	} else {
		# number NOT active on OLD system -> route to new system and loadbalance (dispatcher group 1)
		xlog("L_INFO", "Routing to default dispatcher\n");
		if(!ds_select_dst(1, 4)) {
			xlog("L_ERR", "Failed to route to default system");
			send_reply("503", "Service temporary not available");
			exit;
		}

	}
	sql_result_free("resultset");
	t_on_failure("RTF_DISPATCH");
	return;
}

# Sample failure route
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;
		}
	}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 5601556c-c707-123a-6bab-c81f66c79ea0.pcap
Type: application/vnd.tcpdump.pcap
Size: 1434 bytes
Desc: not available
URL: <http://lists.kamailio.org/pipermail/sr-users/attachments/20211123/7c0c1a34/attachment.pcap>


More information about the sr-users mailing list