[SR-Users] Calls to devices behind NAT not working

Adnan adnan at ttnc.co.uk
Thu Aug 28 12:39:28 CEST 2014


Hi all,

I'm trying to configure a Kamailio server, and am having trouble getting 
devices behind NAT receive calls. Looking at a SIP trace, nothing is 
being received by the end point, even though Kamailio seems to be 
sending out a response.

I've opened up my firewall rules, so that shouldn't be an issue.

If I call another endpoint which is behind the same NAT, it works 
(although no audio), and looking at the trace, the SIP messaging is 
coming from the Kamailio server (ie. not the other endpoint).

I've even tried using the default kamailio-advanced.cfg & 
kamailio-basic.cfg both of which didn't work either.

I've attached the current config I'm working on, if someone could please 
have a look through it, and see where I'm going wrong I'd highly 
appreciate it.


Thanks

Adnan
-------------- next part --------------
debug		=	2
fork		=	yes
log_stderror	=	no
listen      =	1.2.3.4
port		=	5060
children	=	4
log_facility	=	LOG_LOCAL0

alias=1.2.3.4

log_stderror=no

memdbg=0
memlog=0

dns		=	no
rev_dns		=	no

mpath		=	"/usr/lib/i386-linux-gnu/kamailio/modules"

loadmodule	"db_mysql.so"
loadmodule	"db_cluster.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	"usrloc.so"
loadmodule	"registrar.so"
loadmodule	"textops.so"
loadmodule	"siputils.so"
loadmodule	"xlog.so"
loadmodule	"sanity.so"
loadmodule	"ctl.so"
loadmodule	"auth.so"
loadmodule	"auth_db.so"
loadmodule	"nathelper.so"
loadmodule	"rtpproxy.so"
loadmodule	"sqlops.so"
loadmodule	"regex.so"

#!define DLG_FLAG 4
#!define FLT_NATS 5
#!define FLB_NATB 6
#!define FLB_NATSIPPING 7

modparam("tm", "failure_reply_mode", 3)
modparam("tm", "fr_timer", 30000)
modparam("tm", "fr_inv_timer", 120000)

modparam("rr", "enable_full_lr", 1)
modparam("rr", "append_fromtag", 0)
#modparam("rr", "add_username", 1)

modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")

modparam("registrar", "method_filtering", 1)
#modparam("registrar", "append_branches", 0)
#modparam("registrar", "max_contacts", 1)
modparam("registrar", "max_expires", 3600)
modparam("registrar", "gruu_enabled", 0)

modparam("nathelper", "natping_interval", 15)
modparam("nathelper", "ping_nated_only", 0)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
modparam("nathelper", "sipping_from", "sip:pinger at 1.2.3.4")

modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")

modparam("auth_db", "db_url", "mysql://*user*:*pass*@*ip*/*db*")
modparam("auth_db", "use_domain", 0)
modparam("auth_db", "version_table", 0)
modparam("auth_db", "load_credentials", "")

modparam("usrloc", "db_url", "mysql://*user*:*pass*@*ip*/*db*")
modparam("usrloc", "use_domain", 0)
modparam("usrloc", "nat_bflag", FLB_NATB)
modparam("usrloc", "db_mode", 1)

modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722")

modparam("alias_db", "db_url", "mysql://*user*:*pass*@*ip*/*db*")
modparam("alias_db", "use_domain", 0)

route {
	xlog("KAMAILIO: $rm: $fu -> $ru\n");

	route(SANITY);
	route(NAT);

	if (!method=="REGISTER") {
		record_route();

	}

	if(is_method("CANCEL")) {
		if(t_check_trans()) {
			route(RELAY);

		}
		exit;
	}

	route(DLG);

	t_check_trans();

	route(AUTH);

	remove_hf("Route");
	if(!is_method("REGISTER")) {
		record_route();

	}

	route(FREESWITCH);

	route(REGISTRAR);

	if($rU==$null) {
		sl_send_reply("484","Address Incomplete");
		exit;

	}

	route(INTERNAL);

}

route[NAT] {
	force_rport();

	if(nat_uac_test("19")) {
		if(is_method("REGISTER")) {
			fix_nated_register();
			xlog("KAMAILIO: REGISTER SIP message from $fu is behind NAT, fixing\n");

		} else {
			add_contact_alias();
			xlog("KAMAILIO: SIP message from $fu is behind NAT, fixing\n");

		}

		setflag(FLT_NATS);

	}

	return;

}

