[OpenSIPS-Users] Opensips behind a NAT - change record-route

Ben Newlin Ben.Newlin at genesys.com
Thu Jan 11 12:49:33 EST 2018


John,

You just need to tell OpenSIPS to use the public IP in messaging instead of the private IP. You can do this a few ways depending on your scenario and your requirements.

If you can use the public IP always, when sending both to Asterisk and the SIP provider, then you can use the global parameter set_advertised_address [1]. This will cover all messaging and is the easiest method.

If the Asterisk side must use the private IP, then one way is to have two separate interfaces, and set the advertised address of the public-facing one to the Public NAT IP using the “as” function of the “listen” parameter [2]. Then you can use routing rules on the host or the force_send_socket() [3] function to send messages out the appropriate interface for internal or external. OpenSIPS should use the appropriate address in messaging, including (I believe) the necessary double record-routing, although this may require the setting of the mhomed [4] parameter, I am not sure.

If you only have one interface available on the machine, then you can use the record_route_preset() [5] function but you can’t use it in a reply, as you say. Record-Route headers are added as the Request passes through, not on the reply. You will also have to double record-route so there will be a record for each interface the message traverses (public and private). So on an initial request from the public network, you will record route the private first, then the public, like so:

record_route_preset("PRIVATE_ADDRESS:LOCAL_PORT", "PUBLIC_ADDRESS:LOCAL_PORT");
add_rr_param(";r2=on");

On a request from the private to public network, you would reverse the order of the addresses in the record-route. The “r2=on” parameter is necessary to let OpenSIPS know that double record-routing was used, so that both Route headers will be removed when loose_route() is called for sequential requests. This is the way I have implemented it as neither of the other two options would work for me.

There are probably also a few other ways to do it too. ☺

[1]  - http://www.opensips.org/Documentation/Script-CoreParameters-2-3#toc25
[2] - http://www.opensips.org/Documentation/Script-CoreParameters-2-3#toc63
[3] - http://www.opensips.org/Documentation/Script-CoreFunctions-2-3#toc16
[4] - http://www.opensips.org/Documentation/Script-CoreParameters-2-3#toc78
[5] - http://www.opensips.org/html/docs/modules/2.3.x/rr.html#idp5595248

Ben Newlin


From: Users <users-bounces at lists.opensips.org> on behalf of John Hablitzel <jjblitz071 at gmail.com>
Reply-To: OpenSIPS users mailling list <Users at lists.opensips.org>
Date: Thursday, January 11, 2018 at 12:18 PM
To: "Users at lists.opensips.org" <Users at lists.opensips.org>
Subject: [OpenSIPS-Users] Opensips behind a NAT - change record-route

Relatively new to OpenSIPS but have been working with Asterisk and VoIP for several years.  We want to use the load balancer or dispatcher modules to distribute inbound calls from a SIP provider among several Asterisk servers.  This will be coming in from another private network that is out of our control, therefore security is definitely required.  We won't be using OpenSIPS to control far-end clients that are behind NAT (far-end).

I know that it is recommended in this situation that OpenSIPS be on a public IP (or IP on the "outside" network", but the requirement in this particular situation is that this must be behind a NAT firewall, as there are other IP communications from servers on the the internal network that must use this same outside IP for communications with other services.  The outside network provider only allows us to have a single IP on their network for everything.

I have the inbound calls mostly working now in my lab with the LB module, using RTPProxy to anchor the media and some of the nathelper stuff.  However am seeing issues with the ACK on the 200OK being sent to the internal OpenSIPS IP and not the external IP on the NAT.  I believe this is due to the Internal IP being in the record-route header on the 200OK.  Pouring through the forums and other documentation I can find, I haven't been able to find any way to change this.

So I have 2 questions:
1) Is OpenSIPS even capable of operating in this mode?  In everything I've read, there is a bunch of documentation about handling NAT at the far-end, where UAC's are behind a NAT, but very little (and nothing with any concrete solution) about using OpenSIPS server behind a NAT.
2) if it is possible, can anyone provide a sample .cfg where they are have accomplished it?  I tried adding record_route_preset to the reply section, but OpenSIPS complains saying it can't be added in a reply section.

Here is my setup.  Any help will be greatly appreciated.

Asterisk PBXs<---------------------OpenSIPS<-------------------------------Firewall<---------------------------Trunk Provider (Asterisk box)
10.95.95.235                            10.95.95.220                       10.95.95.1 - 192.168.85.252                        192.168.85.242
10.95.95.236

My .cfg.  I realize there is a bunch of extra "stuff" here, but am working from a template at this point since I'm still going through the huge learning curve of OpenSIPS.

####### Global Parameters #########

log_level=4 #debug
#log_level=3 #info
log_stderror=no
log_facility=LOG_LOCAL0

children=4

