[SR-Users] Kamailio + RTPEngine SIP Proxy...

David Walsh davow at onthenet.com.au
Sat Sep 24 03:36:06 CEST 2022


Hi Jerry,
            I just joined so am unsure if you are good to go now but thought I would post my config as I also have a Freeswitch environment which I have placed Kamailio in front of to act as a load-balancing proxy. I also managed to get RTPEngine proxying through it too.


Here is the config, which I have created from Daniel’s default kamailio config.  I have omitted the top portions of loading the modules and their settings. My dispatcher list is just a text file. I have two groups. One for registrations and outbound calls, and one for calls inbound coming from the FreeSwitch server.

In the NATMANAGE route, I currently have RTP proxying disabled as my free switch servers have external IPs and I let them handle the rtp stream.

On Freeswitch, I made the following changes to accomodate user/pass and IPAuth reg:

Changes to the Freeswitch servers listed in the dispatcher file
Edit /usr/local/freeswitch/conf/autoload_configs/acl.conf
<list name="proxy" default="deny">
     <node type="allow" cidr=“IP address of Kamailio/32"/>
   </list>

Edit /usr/local/freeswitch/conf/sip-profiles/internal-private.xml    (or the sip-profile you need to edit in your instance)
<param name="apply-proxy-acl" value="proxy"/>  #Add this line above the one below. This tells Freeswitch to look at the X-Auth-IP header which was inserted by Kamailio.
  
<param name="apply-inbound-acl" value="domains"/>
Then, restart freeswitch (with no active calls),
service freeswitch restart     # or rescan the profile / reloadxml


I am not proxying RTP, however, I can un-comment out the stanza in the NATMANAGE route to get it to work.



The biggest gotcha for me was I was trying to use fix_nated_register when handling NAT for registrations instead of:

Fix_nated_contact() or the better set_contact_alias().

Using add_path_received(); in the Dispatcher just before sending to Freeswitch ensured all traffic returned to Kamailio too.

I am unsure of the SUBSCRIBE/PRESENCE stuff for you but the route should go out via the Kamailio proxy with this.


----------------------------
# main request routing logic

request_route {

	xlog("L_WARN", "--- Going to <$ru>. src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si\n");
	# per request initial checks
	route(REQINIT);

	# NAT detection
	route(NATDETECT);

    if(ds_is_from_list("33")) {
	    setflag(FLT_FS);
	    #xlog("L_WARN", "This source $si is from the dispatcher list.\n");
     }

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

	# handle retransmissions
	if (!is_method("ACK")) {
		if(t_precheck_trans()) {
			t_check_trans();
			exit;
		}
		t_check_trans();
	}

	# handle requests within SIP dialogs
	route(WITHINDLG);

	# record routing for dialog forming requests (in case they are routed)
	# - remove preloaded route headers
	remove_hf("Route");
	if (is_method("INVITE|SUBSCRIBE")) {
		xlog("L_WARN", "--- Going to <$ru>. src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si\n");
		xlog("L_ALERT", "Marker 1\n");
		record_route();
	}

	# account only INVITEs
	if (is_method("INVITE")) {
		setflag(FLT_ACC); # do accounting
	}
	
	if (isflagset(FLT_FS)) {
                ##t_on_reply("EXTERNAL_REPLY");
                route(FROM_FS);
                exit;
        }

	# handle presence related requests
	route(PRESENCE);

	# handle registrations
	route(REGISTRAR);

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

	# dispatch destinations
	route(DISPATCH);

	return;
}

route[FROM_FS]
{
        #record_route();
	#loose_route_preloaded();
	route(DLGURI);
        route(RELAY);
        exit;
}

