[OpenSIPS-Users] Pass calls to another realm via gateway

Alexander goal81 at gmail.com
Thu Oct 1 20:33:30 CEST 2009


  Hello all!

  I've encountered one problem I can not solve :( The situation is following:
we've  got  Opensips working together with our own SIP platform. Our platform is
about  various  call  processing  business logic and billing. All calls from SIP
users  should  pass  through  our platform. For now we successfully can make and
receive  calls  inside  our  domain - NAT is handled fine in most cases, instant
messages are handled and so on. It looks like that:
  - Opensips receives a call from caller
  - Call is redirected to our platform
  - Platform redirects call back to Opensips and Opensips looks for callee.

  This  works  fine  when both caller and callee are inside our domain. But when
callee  is  in  another  domain, I can't make Opensips pass the call through our
platform  correctly. Caller and callee can't see each other's ACKs and so on, if
I  use  rewritehostport()  or  something.  But if I bypass our platform (!uri ==
myself) - everything is fine.

  What I need (in addition to written above):
  - Opensips receives a call to another domain ('!uri == myself' branch)
  - This call is redirected to our platform
  - Platform redirects this  call  back  to Opensips and Opensips starts to call
    to outside domain.

  What  should  I  change  and/or add to my configuration file? For now it looks
like this:

 --------------------------------------------------------------------------------

 # ----------- Global configuration parameters ------------------------

debug        = 2
fork         = yes
log_stderror = no
log_facility = LOG_DAEMON
log_name     = "opensips"

check_via     = no     # (cmd. line: -v)
dns           = no     # (cmd. line: -r)
rev_dns       = no     # (cmd. line: -R)
children      = 4

server_header = "Server: Our SIP Proxy"

# Listen on both network interfaces
listen        = udp:1.2.3.4:5060
listen        = udp:192.168.2.1:5060

# Aliases for SIP realm
alias         = sip.our_domain.ru
alias         = sip.our_domain.ru
alias         = our_domain.ru
alias         = our_domain.ru

# Path to modules
mpath         = "/usr/local/lib/opensips/modules/"

# ------------------- Load modules  ----------------------------------

loadmodule "signaling.so"
loadmodule "uri_db.so"
loadmodule "db_postgres.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "dialog.so"
loadmodule "nathelper.so"
loadmodule "nat_traversal.so"
loadmodule "auth.so"
loadmodule "auth_db.so"
loadmodule "xlog.so"
loadmodule "presence.so"
loadmodule "presence_mwi.so"
loadmodule "presence_xml.so"
loadmodule "msilo.so"
loadmodule "mi_fifo.so"


# ------------------- Set module-specific parameters -----------------

# DB authorization params
# -----------------------
modparam("auth_db", "db_url",           "postgres://user:password@db/work")
modparam("auth_db", "user_column",      "fsep_id")
modparam("auth_db", "password_column",  "fspassword")
modparam("auth_db", "load_credentials", "fsep_id")
modparam("auth_db", "calculate_ha1",    yes)

# usrloc params
# -------------
modparam("usrloc", "db_mode",   0)
modparam("usrloc", "nat_bflag", 6)

# registrar params (nathelper also uses "received_avp")
# -----------------------------------------------------
modparam("registrar|nathelper", "received_avp", "$avp(i:42)")

# rr params
# ---------
modparam("rr", "enable_full_lr", 1)

# dialog params
# -------------
modparam("dialog", "dlg_flag", 4)

# nathelper
# ---------
modparam("nathelper", "rtpproxy_sock",    "udp:127.0.0.1:7877")
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only",  1)
modparam("nathelper", "sipping_bflag",    7)
modparam("nathelper", "sipping_from",     "sip:pinger at sip.our_domain.ru")

# nat_traversal params
# --------------------
modparam("nat_traversal", "keepalive_interval",   30)
modparam("nat_traversal", "keepalive_method",     "NOTIFY")
modparam("nat_traversal", "keepalive_state_file", "/var/run/opensips/keepalive_state")

# presense params
# ---------------
modparam("presence", "db_url",         "postgres://opensips:password@db/opensips")
modparam("presence", "server_address", "sip:1.2.3.4:5060")

# presense_xml params
# -------------------
modparam("presence_xml", "db_url",       "postgres://opensips:password@db/opensips")
modparam("presence_xml", "force_active", 1)