/* uncomment the following lines 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:10.95.95.220:5060<http://10.95.95.220:5060>   # CUSTOMIZE ME

#listen=tcp:10.95.95.220:5060<http://10.95.95.220:5060>   # CUSTOMIZE ME


####### Modules Section ########

#set module path
mpath="/usr/local/lib64/opensips/modules/"

#### 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", 0)

#### 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"
modparam("registrar", "tcp_persistent_flag", "TCP_PERSISTENT")
modparam("registrar", "received_avp", "$avp(received_nh)")
/* 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)


####  NAT modules
loadmodule "nathelper.so"
modparam("nathelper", "natping_interval", 10)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", "SIP_PING_FLAG")
modparam("nathelper", "sipping_from", "sip:pinger at 192.168.85.252<mailto:sip%3Apinger at 192.168.85.252>") #CUSTOMIZE ME
modparam("nathelper", "received_avp", "$avp(received_nh)")

loadmodule "rtpproxy.so"
modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:7722") # CUSTOMIZE ME

loadmodule "proto_udp.so"

#loadmodule "proto_tcp.so"

loadmodule "db_mysql.so"

loadmodule "dialog.so"
modparam("dialog", "db_mode", 1)
modparam("dialog", "db_url", "mysql://opensips:opensips@localhost/opensips")

loadmodule "load_balancer.so"
modparam("load_balancer", "db_url", "mysql://opensips:opensips@localhost/opensips")
modparam("load_balancer", "probing_method", "OPTIONS")
modparam("load_balancer", "probing_interval", 10)


####### Routing Logic ########

# main request routing logic

route{
xlog("starting route\n");
force_rport();
if (nat_uac_test("23")) {
xlog("we have a NAT\n");
if (is_method("REGISTER")) {
fix_nated_register();
setbflag(NAT);
} else {
fix_nated_contact();
setflag(NAT);
}
}

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

if (has_totag()) {
# sequential request withing a dialog should
# take the path determined by record-routing
xlog("has_totag\n");
if (loose_route()) {
xlog("loose_route\n");
if (is_method("BYE")) {
# do accounting even if the transaction fails
do_accounting("log","failed");
} 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.
record_route();
}

if (check_route_param("nat=yes"))
setflag(NAT);

# 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
t_relay();
exit;
} else {
# ACK without matching transaction ->
# ignore and discard
exit;
}
}
sl_send_reply("404","Not here");
}
exit;
}

# OPTIONS processing - don't forward
if (is_method("OPTIONS")) {
sl_send_reply("200", "OK");
xlog("OPTIONS received\n");
exit;
}
# CANCEL processing
if (is_method("CANCEL"))
{
xlog("CANCEL received\n");
if (t_check_trans())
t_relay();
exit;
}

t_check_trans();

/* if ( !(is_method("REGISTER")  ) ) {
xlog("check_trans - to=$tu/from=$fu/request=$ru\n");
if (from_uri==myself){
}
else {
# if caller is not local, then called number must be local
if (!uri==myself) {
send_reply("403","Relay forbidden");
exit;
}
}
}*/

# preloaded route checking
if (loose_route()) {
xlog("L_ERR",
"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"))
record_route();

# account only INVITEs
if (is_method("INVITE")) {
do_accounting("log");
}

if (!uri==myself) {
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 (is_method("REGISTER"))
{

if ( proto==TCP ||  0 ) setflag(TCP_PERSISTENT);

if (isflagset(NAT)) {
setbflag(SIP_PING_FLAG);
}

if (!save("location"))
sl_reply_error();

exit;
}

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


# do lookup with method filtering
if (!lookup("location","m")) {
t_newtran();
t_reply("404", "Not Found");
exit;
}

if (isbflagset(NAT)) setflag(NAT);

# when routing via usrloc, log the missed calls also
do_accounting("log","missed");
route(relay);
}


route[relay] {
if (isflagset(NAT)) {
xlog("adding rr_param\n");
add_rr_param(";nat=yes");
}

# for INVITEs enable some additional helper routes
if (is_method("INVITE")) {
xlog("incoming INVITE\n");
if (isflagset(NAT)) {
xlog("incoming INVITE with NAT\n");
rtpproxy_offer("ro");
}

t_on_branch("per_branch_ops");
t_on_reply("handle_nat");
t_on_failure("missed_call");

xlog("calling lb_start_or_next\n");
lb_start_or_next("1","pstn","r");
if ($retcode<0) {
             xlog("calling lb_start_or_next\n");
sl_send_reply("500","Internal Error");
             exit;
}
xlog("Selected destination is: $du\n");
# send it out
if (!t_relay()) {
xlog("relay failed\n");
sl_reply_error();
}
}
else {
xlog("reply\n");
t_on_failure("missed_call");
t_relay();
exit;
}
xlog("exiting route-relay\n");
exit;
}


branch_route[per_branch_ops] {
xlog("new branch at $ru\n");
}


onreply_route[handle_nat] {
xlog("onreply_route-handle nat\n");

if (nat_uac_test("1")) {
xlog("nat test yes\n");
fix_nated_contact();
}
if ( isflagset(NAT) ) {
xlog("nat flag set-doing rtpproxy answer\n");
rtpproxy_answer("ro");
}
}


failure_route[missed_call] {
xlog("failure route - trying next destination\n");
lb_disable_dst();
if (lb_start_or_next("1","pstn","r")) {
t_on_failure("missed_call");
t_relay();
}
else {
xlog("no destinations available\n");
t_reply("503", "Service Unavailable");
}
}
# 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;
##}







-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.opensips.org/pipermail/users/attachments/20180111/28529d17/attachment-0001.html>


More information about the Users mailing list