Oopensips Nat script with RTPPROXY - English
First of all, my english is not so good as i want, but im writing this in english too because i ever see a lot of people asking about nat problems, so if you find something wrong on my english translation please fix that.
Nat is something that need some work to understand how to use with opensips, is different from what we know on asterisk where you just need to set nat=yes and everything work fine.
I will not show how to install opensips or rtpproxy because we have other howto's here that show this, i will just show the opensips.cfg route script with a simple configuration to accept register and relay the call from a user to another over nat.
The script does not need any user created on opensips, any authentication will be accepted and if you do a restart on opensips you need to register the account again because the location information is just on the memory.
There is a lot of ways to make this, using variables and other functions, this way is simple, is for understand, you can your own implementation as you want.
opensips.cfg
################################### # This script have only the purpose of show you # how configure opensips to work over a nat network # # # YOU SHOULD CHANGE THIS: ___IP_DO_OPENSIPS_AQUI___ # TO THE IP ADDRESS FROM YOUR SERVER ################################### ####### Parametros Globais ######### debug=3 log_stderror=no log_facility=LOG_LOCAL0 fork=yes children=4 /* uncomment the lins below to increase the debug level */ #debug=6 #fork=no #log_stderror=yes auto_aliases=no # Ip address where opensips will run listen=udp:___IP_DO_OPENSIPS_AQUI___:5060 # disable support for sip over tcp disable_tcp=yes # disable tls support disable_tls=yes ####### Modules Section ######## # Opensips module directory mpath="/usr//lib64/opensips/modules/" #### signialing module loadmodule "signaling.so" #### stateless module loadmodule "sl.so" #### transaction module loadmodule "tm.so" modparam("tm", "fr_timer", 5) modparam("tm", "fr_inv_timer", 30) modparam("tm", "restart_fr_on_each_reply", 0) modparam("tm", "onreply_avp_mode", 1) #### record route module loadmodule "rr.so" modparam("rr", "append_fromtag", 0) #### max forward module loadmodule "maxfwd.so" #### sip message 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" #### nathelper module loadmodule "nathelper.so" modparam("nathelper", "natping_interval", 10) modparam("nathelper", "natping_socket", "___IP_DO_OPENSIPS_AQUI___:5060") modparam("nathelper", "received_avp", "$avp(42)") #modparam("nathelper", "sipping_bflag", "SIP_PING_FLAG") modparam("nathelper", "sipping_from", "sip:pinger@___IP_DO_OPENSIPS_AQUI___") modparam("nathelper", "sipping_method", "OPTIONS") #### Modulo rtpproxy (forcar o audio atraves do opensips) loadmodule "rtpproxy.so" modparam("rtpproxy", "rtpproxy_sock", "udp:localhost:7890") ####### routing logic ######## route{ 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 if (loose_route()) { xlog("We are on has_totag - loose_route"); if (is_method("INVITE")) { record_route(); } route(relay); } else { if ( is_method("ACK") ) { if ( t_check_trans() ) { t_relay(); exit; } else { xlog("We are on has_totag, our method is not ACK [ $rm ] "); # ACK without matching transaction -> # ignore and discard exit; } } 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") ) ) { if (from_uri==myself) { } else { # if caller is not local, then called number must be local if (!uri==myself) { send_reply("403","Rely 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(); # If we are not the final destination the call is # to a external destination if (!uri==myself) { append_hf("P-hint: outbound\r\n"); route(relay); } # We dont accept publish or subscribe here if (is_method("PUBLISH|SUBSCRIBE")) { sl_send_reply("503", "Service Unavailable"); exit; } if (is_method("REGISTER")) { # we receive a register request # we will execute fix_nated_register nad fix_nated_contact fix_nated_register(); fix_nated_contact(); if (!save("location")) sl_reply_error(); exit; } if ($rU==NULL) { #requisicao com endereco incompleto sl_send_reply("484","Address Incomplete"); exit; } # do lookup with method filtering if (!lookup("location","m")) { t_newtran(); t_reply("404", "Not Found"); exit; } route(relay); } route[relay] { # check if this request is a invite if (is_method("INVITE")) { # for each branch we will call the function below t_on_branch("per_branch_ops"); # for each reply we will call the function below t_on_reply("handle_nat"); # if the call was not completed, so failure route t_on_failure("missed_call"); # lets try to identify if the user is behind a nat # you can check the mean of 127 on # http://www.opensips.org/html/docs/modules/1.9.x/nathelper.html#id292854 # 127 = 1111111 (activate all check) if(nat_uac_test("127")){ # user identified as behing a nat xlog("we are on route relay, user behind nat"); fix_nated_contact(); } # if we have an application/sdp on our body, so we execute # the rtpproxy_offer if(has_body("application/sdp")){ xlog("we have sdp on this $rm"); rtpproxy_offer(); } } # removing the rtpproxy session if(is_method("CANCEL|BYE")){ unforce_rtp_proxy(); } if (!t_relay()) { send_reply("500","Internal Error"); }; exit; } branch_route[per_branch_ops] { xlog("new branch at $ru\n"); } onreply_route[handle_nat] { xlog("incoming reply\n"); # we receive a reply, we need to check about application/sdp # on our body, if we have, we answer that if(is_method("ACK") && has_body("application/sdp")){ rtpproxy_answer(); }else if(has_body("application/sdp")){ # offering rtpproxy on a non ack message rtpproxy_offer(); } # here we try to identify if the user is behind a nat again # but now is the second user (the called user) if(nat_uac_test("127")){ xlog("we are on nat handle , user behind nat, fixing contact"); fix_nated_contact(); } } failure_route[missed_call] { if (t_was_cancelled()) { exit; } }
Is this, i hope that this sample can make you understand how to implement the nat on opensips