[Users] 400 Bad Requests on internal routes behind NAT

Justin Pearce justinp at pricevideo.com
Wed Aug 2 21:46:33 CEST 2006


Hey Guys,

We're trying to use an OpenSER server for some SIP communications. While it works great for most scenarios (Behind NAT, Outside of NAT, One client behind NAT and the other Outside of NAT), there is one that seems to be causing difficulty (naturally, this is the one that is being requested. :\ ). I'm being asked if we can set up the server to not only support the previously mentioned scenarios but also where both clients are behind the same NAT, but no ports are forwarded through the NAT for the clients. Basically, client calls another client on the same network using the off-network server as a registrar (no Mediaproxy or RTPproxy).

Is this even possible with OpenSER (v 1.0.1)? If so, perhaps I'm doing something wrong in my config (pertinent parts attached below). I know this part of the config works for most situations, so long as the clients have ports routed in the firewall/NAT device (minus the use of AVP at the end to try and achieve the desired results). Any help at all would be appreciated.

Justin Pearce

route{
      # Label all transactions for accounting, as per the
      # parameters for the Accounting Module
      setflag(1);
      setflag(2);
      setflag(3);
      setflag(4);

      # 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");
            exit;
      };
      #If the message is too big for SIP
      if (msg:len >=  2048 ) {
            sl_send_reply("513", "Message too big");
            exit;
      };
      # We 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
      if (loose_route()) {
            # mark routing logic in request
            append_hf("P-hint: rr-enforced\r\n"); 
            route(1);
      };

      if (!uri==myself) {
            # mark routing logic in request
            append_hf("P-hint: outbound\r\n"); 
            route(1);
      };

      # if the request is for other domain use UsrLoc
      # (in case, it does not work, use the following command
      # with proper names and addresses in it)
      if (uri==myself) {
                
            if (method=="REGISTER") {
                       fix_nated_register(); # Fix REGISTERs broken by NAT
                   fix_nated_contact();
                   force_rport(); # Force the return port in the firewall
                   add_rcv_param(); # Add the "recieved" parameter to the location
                       save("location"); # Save the location in the registrar
                       acc_db_request("200", "acc"); # Log the 200 OK
                       exit;
            };

            lookup("aliases"); # Check the ALIASES table
            if (!uri==myself) {
                  append_hf("P-hint: outbound alias\r\n"); 
                  route(1);
            };

            # native SIP destinations are handled using our USRLOC DB
            if (!lookup("location")) {
                  # If the user cannot be found, reply to the user
                  # and exit the call process
                  sl_send_reply("404", "Not Found");
                  exit;
            };
            append_hf("P-hint: usrloc applied\r\n"); 
      }else{
      # if the request is for other domain use UsrLoc
      # (in case, it does not work, use the following command
      # with proper names and addresses in it)
            if (method=="REGISTER") {
                  fix_nated_register(); # Fix the REGISTERs broken bt NAT
                  fix_nated_contact();
                  force_rport(); # Force the return port in the firewall
                  add_rcv_param(); # Add the "recieved' parameter to the location
                  save("location"); # Save the location in the registrar
                  acc_db_request("200", "acc"); # Log the 200 OK
                  exit;  
            };
            # native SIP destinations are handled using our USRLOC DB
            if (!lookup("location")) {
                  # If the user cannot be found, notify sender and exit.
                  sl_send_reply("404", "Not Found");
                    exit;     
            };
      };
      # Continue onto route #1 below...
      route(1);
}

route[1] {
      avp_write("$src_ip", "s:temp_from_ip");
      avp_write("$duri", "s:temp_to_ip");
      avp_subst("s:temp_to_ip", "/^\D+@//i");
      if(method=="INVITE" && !(to_uri=~"^admin@[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[:]*[0-9]*")){
          fix_nated_contact();
        force_rport();   
        if(avp_check("s:temp_to_ip", "ne/s:temp_from_ip/g")){
        fix_nated_sdp("15");
        }else{
            append_hf("P-Hint: Same Domain");
        };
        record_route();       
       };
      #This is set of processes to be preformed on all replies...
        #This conditional is to try and redeem ACKs that some how managed to get a private address attached to them.
        #This is basically a hack to try and "normalize" the packets coming through and pray they work.
   if(method=="ACK" || method=="BYE" || method=="INFO"){
 if(uri=~"^sip:192\.168\.[0-9]+\.[0-9]+[:]*[0-9]*" || uri=~"^sip:10\.[0-9]+\.[0-9]+\.[0-9]+[:]*[0-9]*" || uri=~"^sip:172\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)\.[0-9]+\.[0-9]+[:]*[0-9]*"){
                #Rewrite the R-URI of the packet to the To-URI in the To header.
                 subst_uri('/^sip:[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[:]*[0-9]*$/$tu/ig');
                #Force the server to perform a lookup on the new URI and try and route it properly.
                 lookup("location");
          };
        };

      # send it out now; use stateful forwarding as it works reliably
      # even for UDP2TCP
      if (!t_relay()) {
            # If the stateful relay of a message cannot take place,
            # reply to the sender statelessly with the error.
            sl_reply_error();
      };
      exit;
}

onreply_route{

        if(status=="200" || method=="INVITE"){
      fix_nated_contact();
      force_rport();
      if(!search("P-Hint: Same Domain")){
          fix_nated_sdp("15");
         };
       };
}




More information about the Users mailing list