# uri db params
# -------------
modparam("uri_db", "use_uri_table", 0)
modparam("uri_db", "db_url",        "")

# MSILO params
# ------------
modparam("msilo", "db_url",           "postgres://opensips:password@db/opensips")
modparam("msilo", "content_type_hdr", "Content-Type: text/plain\r\n")
modparam("msilo", "offline_message",  "*** User $rU is offline! ***")

# mi_fifo params
# --------------
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("mi_fifo", "fifo_mode", 0666)


# Main routing logic.
# -------------------
route
{
    if (!mf_process_maxfwd_header("30"))
    {
        xlog("L_ERR", "Too many hops: method <$rm>, from-header <$fu>\n");
        sl_send_reply("483","Too Many Hops");
        exit;
    };

    if (msg:len >=  2048)
    {
        sl_send_reply("513", "Message too big");
        exit;
    };

    # NAT detection
    # -------------
    route(2);

    if (!method == "REGISTER")
        record_route();

    # loose_route() returns true if route headers are present.
    # It also removes any route header entries that match OpenSips own address(es).
    # -----------------------------------------------------------------------------
    if (loose_route())
    {
        append_hf("P-hint: rr-enforced\r\n"); 
        route(1);
    };

    # Outgoing messages processing.
    # -----------------------------
    if (!uri == myself)
    {
        append_hf("P-hint: outbound\r\n"); 
        
        route(1);
    };

    # Incoming messages processing.
    # -----------------------------
    if (uri == myself)
    {
        if (method == "REGISTER")
        {
            # Perform authorization.
            # ----------------------
            if (!www_authorize("", "auth_table"))
            {
                www_challenge("", "0");
                exit;
            };
                        
            if (isflagset(5))
            {
                setbflag(6);

                # If you want OPTIONS natpings uncomment next
                # setbflag(7);
            };

            # Remove authorized credentials from the message.
            # This ensures that the proxy will not reveal information about credentials
            # used to downstream elements and also makes the message a little bit shorter.
            # ----------------------------------------------------------------------------
            consume_credentials();

            # Remember user.
            # --------------
            save("location");
            
            # Now user is online, try to deliver all undelivered messages
            # (sent when user was offline).
            # -----------------------------------------------------------
            m_dump("$fu");
            
            exit;
        }
        else if (is_method("INVITE"))
        {
            # Calls from every IP (except of our platform's one) go to our platform.
            # ----------------------------------------------------------------------
            if ((uri =~ "sip:*@*") && ($si != "1.2.3.5"))
            {
                xlog("L_INFO", "DBG [$Tf] Trying to authorize caller\n");

              # Perform authorization. Accept calls from RED5 server without authorization.
              # RED5's IP address is specified manually. "From" domain is checked manually - if
              # it's not "sip.our_domain.ru" or "our_domain.ru" - the call belongs to other subnet.

                # -------------------------------------------------------------------------------
                if ($si != "192.168.2.2" && ($fd == "sip.our_domain.ru" || $fd == "our_domain.ru" || $fd == "1.2.3.4" || $fd == "1.2.3.4:5060"))
                {
                    xlog("L_INFO", "Attempt to authorize caller $fu\n");
        
                    if (!proxy_authorize("", "auth_table"))
                    {
                        proxy_challenge("", "0");
                        return(0);
                    }
                    else if (!check_from())
                    {
                        sl_send_reply("403", "Use From ID");
                        return(0);
                    };
            
                    consume_credentials();
                }
                else
                {
                    xlog("L_INFO", "Accept trusted call from $fu\n");
                    
                    xlog("L_INFO", "Accepting INVITE from trusted $si without authorization\n");
                }
            
                log("Redirecting call to our platform\n");
                rewritehostport("1.2.3.5:5061");
                route(1);
                return(0);
            }
        }
        else if (is_method("BYE|CANCEL"))
        {
            route(1);
            return(0);
        }
        else if (method == "OPTIONS")
        {
            sl_send_reply("200", "Got it");
            return(0);
        }
        else if (method == "PING")
        {
            sl_send_reply("200", "OK Alive");
            return(0);
        }
        else if (method == "SUBSCRIBE" || method == "PUBLISH" || method == "NOTIFY")
          {
            route(4);
            return(0);
        }

        # Try to find user in usrloc.
        # ---------------------------
        if (!lookup("location"))
        {
            if (!t_newtran())
          {
              sl_reply_error();
              exit;
          };
            
          # User not found.
          # Instant messages should be stored in database, in other case we respond
          # with 404 and exit.
          # -----------------------------------------------------------------------
            if (!method == "MESSAGE")
          {                                                                 
                sl_send_reply("404", "Not Found");
                exit;
            }
            
            log("MESSAGE received -> storing using MSILO\n");
            
            # Store instant message in database.
            # ----------------------------------
            if (m_store("$ru"))
          {
              log("MSILO: offline message stored\n");

              if (!t_reply("202", "Accepted")) 
              {
                  sl_reply_error();
              };
          }
          else
          {
              log("MSILO: offline message NOT stored\n");
        
            if (!t_reply("503", "Service Unavailable")) 
            {
                sl_reply_error();
            };
          };
            
          exit;
        };
        
        # If the downstream UA does not support MESSAGE requests,
        # we can handle it with failure_route[1].
        t_on_failure("1");

        append_hf("P-hint: usrloc applied\r\n"); 
    };

    route(1);
}

