I would like to use the opensips mid_registrar module in front of fusionpbx. However, I have some issues with handling the natted phones. I'm attaching below my opensips.cfg for reference.
The issue is that when a device behind nat receives a call (inbound), the ACKs are sent from the proxy to the private ip address and not the public ip : port. Funny thing is I have two-way audio but the call is not established because the ack does not come to the calling device.
If it is the natted device that makes the call, all works.
I'm sure I'm missing something obvious (mediaproxy... but how?)
The issue is that when a device behind nat receives a call (inbound), the ACKs are sent from the proxy to the private ip address and not the public ip : port. Funny thing is I have two-way audio but the call is not established because the ack does not come to the calling device.
If it is the natted device that makes the call, all works.
I'm sure I'm missing something obvious (mediaproxy... but how?)
C-like:
####### Global Parameters #########
log_level=4
log_stderror=yes
log_facility=LOG_LOCAL0
#children=4
/* uncomment the following line to enable debugging */
#debug_mode=yes
/* uncomment the next line to enable the auto temporary blacklisting of
not available destinations (default disabled) */
#disable_dns_blacklist=no
/* uncomment the next line to enable IPv6 lookup after IPv4 dns
lookup failures (default disabled) */
#dns_try_ipv6=yes
/* comment the next line to enable the auto discovery of local aliases
based on revers DNS on IPs */
auto_aliases=no
listen=udp:0.0.0.0:5060
####### Modules Section ########
#set module path
mpath="/usr/local/lib64/opensips/modules/"
loadmodule "mid_registrar.so"
modparam("mid_registrar", "mode", 2) /* 0 = mirror / 1 = ct / 2 = AoR */
modparam("mid_registrar", "outgoing_expires", 7200)
modparam("mid_registrar", "received_avp", "$avp(received)")
modparam("mid_registrar", "received_param", "received")
#### Removed ??? modparam("mid_registrar", "insertion_mode", 0) /* 0 = contact; 1 = path */
#### SIGNALING module
loadmodule "signaling.so"
#### StateLess module
loadmodule "sl.so"
#### Transaction Module
loadmodule "tm.so"
modparam("tm", "fr_timeout", 5)
modparam("tm", "fr_inv_timeout", 30)
modparam("tm", "restart_fr_on_each_reply", 0)
modparam("tm", "onreply_avp_mode", 1)
#### Record Route Module
loadmodule "rr.so"
/* do not append from tag to the RR (no need for this script) */
modparam("rr", "append_fromtag", 1)
#### MAX ForWarD module
loadmodule "maxfwd.so"
#### SIP MSG OPerationS module
loadmodule "sipmsgops.so"
#### FIFO Management Interface
loadmodule "mi_fifo.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
#### URI module
loadmodule "uri.so"
modparam("uri", "use_uri_table", 0)
#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "db_mode", 0)
#### REGISTRAR module
loadmodule "registrar.so"
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
#### ACCounting module
loadmodule "acc.so"
/* what special events should be accounted ? */
modparam("acc", "early_media", 0)
modparam("acc", "report_cancels", 0)
/* by default we do not adjust the direct of the sequential requests.
if you enable this parameter, be sure the enable "append_fromtag"
in "rr" module */
modparam("acc", "detect_direction", 0)
### UAC Module ####
loadmodule "uac.so"
modparam("uac","restore_mode","auto")
modparam("rr", "append_fromtag", 1)
#### NAT modules
loadmodule "nathelper.so"
modparam("nathelper", "natping_interval", 60)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "received_avp", "$avp(received)")
modparam("nathelper", "sipping_from", "sip:nat-alive@mid_registrar")
### Mediaproxy
loadmodule "mediaproxy.so"
modparam("mediaproxy", "media_relay_avp", "$avp(media_relay)")
#### UDP protocol
loadmodule "proto_udp.so"
####### Routing Logic ########
# main request routing logic
route{
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
exit;
}
if ( nat_uac_test("31")) {
if ( is_method("REGISTER")) {
fix_nated_register() ;
} else {
fix_nated_contact() ;
}
force_rport() ;
setbflag(NAT);
xlog("L_INFO", "[LOG] NATed. [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
}
if (has_totag()) {
# sequential requests within a dialog should
# take the path determined by record-routing
if (loose_route()) {
if (is_method("BYE")) {
# do accunting, even if the transaction fails
if (isbflagset(NAT)) {
end_media_session();
}
do_accounting("log","failed");
xlog("L_INFO", "[LOG] BYE. [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
} else if (is_method("INVITE")) {
# even if in most of the cases is useless, do RR for
# re-INVITEs alos, as some buggy clients do change route set
# during the dialog.
xlog("L_INFO", "[LOG] INVITE. [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
record_route();
}
# route it out to whatever destination was set by loose_route()
# in $du (destination URI).
route(relay);
} else {
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
xlog("L_INFO", "[LOG] ACK. [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
t_relay();
exit;
} else {
# ACK without matching transaction ->
# ignore and discard
xlog("L_INFO", "[LOG] ACK. not match [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
exit;
}
}
xlog("L_INFO", "[LOG] BAD REQUEST. [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
sl_send_reply("404","Not here");
}
exit;
}
# CANCEL processing
if (is_method("CANCEL"))
{
if (t_check_trans())
t_relay();
exit;
}
t_check_trans();
if (is_method("REGISTER")) {
xlog("L_INFO", "[LOG] REGISTER [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]");
mid_registrar_save("location","v"); #,"$avp(received)");
switch ($retcode) {
case 1:
$ru = "sip:fusion.pbx:5060";
t_relay();
break;
case 2:
xlog("L_INFO", "[LOG] absorbing REGISTER! ($$ci=$ci)\n");
break;
default:
xlog("L_INFO", "[LOG] failed to save registration! ($$ci=$ci)\n");
}
exit;
}
if ( is_method("INVITE|MESSAGE|CANCEL|BYE|NOTIFY") && ($si != "fusion.ip.add.ress" || $sp != 5060) ) {
$ru = "sip:fusion.pbx:5060";
xlog("L_INFO", "[LOG] relay to $avp(new_to_user) from $avp(new_from_user)\n");
}
# preloaded route checking
if (loose_route()) {
xlog("L_ERR", "[LOG] Attempt to route with preloaded Route's [$fu/$tu/$ru/$ci]");
if (!is_method("ACK"))
sl_send_reply("403","Preload Route denied");
exit;
}
# record routing
if (!is_method("REGISTER|MESSAGE|NOTIFY"))
record_route();
# account only INVITEs
if (is_method("INVITE")) {
do_accounting("log");
}
if (!is_myself("$rd")) {
append_hf("P-hint: outbound\r\n");
route(relay);
}
# requests for my domain
if (is_method("PUBLISH|SUBSCRIBE"))
{
sl_send_reply("503", "Service Unavailable");
exit;
}
if ($rU==NULL) {
# request with no Username in RURI
sl_send_reply("484","Address Incomplete");
exit;
}
# initial requests from main registrar, need to look them up!
# $si = ip.
if (is_method("INVITE|MESSAGE") && $si == "fusion.ip.add.ress" && $sp == 5060) {
xlog("L_INFO", "[LOG] INVITE|MESSAGE Received. looking up $ru!\n");
if (!mid_registrar_lookup("location")) {
xlog("L_ERR", "[LOG] Cannot find $ru!\n");
t_reply("404", "Not Found");
exit;
}
t_relay();
exit;
}
# when routing via usrloc, log the missed calls also
do_accounting("log","missed");
route(relay);
}
route[relay] {
# for INVITEs enable some additional helper routes
if (is_method("INVITE")) {
if ( isbflagset(NAT)) {
if ( has_body("application/sdp")) {
xlog("L_INFO", "[LOG] using media proxy");
use_media_proxy();
}
}
t_on_branch("per_branch_ops");
t_on_reply("handle_nat");
t_on_failure("missed_call");
}
if (isbflagset(NAT)) {
add_rr_param(";nat=yes");
}
if (!t_relay()) {
send_reply("500","Internal Error");
};
exit;
}
branch_route[per_branch_ops] {
xlog("L_INFO", "[LOG] new branch at $ru\n");
}
onreply_route[handle_nat] {
xlog("L_INFO", "[LOG] (handle_nat) incoming reply\n");
if ( nat_uac_test("1")) {
fix_nated_contact() ;
}
if ( isbflagset(NAT)) {
if ( has_body("application/sdp")) {
use_media_proxy();
}
}
if ( is_method("INVITE")) {
xlog("L_INFO", "[LOG] re-INVITE. [rm:$rm] [fu:$fu] [ou:$ou] [ru:$ru] [si:$si]\n");
}
}
failure_route[missed_call] {
if (t_was_cancelled()) {
exit;
}
# uncomment the following lines if you want to block client
# redirect based on 3xx replies.
##if (t_check_status("3[0-9][0-9]")) {
##t_reply("404","Not found");
## exit;
##}
}
Last edited: