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;
}