route[RELAY] {

	# enable additional event routes for forwarded requests
	# - serial forking, RTP relaying handling, a.s.o.
	if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
		if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
	}
	if (is_method("INVITE|SUBSCRIBE|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;
}

#reply_route {
#    if(status == 403) {
#        xlog("L_WARN", "Forbidden from $si:$sp blah...\n");
#	xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
#    }
#}

onreply_route[LOGRPL] {
      if(status == 403) {
	  xlog("L_ALERT", "$rs response. Consider banning AVP \"ipbancandidate\" is $avp(ipbancandidate) ");
      }
}

# Per SIP request initial checks
route[REQINIT] {
	# no connect for sending replies
	# Enable tracing for SNGREP
	##sip_trace();
	##setflag(24);
	#
	set_reply_no_connect();
	# enforce symmetric signaling
	# - send back replies to the source address of request
	force_rport();

#!ifdef WITH_ANTIFLOOD
	# flood detection from same IP and traffic ban for a while
	# be sure you exclude checking trusted peers, such as pstn gateways
	# - local host excluded (e.g., loop to self)
	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;
		}
	}
#!endif
	if($ua =~ "friendly|scanner|sipcli|sipvicious|VaxSIPUserAgent|pplsip|Hello\ SIP\ Automated") {
		# silent drop for scanners - uncomment next line if want to reply
		# sl_send_reply("200", "OK");
	        xlog("User agent is: $ua\n");
		exit;
	}

	if (!mf_process_maxfwd_header("10")) {
		sl_send_reply("483","Too Many Hops");
		exit;
	}

	if(is_method("OPTIONS") && uri==myself && $rU==$null) {
		sl_send_reply("200","Keepalive");
		exit;
	}

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

# Handle requests within SIP dialogs
route[WITHINDLG] {

	if (!has_totag()) return;

	# sequential request withing a dialog should
	# take the path determined by record-routing
	if (loose_route()) {
	  	xlog("L_INFO", "Routing before DLGURI\n");	
		route(DLGURI);
		if (is_method("BYE")) {
			setflag(FLT_ACC); # do accounting ...
			setflag(FLT_ACCFAILED); # ... even if the transaction fails
		} else if ( is_method("ACK") ) {
			# ACK is forwarded statelessly
			route(NATMANAGE);
		} else if ( is_method("NOTIFY") ) {
			# Add Record-Route for in-dialog NOTIFY as per RFC 6665.
			record_route();
		}
		route(RELAY);
		exit;
	}

	if (is_method("SUBSCRIBE") && uri == myself) {
		# in-dialog subscribe requests
		route(PRESENCE);
		exit;
	}
	if ( is_method("ACK") ) {
		if ( t_check_trans() ) {
			# no loose-route, but stateful ACK;
			# must be an ACK after a 487
			# or e.g. 404 from upstream server
			route(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;
	xlog("L_WARN", "--- Going to <$ru>. src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si\n");
	add_path_received();
	$avp(ipbancandidate) = $si;
	if(isflagset(FLT_NATS)) {
		setbflag(FLB_NATB);
#!ifdef WITH_NATSIPPING
		# do SIP NAT pinging
		setbflag(FLB_NATSIPPING);
#!endif
	}
        route(DISPATCH);
	if (!save("location")) {
		sl_reply_error();
	}
	exit;
}

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

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


# Caller NAT detection
route[NATDETECT] {
#!ifdef WITH_NAT
        if (nat_uac_test("19")) {
                if (is_method("REGISTER")) {
                        #fix_nated_register(); Disabled as we proxy registrations
                        #fix_nated_contact();
			set_contact_alias();
			##add_contact_alias();
			#fix_nated_sdp("3");
			xlog("L_ALERT", "Nat Registration nat fixed.\n");
                } else {
                        if(is_first_hop()) {
                                set_contact_alias();
				xlog("L_ALERT", "Contact NAT fixed\n");
                        	} 
			}
                setflag(FLT_NATS);
		xlog("L_ALERT", "FLT_NATS flag set\n");
       } 
#!endif
        return;
}

# RTPProxy control and signaling updates for NAT traversal
route[NATMANAGE] {
#!ifdef WITH_NAT
	if (is_request()) {
		if(has_totag()) {
			if(check_route_param("nat=yes")) {
				setbflag(FLB_NATB);
			}
		}
	}
	if (nat_uac_test("3")) {
            #fix_nated_contact();
	    set_contact_alias();
	    ##add_contact_alias();
            force_rport();
        }
	if (has_body("application/sdp") && nat_uac_test("8")) {
            fix_nated_sdp("11");
        }

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

###!ifdef WITH_RTPENGINE
##	xlog("RTPEngine enabled\n");
##	if(nat_uac_test("8")) {
##		xlog("RTP 1\n");
##		rtpengine_manage("SIP-source-address replace-origin replace-session-connection");
##	} else {
##		rtpengine_manage("replace-origin replace-session-connection");
##	}
###!else
##	if(nat_uac_test("8")) {
##		rtpproxy_manage("co");
##	} else {
##		rtpproxy_manage("cor");
##	}
###!endif

	if (is_request()) {
		if (!has_totag()) {
			if(t_is_branch_route()) {
				add_rr_param(";nat=yes");
				 xlog("Nat notation added!\n");
			}
		}
	}
	if (is_reply()) {
		if(isbflagset(FLB_NATB)) {
			if(is_first_hop())
				#fix_nated_contact();
				set_contact_alias();
				#add_contact_alias();
		}
	}

	if(isbflagset(FLB_NATB)) {
		# no connect message in a dialog involving NAT traversal
		if (is_request()) {
			if(has_totag()) {
				set_forward_no_connect();
			}
		}
	}
#!endif
	return;
}

# URI update for dialog requests
route[DLGURI] {
#!ifdef WITH_NAT
	if(!isdsturiset()) {
		handle_ruri_alias();
		xlog("L_INFO", "Routing in-dialog $rm from $fu to $du\n");
	}
#!endif
	return;
}

# Dispatch requests
route[DISPATCH] {
	# round robin dispatching on gateways group '1'
	remove_hf_re("Subject|P-.*|X-.*");
        append_hf("X-Auth-IP: $si\r\n");
	#add_rr_param(";nat=yes");
	t_on_reply("LOGRPL");
	if(!ds_select_dst("1", "0")) {
		send_reply("404", "No destination");
		exit;
	}
	#xdbg("--- SCRIPT: going to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n");
	xlog("L_WARN", "--- Going to <$ru>. src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si; $RAi; $Ri;\n");
	t_on_failure("RTF_DISPATCH");
	route(RELAY);
}

# Try next destionations in 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()) {
			xdbg("--- SCRIPT: retrying to <$ru> via <$du> (attrs: $xavp(_dsdst_=>attrs))\n");
			t_on_failure("RTF_DISPATCH");
			route(RELAY);
			exit;
		}
	}
}