route[SANITY] {
	if(!mf_process_maxfwd_header("10")) {
		sl_send_reply("483", "Too Many Hops");
		xlog("KAMAILIO: (replied error 483) Too many hops\n");
		return;

	}

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

	}

	if(msg:len > 8192) {
		sl_send_reply("513", "Message too big" );
		xlog("KAMAILIO: (replied error 513) SIP message from $si:$sp too big\n");
		return;

	}

	return;

}

route[REGISTRAR] {
	if(is_method("REGISTER")) {
		if(isflagset(FLT_NATS)) {
			setbflag(FLB_NATB);
			setbflag(FLB_NATSIPPING);
		}

		exit;

	}

}

route[AUTH] {
    if (from_uri!=myself && uri!=myself) {
		sl_send_reply("403","Not relaying");
		xlog("KAMAILIO: (replied error 513) Not relaying");
		exit;

	}

	xlog("KAMAILIO: Checking if IP Address '$si' is allowed...\n");

	sql_xquery("db", "
			(SELECT
				1 AS trunk_id,
				'allow' AS action,
				1 AS owner,
				NULL AS rpid,
				1 AS dest_local", "result");

	if($xavp(result=>action) == "allow") {
		xlog("KAMAILIO: Great IP Address '$si' - Owner ($xavp(result=>owner)) is allowed!\n");

		remove_hf("X-Billing");
		append_hf("X-Billing: uid=$xavp(result=>owner); tid=$xavp(result=>trunk_id)\r\n");

	} else if($xavp(result=>action) == "deny") {
		xlog("KAMAILIO: IP Address '$si' is denied!\n");

		sl_send_reply("403","Forbidden");
		exit;

	} else {
		if(
			$xavp(result=>dest_local) == "1" &&
			is_method("INVITE|ACK|BYE|CANCEL")
		) {
			xlog("KAMAILIO: Destination is registered with us, no auth needed\n");

		} else {
			if(is_method("REGISTER") || from_uri==myself) {
				xlog("KAMAILIO: IP Address '$si' is not listed, we're gonna need a REGISTER to get any further.!\n");

				if(!www_authorize("1.2.3.4", "in_trunks")) {
					www_challenge("1.2.3.4", "1");
					exit;

				} else {
					xlog("KAMAILIO: Call is Authed!\n");

				}

			}

			if(!is_method("REGISTER|PUBLISH")) {
				consume_credentials();

			}

		}

		if(is_method("REGISTER")) {
			unregister("location", "$tu");
			if(!save("location")) {
				sl_reply_error();

			}

		}

	}

	$var(dest_local) = $xavp(result=>dest_local);
	$var(rpid) = $xavp(result=>rpid);
	$var(cli_name) = $xavp(result=>rpid);
	$var(cli_num) = $xavp(result=>rpid);
	$var(cli_clir) = 0;

	route(FIXFROM);

	return;

}

route[FIXFROM] {
	if($var(dest_local) == "0") {
		if(is_method("INVITE|CANCEL|BYE|ACK")) {
			# PAI/PPI-privacy
			if(is_present_hf("Privacy")) {
				if(!is_privacy("none")) {
					$var(cli_name) = "Anonymous";
					$var(cli_clir) = 1;
				}

			# RPID-privacy
			} else if($re) {
				if($(hdr(Remote-Party-ID)[0]) =~ ";privacy=" && !($(hdr(Remote-Party-ID)[0]) =~ ";privacy=off(;|$)")) {
					$var(cli_name) = "Anonymous";
					$var(cli_clir) = 1;
				}

			# From-privacy
			} else if($fU == "Anonymous" || $fU == "anonymous" || $fU == "Unavailable" || $fU == "Unknown" || $fU == "unknown") {
				$var(cli_name) = "Anonymous";
				$var(cli_clir) = 1;
			}

			# PAI-cli
			if($ai) {
				$var(cli_name) = $(hdr(P-Asserted-Identity)[0]{nameaddr.name}); # including dquotes
				$var(cli_num) = $(ai{uri.user});

			# PPI-cli
			} else if($pU) {
				$var(cli_name) = $pn; # including dquotes
				$var(cli_num) = $pU;

			# RPID-cli
			} else if($re) {
				$var(cli_name) = $(hdr(Remote-Party-ID)[0]{nameaddr.name}); # including dquotes
				$var(cli_num) = $(re{uri.user});

			# From-cli
			} else {
				# Privacy from fromname?
				if($fn == "Anonymous" || $fn == "\"Anonymous\"" || $fn == "anonymous" || $fn == "\"anonymous\"") {
					$var(cli_clir) = 1;
				}
			}

			if($var(rpid) =~ "^[0-9]+$" && $var(rpid) != "0") {
				xlog("KAMAILIO: We have an RPID ($var(rpid)) we are going to force!\n");

				$var(cli_clir) = 0;
				$var(cli_name) = $var(cli_num);
				$var(cli_num) = $var(cli_num);

				$fU = $var(cli_num);

			} else if($fU =~ "[A-Za-z\-\_]") {
				$var(cli_clir) = 1;
				$var(cli_name) = "Anonymous";
				$var(cli_num) = "anonymous";

				xlog("KAMAILIO: FROM $fU is non-numeric, replacing to anonymous!\n");

				$fU = "anonymous";

			}

			if($var(cli_name)) { pv_printf("$var(cli_name)", "$var(cli_name) "); } # add space
			if($var(cli_clir)) { $var(cli_clir) = "full"; } else { $var(cli_clir) = "off"; }

			if($var(cli_num)) {
				#remove_hf("Privacy");
				#remove_hf("P-Asserted-Identity");
				#remove_hf("P-Preferred-Identity");
				#remove_hf("Remote-Party-ID");

				#append_hf("Remote-Party-ID: $var(cli_name)<sip:$var(cli_num)@$si>;privacy=$var(cli_clir);screen=no\r\n");

				xlog("KAMAILIO: Changing FROM address: $fU -> $var(cli_num)!\n");

				#$fU = $var(cli_num);

			}

		}

	}

    return;

}



route[DLG] {
	if(has_totag()) {
		if(loose_route()) {
			if(!isdsturiset()) {
				handle_ruri_alias();

			}

			if(is_method("ACK")) {
				route(RTPPROXY);

			} else if(is_method("NOTIFY")) {
				record_route();

			}

			route(RELAY);

		} else {
			if(is_method("ACK")) {
				if(t_check_trans() ) {
					t_relay();
#					route(RELAY);
					exit;

				} else {
					exit;

				}

			}

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

		}

		exit;

	}

}

route[RTPPROXY] {
	if(is_request()) {
		if(has_totag()) {
			if(check_route_param("nat=yes")) {
				setbflag(FLB_NATB);
			}
		}
	}

	if(!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) {
		return;

	}

	rtpproxy_manage();

	if(is_request()) {
		if(!has_totag()) {
			add_rr_param(";nat=yes");
		}

	}

	if(is_reply()) {
		if(isbflagset(FLB_NATB)) {
			add_contact_alias();
		}

	}

}

route[RELAY] {
	if(is_method("INVITE|BYE|UPDATE")) {
		if(!t_is_set("branch_route")) {
			t_on_branch("MANAGE_BRANCH");

		}

	}

	if(is_method("INVITE|UPDATE")) {
		if(!t_is_set("onreply_route")) {
			t_on_reply("MANAGE_REPLY");

		}

	}

	if(is_method("INVITE")) {
		if(!t_is_set("failure_route")) {
			t_on_failure("MANAGE_FAILURE");

		}

	}

	if(!t_relay()) {
		sl_reply_error();

	}

	exit;

}

route[FREESWITCH] {
	if(
		$var(dest_local) == "0" &&
		is_method("INVITE|ACK|CANCEL|UPDATE|OPTIONS|BYE")
	) {
		if(from_uri!=myself) {
			sl_send_reply("403", "Not Allowed");
			exit;

		}

		xlog("KAMAILIO: Relaying to FS Server!\n");
		$ru = "sip:" + $rU + "@" + "4.3.2.1" + ":5060";

		append_hf("P-hint: outbound\r\n");

		route(RELAY);

	} else {
		xlog("KAMAILIO: NOT Relaying to FS Server (Local Call)!\n");

	}

}

route[INTERNAL] {
	if (!lookup("location")) {
		$var(rc) = $rc;
		t_newtran();
		switch ($var(rc)) {
			case -1:
			case -3:
				send_reply("404", "Not Found");
				exit;
			case -2:
				send_reply("405", "Method Not Allowed");
				exit;
		}
	}

	route(RELAY);
	exit;
}

# manage outgoing branches
branch_route[MANAGE_BRANCH] {
	route(RTPPROXY);

}

# manage incoming replies
onreply_route[MANAGE_REPLY] {
	if(status=~"[12][0-9][0-9]") {
		route(RTPPROXY);

	}
}

# manage failure routing cases
failure_route[MANAGE_FAILURE] {
	route(RTPPROXY);

	if(t_is_canceled()) {
		exit;

	}

}


More information about the sr-users mailing list