# Default Message Handling.
# -------------------------
route[1]
{
    if (subst_uri('/(sip:.*);nat=yes/\1/'))
    {
        setbflag(6);
    };

    if (isflagset(5) || isbflagset(6))
    {
        route(3);
    }

    if (!t_relay())
    {
        sl_reply_error();
    };
    
    exit;
}

# Check for NAT. If needed, fix NATed headers.
# --------------------------------------------
route[2]
{
    force_rport();
    
    if (nat_uac_test("19"))
    {
        if (method == "REGISTER")
        {
            fix_nated_register();
            nat_keepalive();
        }
        else
        {
            fix_nated_contact();
            
            if (method == "INVITE")
            {
                 fix_nated_sdp("1");
            }
        };

        setflag(5);
    };
}

# Process INVITE and BYE/CANCEL events.
# Turns RTP proxy on/off.
# -------------------------------------
route[3]
{
    if (is_method("BYE|CANCEL"))
    {
        unforce_rtp_proxy();
    }
    else if (is_method("INVITE"))
    {
        force_rtp_proxy();
    }

    if (isflagset(5))
        search_append('Contact:.*sip:[^>[:cntrl:]]*', ';nat=yes');

    t_on_reply("1");
}

# SUBSCRIBE and PUBLISH Message Handling
# --------------------------------------
route[4]
{
    if (!t_newtran())
    {
        xlog("L_INFO", "Failed to create transaction\n");
        sl_reply_error();
        exit;
    }
    
    if (is_method("PUBLISH"))
    {
        xlog("L_INFO", "Route 5 - PUBLISH \n");
        handle_publish();
    }  
    else if (is_method("SUBSCRIBE"))
    {
        xlog("L_INFO", "Route 5 - SUBSCRIBE\n");
        handle_subscribe();
    }
    else if (is_method("NOTIFY"))
    {
        xlog("L_INFO", "Route 5 - NOTIFY\n");
        t_reply("200", "OK");
        exit;           
    }
    
    exit; 
}

# Failed transaction routing block. Contains actions for transanctions
# that received negative replies (>= 300).
# --------------------------------------------------------------------
failure_route[1]
{
    if (is_method("MESSAGE"))
    {
        log("MSILO: the downstream UA doesn't support MESSAGEs\n");
        
        # $ou is used because we have changed the R-URI with the contact address
        if (m_store("$ou"))
        {
            log("MSILO: offline message stored\n");
            t_reply("202", "Accepted"); 
        }
        else
        {
            log("MSILO: offline message NOT stored\n");
            t_reply("503", "Service Unavailable");
        };                                                
    }

    if (isbflagset(6) || isflagset(5))
    {
        unforce_rtp_proxy();
    }
}

# Reply routing block. Contains actions to be taken for SIP replies. 
# ------------------------------------------------------------------
onreply_route[1]
{
    # 180 - Ringing, 183 - Progress
    if ((isflagset(5) || isbflagset(6)) && status=~"(180)|(183)|(2[0-9][0-9])")
    {
        if (!search("^Content-Length:[ ]*0"))
        {
            force_rtp_proxy();
        }
    }
    
    search_append('Contact:.*sip:[^>[:cntrl:]]*', ';nat=yes');

    if (isbflagset(6))
    {
        fix_nated_contact();
    }
}



-- 
Sincerely,
 Alexander                          mailto:goal81 at gmail.com




More information about the Users mailing list