# Manage outgoing branches
branch_route[MANAGE_BRANCH] {
	xdbg("new branch [$T_branch_idx] to $ru\n");
	xlog("L_ALERT", "Marker 20\n");
	route(NATMANAGE);
	return;
}

# Manage incoming replies
reply_route {
	if(!sanity_check("17604", "6")) {
		xlog("Malformed SIP response from $si:$sp\n");
		drop;
	}
	return;
}

# Manage incoming replies in transaction context
onreply_route[MANAGE_REPLY] {
	xdbg("incoming reply\n");
	xlog("L_ALERT", "Marker 21\n");
	if(status=~"[12][0-9][0-9]") {
		route(NATMANAGE);
	}
#	 if (has_body("application/sdp")) {
#                rtpengine_manage();
#        }
	return;
}

# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
	xlog("L_ALERT", "Marker 23\n");
	route(NATMANAGE);

	if (t_is_canceled()) exit;

#!ifdef WITH_BLOCK3XX
	# block call redirect based on 3xx replies.
	if (t_check_status("3[0-9][0-9]")) {
		t_reply("404","Not found");
		exit;
	}
#!endif

#!ifdef WITH_BLOCK401407
	# block call redirect based on 401, 407 replies.
	if (t_check_status("401|407")) {
		t_reply("404","Not found");
		exit;
	}
#!endif

#!ifdef WITH_VOICEMAIL
	# serial forking
	# - route to voicemail on busy or no answer (timeout)
	if (t_check_status("486|408")) {
		$du = $null;
		route(TOVOICEMAIL);
		exit;
	}
#!endif
	return;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.kamailio.org/pipermail/sr-users/attachments/20220924/971aa766/attachment.htm>


More information about the sr-users mailing list