[Devel] [Users] nathelper/rtpproxy when both SIP UA are behind same NAT

Norman Brandinger norm at goes.com
Thu Dec 8 04:07:17 CET 2005


Hi Rafael,

You would use the "example code snippet" when you want to decide whether 
or not to use rtpproxy or mediaproxy based on the fact that both the 
caller and the callee are behind the same NAT device.  Please review the 
mailing lists as this topic has been discussed many times.

I added some additional comments in regard to the setting of flags 2 and 
3 in the posted example at: 
http://openser.org/dokuwiki/doku.php?id=avp_examples

Generally, I have found that if OpenSER fails to start with an error 
indicating that the function can't be found, it's time to find the 
correct module to add.

In response to your last question "etc." I suggest that you review the 
three web sites: openser.org, iptel.org and onsip.org.  The last one has 
some really great material that explains alot.

Regards,
Norm


Rafael R. GV wrote:
> Hi
> I am using nathelper/rtpproxy in ser , please see my ser.cfg attached 
> and tell me where do I have to use this code snippet?  where did you 
> set flags 2 and 3?, what other modules I need?, etc.
>
> thank you
> Rafael
> Lima-Peru
>
> On 12/7/05, *Norman Brandinger* <norm at goes.com <mailto:norm at goes.com>> 
> wrote:
>
>     Thanks go out to Klaus and Tavis.
>
>     I took the results of this thread and placed it in the docuwiki
>     for the
>     rest of the user community to use (at least, the rest of the user
>     community that reads the docuwiki :)
>
>     http://openser.org/dokuwiki/doku.php?id=avp_examples
>
>     If I made any typos, please feel free to correct them.
>
>     Regards,
>     Norm
>
>     _______________________________________________
>     Users mailing list
>     Users at openser.org <mailto:Users at openser.org>
>     http://openser.org/cgi-bin/mailman/listinfo/users
>     <http://openser.org/cgi-bin/mailman/listinfo/users>
>
>
> ------------------------------------------------------------------------
>
> #  
> #  If you don't want to enforce RTP proxy for some destinations 
> #  then simply use t_relay() instead of route(1)
> # 
> # Modificado para MYSQL_ACC support
> # Handling of Unavailable user and Voicemail redirection (404|408|486)
> # 
> # Log Missed Calls (403|404|408|415|484|486|487).
> #
> # Group checking and PSTN credentials.
> #
> # 18/07/2005 Prepaid & B2bua support added
> # 11/11/2005 LDI a 192.168.2.132 with a2billing
> #
> # Pendientes !! - Administrar Multi-Dominio para otros Códigos de Area.
> #               - Completar Logica para tratamiento de llamadas entre 
> #                 un mismo NAT usando avpops.
> # 
> # ----------- global configuration parameters ------------------------
>
> #/* Uncomment these lines to enter debugging mode
> debug=2
> fork=yes
> log_stderror=yes
> #*/
>
> listen=192.168.2.130
> listen=127.0.0.1
> port=5060
>
> # hostname matching an alias will satisfy the condition uri==myself".
> alias=mydomain.com.pe
> alias=127.0.0.1
>
> check_via=no    # (cmd. line: -v)
> dns=no          # (cmd. line: -r)
> rev_dns=no      # (cmd. line: -R)
> children=4
> fifo="/tmp/ser_fifo"
> fifo_mode=0666  # Fifo permissions can be changes from here.
>
> # sip_warning - Should replies include extensive warnings? 
> # By default yes, it is good for trouble-shooting.
> sip_warning=yes
>
> # ------------------ module loading ----------------------------------
> loadmodule "/usr/local/lib/ser/modules/domain.so"
> loadmodule "/usr/local/lib/ser/modules/avpops.so"
> loadmodule "/usr/local/lib/ser/modules/mysql.so"
> loadmodule "/usr/local/lib/ser/modules/sl.so"
> loadmodule "/usr/local/lib/ser/modules/tm.so"
> loadmodule "/usr/local/lib/ser/modules/rr.so"
> loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
> loadmodule "/usr/local/lib/ser/modules/usrloc.so"
> loadmodule "/usr/local/lib/ser/modules/registrar.so"
> loadmodule "/usr/local/lib/ser/modules/group.so"
> loadmodule "/usr/local/lib/ser/modules/uri.so"
> loadmodule "/usr/local/lib/ser/modules/uri_db.so" 
> loadmodule "/usr/local/lib/ser/modules/acc.so"
> loadmodule "/usr/local/lib/ser/modules/textops.so"
>
> # digest authentication
> loadmodule "/usr/local/lib/ser/modules/auth.so"
> loadmodule "/usr/local/lib/ser/modules/auth_db.so"
>
> # !! Nathelper
> loadmodule "/usr/local/lib/ser/modules/nathelper.so"
>
> # ----------------- setting module-specific parameters ---------------
>
> modparam("usrloc", "db_mode", 2)
>
> # minimize write back window - default is 60 seconds
> modparam("usrloc", "timer_interval", 10)
>
> # database location
> modparam("usrloc", "db_url", "mysql://ser:heslo@localhost/ser")
>
> modparam("usrloc", "use_domain", 1)
> modparam("auth_db", "use_domain", 1)
>
>
> modparam("domain", "db_mode", 1)
> modparam("domain", "domain_table", "domain")
> modparam("domain", "domain_col", "domain")
>
>
> # ------------- Mysql Accounting parameters
> modparam("acc", "log_flag", 1)
> modparam("acc", "log_level", 2)
> modparam("acc", "db_flag", 1)
> modparam("acc", "db_missed_flag", 3)
> modparam("acc", "log_missed_flag", 3)
> modparam("acc", "db_url", "mysql://seradmin:heslo@localhost/ser")
> modparam("acc", "report_ack", 0) # 1 reporta dos starts en acc (para INVITE y ACK)
> modparam("acc", "failed_transactions", 1) # *all* non-200 transactions marked for acc will be logged too.
>
> modparam("acc", "log_fmt", "miocfsputdr")
>
> modparam("tm", "fr_timer", 20 )
> modparam("tm", "fr_inv_timer", 40 ) # Timer which hits if no final reply for an INVITE
> modparam("tm", "wt_timer", 20 )
>
> # add value to ;lr param to make some broken UAs happy
> modparam("rr", "enable_full_lr", 1)
>
> modparam("group", "db_url", "mysql://seradmin:heslo@localhost/ser")
> modparam("uri_db", "db_url", "mysql://seradmin:heslo@localhost/ser")
>
> # ------------- registration parameters
> modparam("registrar", "nat_flag", 6)
> modparam("registrar", "min_expires", 60)
> modparam("registrar", "max_expires", 86400)
> modparam("registrar", "default_expires", 3600)
> modparam("registrar", "desc_time_order", 1)
> modparam("registrar", "append_branches", 1)
>
> modparam("registrar", "use_domain", 1)
>
> # !! Nathelper
> # modparam("registrar", "nat_flag", 6)
> modparam("nathelper", "natping_interval", 30) # Ping interval 30 s
> modparam("nathelper", "ping_nated_only", 1)   # Ping only clients behind NAT
>
> # -------------------------- request routing logic --------------------------
>
> route {
>
>         log(1, "-------------------------------------------\n");
>         log(1, "entering main loop\n");
>
>
>         # initial sanity checks -- messages with
>         # max_forwards==0, or excessively long requests
>         if (!mf_process_maxfwd_header("10")) {
>                 sl_send_reply("483","Too Many Hops");
>                 break;
>         };
>         if ( msg:len >= max_len ) {
>                 sl_send_reply("513", "Message too big");
>                 break;
>         };
>
>         # !! Nathelper
>         # Special handling for NATed clients; first, NAT test is
>         # executed: it looks for via!=received and RFC1918 addresses
>         # in Contact (may fail if line-folding is used); also,
>         # the received test should, if completed, should check all
>         # vias for rpesence of received
>         if (nat_uac_test("19")) {
>                 # Allow RR-ed requests, as these may indicate that
>                 # a NAT-enabled proxy takes care of it; unless it is
>                 # a REGISTER
>
>                 if (method == "REGISTER" || ! search("^Record-Route:")) {
>                     log("LOG: Someone trying to register from private IP, rewriting\n");
>
>                     # This will work only for user agents that support symmetric
>                     # communication. We tested quite many of them and majority is
>                     # smart enough to be symmetric. In some phones it takes a configuration
>                     # option. With Cisco 7960, it is called NAT_Enable=Yes, with kphone it is
>                     # called "symmetric media" and "symmetric signalling".
>
>                     fix_nated_contact(); # Rewrite contact with source IP of signalling
>                     if (method == "INVITE") {
>                         fix_nated_sdp("1"); # Add direction=active to SDP
>                     };
>                     force_rport(); # Add rport parameter to topmost Via
>                     setflag(6);    # Mark as NATed
>                 };
>         };
>
>
>        # set flag for Radius Accounting:
>
>
>         if (!method=="OPTIONS") setflag(3);  # SET MISSED_CALLS FLAG FOR ACC
>
>         if (method=="INVITE") {
>                 log(1, "INVITE MESSAGE RECEIVED - START ACC\n");
>                 setflag(1); /* set for accounting (the same value as in log_flag!) */
>         };
>
>         if (method=="BYE") {
>                 log (1, "BYE  - STOP ACCOUNTING\n");
>                 setflag(1);
>         };
>
>         if (method=="CANCEL") {
>                 log (1, "CANCEL - STOP ACCOUNTING\n");
>                 setflag(1);
>         };
>
>
>         # record-route all messages -- to make sure that
>         # subsequent messages will go through our proxy; that's
>         # particularly good if upstream and downstream entities
>         # use different transport protocol
>
>         if (!method=="REGISTER") record_route();
>
>         # subsequent messages withing a dialog should take the
>         # path determined by record-routing
>         # Excluding packets from b2bua (port 5070) 
>         if (loose_route() ) {
>                 log(1," Mark routing logic in request --> rr-enforced \n");
>                 append_hf("P-hint: rr-enforced\r\n"); 
>                 # t_relay();
>                 route(1);  # Nathelper!!
>                 break;
>         };
>
>         if (!uri==myself ) {
>                 log(1," Mark routing logic in request --> outbound\r \n");
>                 append_hf("P-hint: outbound\r\n"); 
>                 # t_relay();
>                 route(1); # Nathelper!!
>                 break;
>         };
>
>         if (uri==myself) {
>
>                 if (method == "REGISTER") {
>
>                         log(1, "ANALYZING REGISTER REQUEST\n");
>                         # to use digest authentication
>                         if (is_user_in("Request-URI", "desactivado")) {
>                                 sl_send_reply("402", "Su cuenta fue desactivada");
>                                 break;
>                         };
>
>                         if (!www_authorize("mydomain.com.pe", "subscriber")) {
>                                 log(1,"       ----- Fails to Register \n");
>                                 www_challenge("mydomain.com.pe", "0");
>                                 break;
>                         };
>
>                         # only signed users are allowed 
>                         if (!check_to()) {
>                                 log(1, "LOG: Hijack!!!--> unsigned user registration attempt\n");
>                                 sl_send_reply("403", "hijack attempt!!!! Only signed users are allowed");
>                                 break;
>                         };
>                         log(1,"      Registered!!! \n");
>                         if (!save("location")) {
>                                 sl_reply_error();
>                         };
>                         break;
>                 };
>
>
>         #For *B2bua: First check the source of the call
>         #**********************************************
>         # If the call comes from the gateways, no authentication is required.
>         if (src_ip==192.168.2.145 || src_ip==192.168.2.132 || src_ip==192.168.2.131) {
>                 log(1,"Call from pstn|*, no authentication is required. \n");
>
>         # If the call comes from B2BUA, no authentication is required, 
>         # The first leg of the call has already been authenticated.
>         } else if (src_ip==192.168.2.130 && src_port==5070) {
>                 log(1,"Call from B2BUA, no authentication is required.  \n");
>         } else { 
>                 # We check user credentials
>                 if ((method == "INVITE" || method== "CANCEL" || method== "BYE" || method== "ACK") && (!src_ip==192.168.2.130 && !src_port==5070)){
>                 log(1, "ANALYZING INVITE||CANCEL REQUESTs\n");
>                         if (!proxy_authorize("mydomain.com.pe", "subscriber")) {
>                                 # log(1,"   ----- Fails to ...proxy_authorize \n");
>                                 proxy_challenge("mydomain.com.pe", "0");
>                                 break;
>                         } else {
>                         if (method == "INVITE" && !check_from()) {
>                                 sl_send_reply("403", "Only registered users are allowed"); 
>                                 log(1," ----> Only registered users are allowed \n");
>                                 break;
>                         };
>                         };
>
>                 # Not all the users are PREPAID, so we check the database
>                 # to see if the call will be routed through B2BUA.
>                 # If every call is to be routed through B2BUA the "is_user_in"
>                 # conditional is not required.
>                 # Do not use b2bua for local calls
>
>                         if (is_user_in("From", "prepaidb") && uri=~"^sip:00") {
>                                 log(1," ----> Usuario PREPAGO!!! enviando a b2bua... \n");
>                                 rewritehostport("192.168.2.130:5070");
>                                 t_relay_to_udp("192.168.2.130", "5070");
>                                 break;
>                         };
>
>                 };# End of if (method == "INVITE" |...
>         };
>
>
>         /* *********** Dial out to Local and PSTN logic ********* */           
>
>
>         # Forward +9n digit requests to gateway Cisco-AS5350 (Celulares):
>
>                 if(uri=~"^sip:9" ){
>                         log(1," digit expression match - Celulares \n");
>                         if (!is_user_in("from", "movlim")) {
>                         sl_send_reply("403", "No permission for mobile calls");
>                         acc_db_request("403 Forbidden", "missed_calls");
>                         break;
>                 }; 
>                 rewritehostport("192.168.2.145:5060");
>                 route(1);
>                 break;
>                 };
>
>
>         /* ******************************************************************** */   
>
>                 lookup("aliases");
>                 
>
>                 # does the user wish redirection on no availability? (i.e., is he
>                 # in the voicemail group?) -- determine it now and store it in
>                 # flag 4, before we rewrite the flag using UsrLoc
>
>                 if (is_user_in("Request-URI", "voicemail")) {
>                         log(1, "requested user is in voicemail group \n");
>                         setflag(4);
>                 };
>
>                 
> 		# native SIP destinations are handled using our USRLOC DB:
>
>                 # LOOKUP (location)!!!!
>
> 		if (!lookup("location")) {
>                         log(1,"unable to locate user X ... sending to route(4)! \n");
>                         # handle user which was not found
>                         route(4);
>                         break;
>                 };
>
>             ### Test if UAS are in the same NAT:
>
>                 # get the host part of the final uri (IP part) and store it in AVP ID 13
>
>                 avp_write("$ruri/domain", "i:13");
>                 if (avp_check("i:13","eq/$src_ip/i")) {
>                         log(1, "source IP is the same as destination IP\n");
>                         route(3);
>                         break;
>                 };
>                 avp_delete("i:13/g");
>
>         
>         }; # End of "if(uri==myself)"
>
>
>         append_hf("P-hint: usrloc applied\r\n"); 
>         route(1);
>
>         # if user is on-line and is in Voicemail group, enable redirection
>         if (method == "INVITE" && isflagset(4)) {
>                 log(1, "invite for voicemail user->initiate failureroute[1]\n");
>                 t_on_failure("1");
>         };
> }
>
> ### ##### ####### ########## - ROUTES - ############### ################# ##################
>
> route[1] 
> {
>
>         # if client or server know to be behind a NAT, enable relay
>         if (isflagset(6)) {
>                 log(1, "Route1: force rtp proxy!!!\n");
>             force_rtp_proxy();
>         };
>
>         # NAT processing of replies; apply to all transactions (for example,
>         # re-INVITEs from public to private UA are hard to identify as
>         # NATed at the moment of request processing); look at replies
>         t_on_reply("1");
>
>         # send it out now; use stateful forwarding as it works reliably
>         # even for UDP2TCP
>         if (!t_relay()) {
>                 sl_reply_error();
>         };
>         log(1, "Route[1]: Send it out now!!!\n");
>         break;
> }
>
> # !! Nathelper
> onreply_route[1] {
>         # NATed transaction ?
>         # Not all 2xx messages have a content body so here we
>         # make sure our Content-Length > 0 to avoid a parse error
>
>     if (isflagset(6) && status =~ "(183)|2[0-9][0-9]") {
>         fix_nated_contact();
>         if (!search("^Content-Length:\ 0")) {
>         force_rtp_proxy();
>         };
>     # otherwise, is it a transaction behind a NAT and we did not
>     # know at time of request processing ? (RFC1918 contacts)
>     } else if (nat_uac_test("1")) {
>         fix_nated_contact();
>     };
> }
>
> # -------------- SIP-to-PSTN call routed ---------------------
>
> route[2]{       
>         log(1,"route[2]:SIP-to-GW call routed \n");
>         if(!t_relay()){
>                 sl_reply_error();
>         };
>         log(1, "Route[2]: Send it out now!!!\n");
> }
>
> # -------------- Same NAT Call Routing (no force rtpproxy) ----
>
> route[3]{
>         log(1," route[3]: UAs are in the same nat, NO force_rtp_proxy ");
>
>         # What do I have to do here?
>
>         if(!t_relay()){
>                 sl_reply_error();
>         };
>         log(1, "Route[3]: Send it out now!!!\n");
> }
>
> # --------------- Handling of Unavailable user ----------------
> route[4] {
>  
>         # non-Voip -- just send "off-line"
>         if (!(method=="INVITE" || method=="ACK" || method=="CANCEL" || method=="BYE" || method=="OPTIONS")) {
>                 sl_send_reply("404", "Not Found");
>                 acc_db_request("404 Not Found", "missed_calls");
>                 log(1, "acc 404 Not Found 1 \n");
>                 break;
>         };
>
>         if (!isflagset(4) && !method=="OPTIONS" && !method=="ACK" && !method=="BYE") { 
>                 sl_send_reply("404", "Not Found and no voicemail turned on !! ");
>                 acc_db_request("404 Not Found", "missed_calls");
>                 log(1, " acc 404 Not Found and no voicemail \n");
>                 break;
>         };
>
>         # forward to voicemail adding prefix to simplify asterisk "extension.conf"
>         prefix("vm");  
>         acc_db_request("404 Not Found -> Vm", "missed_calls");
>         rewritehostport("192.168.2.131:5070");
>         t_relay_to_udp("192.168.2.131", "5070");
> }
>
> # if forwarding downstream did not succeed, try voicemail running at Asterisk 
>
> failure_route[1]{
>         if (t_check_status("408")){
>                 # revert_uri (); back to the original URI, makes me loose all lookup/rewrite stuff
>                 prefix("vm");
>                 rewritehostport ("192.168.2.131:5070");
>                 acc_db_request("408 Timeout   -> Vm", "missed_calls");
>                 append_branch();
>                 t_relay();
>                 break;
>         } else if (t_check_status("486")){
>                 # revert_uri (); back to the original URI, makes me loose all lookup/rewrite stuff
>                 prefix("vm");
>                 rewritehostport ("192.168.2.131:5070");
>                 acc_db_request("486 Busy      -> Vm", "missed_calls");
>                 append_branch();
>                 t_relay();
>                 break;
>         }
> }
>
> ### The End ###





More information about the Users mailing list