OPensips(一):NAT例子

一、例子代码

#
# OpenSIPS residential configuration script
#     by OpenSIPS Solutions <team@opensips-solutions.com>
#
# This script was generated via "make menuconfig", from
#   the "Residential" scenario.
# You can enable / disable more features / functionalities by
#   re-generating the scenario with different options.#
#
# Please refer to the Core CookBook at:
#      http://www.opensips.org/Resources/DocsCookbooks
# for a explanation of possible statements, functions and parameters.
#


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

log_level=3
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:172.16.0.118:6080 as xxx.xx.xx.xx:6080
listen=tcp:172.16.0.118:6080 as xxx.xx.xx.xx:6080
listen=tls:172.16.0.118:6081 as xxx.xx.xx.xx:6081

####### 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)
#### offline config
modparam("tm", "fr_timer", 10 )
modparam("tm", "fr_inv_timer", 15 )
modparam("tm", "wt_timer", 10 )

#### 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)


#### MYSQL module
loadmodule "db_mysql.so"

#### HTTPD module
#loadmodule "httpd.so"
#modparam("httpd", "port", 8888)

#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME
#modparam("usrloc", "db_mode",   2)
#### offline config
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)
#### offline config
modparam("registrar", "default_expires", 120)

#### 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)
modparam("acc", "db_url", "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME


#### AUTHentication modules
loadmodule "auth.so"
loadmodule "auth_db.so"
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db|uri", "db_url",    "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME
modparam("auth_db", "load_credentials", "")


#### PRESENCE modules
loadmodule "xcap.so"
loadmodule "presence.so"
loadmodule "presence_xml.so"
modparam("xcap|presence", "db_url",    "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME
modparam("presence_xml", "force_active", 1)
modparam("presence", "server_address", "sip:172.16.0.118:6080") # CUSTOMIZE ME


#### DIALOG module
loadmodule "dialog.so"
modparam("dialog", "dlg_match_mode", 1)
modparam("dialog", "default_timeout", 21600)  # 6 hours timeout
modparam("dialog", "db_mode", 2)
modparam("dialog", "db_url",    "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME


####  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@127.0.0.1") #CUSTOMIZE ME
modparam("nathelper", "received_avp", "$avp(received_nh)")

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


####  DIALPLAN module
loadmodule "dialplan.so"
modparam("dialplan", "db_url",    "mysql://opensips:opensipsrw@localhost/opensips") # CUSTOMIZE ME


####  MI_HTTP module
#loadmodule "mi_http.so"
loadmodule "proto_udp.so"
loadmodule "proto_tcp.so" 
loadmodule "proto_tls.so"

#### tls
loadmodule "tls_mgm.so"
modparam("tls_mgm","verify_cert", "1")
modparam("tls_mgm","require_cert", "0")
modparam("tls_mgm","tls_method", "TLSv1")
modparam("tls_mgm","certificate", "/usr/local/etc/opensips/tls/user/user-cert.pem")
modparam("tls_mgm","private_key", "/usr/local/etc/opensips/tls/user/user-privkey.pem")
modparam("tls_mgm","ca_list", "/usr/local/etc/opensips/tls/user/user-calist.pem")

#### offline config
loadmodule "msilo.so"
#加载msilo模块
modparam("msilo", "db_table", "silo")
#配置离线消息存储的表silo
modparam("msilo", "db_url","mysql://opensips:opensipsrw@localhost/opensips")
#配置数据库路径
modparam("msilo", "add_date", 1)
#配置是否显示[offline message +时间]
modparam("msilo","content_type_hdr","Content-Type: text/plain
")
modparam("msilo","offline_message","*** User $rU is offline!")
modparam("msilo","from_address","sip:registrar@xxx.xx.xx.xx")
modparam("msilo","contact_hdr","Contact: registrar@xxx.xx.xx.xx:6080;msilo=yes
")

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

# main request routing logic

route{
    force_rport();
    if (nat_uac_test("23")) {
        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
        if (loose_route()) {
            
            # validate the sequential request against dialog
            if ( $DLG_status!=NULL && !validate_dialog() ) {
                xlog("In-Dialog $rm from $si (callid=$ci) is not valid according to dialog
");
                ## exit;
            }
            
            if (is_method("BYE")) {
                # do accounting even if the transaction fails
                do_accounting("db","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("SUBSCRIBE") && $rd == "172.16.0.118:6080") { # CUSTOMIZE ME
                # in-dialog subscribe requests
                route(handle_presence);
                exit;
            }
            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;
    }

    # CANCEL processing
    if (is_method("CANCEL"))
    {
        if (t_check_trans())
            t_relay();
        exit;
    }

    t_check_trans();

    /*
    if ( !(is_method("REGISTER")  ) ) {
        
        if (from_uri==myself)
        {            
            # authenticate if from local subscriber
            # authenticate all initial non-REGISTER request that pretend to be
            # generated by local subscriber (domain from FROM URI is local)
            if (!proxy_authorize("", "subscriber")) {
                proxy_challenge("", "0");
                exit;
            }
            if (!db_check_from()) {
                sl_send_reply("403","Forbidden auth ID");
                exit;
            }
        
            consume_credentials();
            # caller authenticated
            
        } 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();

    # account only INVITEs
    if (is_method("INVITE")) {        
        # create dialog with timeout
        if ( !create_dialog("B") ) {
            send_reply("500","Internal Server Error");
            exit;
        }
        
        do_accounting("db");
        
    }

    
    if (!uri==myself) {
        append_hf("P-hint: outbound
"); 
        
        route(relay);
    }

    # requests for my domain
    
    if( is_method("PUBLISH|SUBSCRIBE"))
        route(handle_presence);

    if (is_method("REGISTER"))
    {
        # authenticate the REGISTER requests
        if (!www_authorize("", "subscriber"))
        {
            www_challenge("", "0");
            exit;
        }
        
        if (!db_check_to()) 
        {
            sl_send_reply("403","Forbidden auth ID");
            exit;
        }

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

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

        if (!save("location"))
        {
            sl_reply_error();            
        }
        #增加部分--start
        if (m_dump()){
            log("MSILO:offline message dumped
");
        }else{
            log("MSILO:no offline message dumped
");
        }
        #增加部分--end
        exit;
    }

    if ($rU==NULL) {
        # request with no Username in RURI
        sl_send_reply("484","Address Incomplete");
        exit;
    }
    
    # apply transformations from dialplan table
    dp_translate("0","$rU/$rU");

    # do lookup with method filtering
    if (!lookup("location","m")) {
        if (!db_does_uri_exist()) {
            send_reply("420","Bad Extension");
            exit;
        }
        
        #t_newtran();
        #t_reply("404", "Not Found");
        #exit;
        
        if(!t_newtran()){
            sl_reply_error();
            exit;
        }
        if (!method=="MESSAGE")
        {
            if (!t_reply("404", "Not found")) 
            {
                    sl_reply_error();
               };
            exit;
        };
        log("MSILO:Message received -> storing using MSILO
");
        if (m_store("$ru")){
            log("MSILO:offline message stored
");
            if (!t_reply("202","Accepted")){
                sl_reply_error();
            };
        }else{
            log("MSILO:offline message NOT stroed
");
            if(!t_reply("503","Service Unavailable")){
                sl_reply_error();
            };
        };
        exit;
    } 
    t_on_failure("1");
    if (isbflagset(NAT)) setflag(NAT);

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


route[relay] {
    # for INVITEs enable some additional helper routes
    if (is_method("INVITE")) {
        
        if (isflagset(NAT)) {
            rtpproxy_offer("ro");
        }

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

    if (isflagset(NAT)) {
        add_rr_param(";nat=yes");
    }

    if (!t_relay()) {
        send_reply("500","Internal Error");
    };
    exit;
}


# Presence route
route[handle_presence]
{
    if (!t_newtran())
    {
        sl_reply_error();
        exit;
    }

    if(is_method("PUBLISH"))
    {
        handle_publish();
    }
    else if( is_method("SUBSCRIBE"))
    {
        handle_subscribe();
    }

    exit;
}


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


onreply_route[handle_nat] {
    if (nat_uac_test("1"))
        fix_nated_contact();
    if ( isflagset(NAT) )
        rtpproxy_answer("ro");
    xlog("incoming reply
");
}


failure_route[missed_call] {
    if (t_was_cancelled()) {
        exit;
    }

    # 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;
    ##}

    # forwarding failed -- check if the request was a MESSAGE 
    if (!method=="MESSAGE")
    {
        exit;
    };
    
    log(1,"MSILO:the downstream UA doesn't support MESSAGEs
");
    # we have changed the R-URI with the contact address, ignore it now
    if (m_store("$ou"))
    {
        log("MSILO: offline message stored
");
        t_reply("202", "Accepted"); 
    }else{
        log("MSILO: offline message NOT stored
");
        t_reply("503", "Service Unavailable");
    };
}

failure_route[1] {
    # forwarding failed -- check if the request was a MESSAGE 
    if (!method=="MESSAGE")
    {
        exit;
    };
    
    log(1,"MSILO:the downstream UA doesn't support MESSAGEs
");
    # we have changed the R-URI with the contact address, ignore it now
    if (m_store("$ou"))
    {
        log("MSILO: offline message stored
");
        t_reply("202", "Accepted"); 
    }else{
        log("MSILO: offline message NOT stored
");
        t_reply("503", "Service Unavailable");
    };
}

local_route {
    if (is_method("BYE") && $DLG_dir=="UPSTREAM") {    
        acc_db_request("200 Dialog Timeout", "acc");    
    }
}

 二、例子代码

# ----------- global configuration parameters ------------------------
debug=3
fork=yes
log_facility=LOG_LOCAL0
log_stderror=no
children=4
port=5060
dns=no
rev_dns=no


#advertised_address="xx.xx.xx.xx"
#alias="xx.xx.xx.xx:5060"


# ------------------ module loading ----------------------------------
mpath="/usr/lib/opensips/modules/"
loadmodule "db_mysql.so"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
loadmodule "uri.so"
loadmodule "nathelper.so"
loadmodule "domain.so"


# ----------------- setting module-specific parameters ---------------
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("usrloc", "db_url",
"mysql://opensipsrw:opensipsrw@localhost/opensips")
modparam("usrloc", "db_mode", 2)
modparam("rr", "enable_full_lr", 1)
modparam("nathelper", "rtpproxy_sock", "udp:127.0.0.1:50010")
modparam("nathelper", "nortpproxy_str", "")
modparam("domain", "db_url",
"mysql://opensipsrw:opensipsrw@localhost/opensips")


################## NAT ######################
modparam("usrloc", "nat_bflag", 6)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", 8)
modparam("nathelper", "received_avp", "$avp(i:801)")
################## NAT ######################




# main routing logic
route {


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


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




   ################## NAT ######################
   if (nat_uac_test("3")) {


       if (is_method("REGISTER") && !is_present_hf("Record-Route")) {


           # Rewrite contact with source IP of signalling
           fix_nated_contact();


           force_rport();
           setbflag(6); # Mark as NATed


           # if you want SIP NAT pinging
           setbflag(8);
       };
   };
   ################## NAT ######################


   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
");
       route(1);
   };


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


   if (uri==myself) {
       if (method=="REGISTER") {
           save("location");
           exit;
       };
   }


   if (is_method("BYE"))
       unforce_rtp_proxy();
     if (!lookup("location","m")) {
       switch ($retcode) {
           case -1:
           case -3:
               t_newtran();
               t_on_failure("1");
               t_reply("404", "Not Found");
               exit;
           case -2:
               sl_send_reply("405", "Method Not Allowed");
               exit;
       }
   };


   route(1);
}






route[1] {


   ################## NAT ######################
   if (uri=~"[@:](192.168.10.172.(1[6-9]2[0-9]3[0-1]).)" &&
!search("^Route:")) {
       sl_send_reply("479", "We don't forward to private IP addresses");
       exit;
   };


   # if client or server know to be behind a NAT, enable relay
   if (isbflagset(6)) {
       if (has_body("application/sdp")) {
           rtpproxy_offer("o");
       };
   };


   t_on_reply("1");
   ################## NAT ######################




   # send it out now; use stateful forwarding as it works
   # reliably even for UDP2TCP
   if (!t_relay()) {
       sl_reply_error();
   };


   exit;
}






onreply_route[1] {


   ################## NAT ######################
   if (isbflagset(6) && status =~ "(183)|2[0-9][0-9]") {
       fix_nated_contact();
       if (has_body("application/sdp")) {
           rtpproxy_answer("o");
       };


       # Is this a transaction behind a NAT and we did not
       # know at time of request processing?
   } else if (nat_uac_test("1")) {
       fix_nated_contact();
   };
   ################## NAT ######################

}

failure_route[1] {
   unforce_rtp_proxy();
}

 三、例子三

#
# simple quick-start config script including nathelper support
# This default script includes nathelper support. To make it work
# you will also have to install Maxim's RTP proxy. The proxy is enforced
# if one of the parties is behind a NAT.
#
# If you have an endpoing in the public internet which is known to
# support symmetric RTP (Cisco PSTN gateway or voicemail, for example),
# then you don't have to force RTP proxy. If you don't want to enforce
# RTP proxy for some destinations than simply use t_relay() instead of
# route(1)
#
# Sections marked with !! Nathelper contain modifications for nathelper
#
# NOTE !! This config is EXPERIMENTAL !
#
# ----------- global configuration parameters ------------------------
log_level=3      # logging level (cmd line: -dddddddddd)
log_stderror=no  # (cmd line: -E)
/* Uncomment these lines to enter debugging mode */
#debug_mode=yes
check_via=no    # (cmd. line: -v)
dns=no           # (cmd. line: -r)
rev_dns=no      # (cmd. line: -R)
port=5060
children=4
# ------------------ module loading ----------------------------------
#set module path
mpath="/usr/local/lib/opensips/modules/"
# Uncomment this if you want to use SQL database
#loadmodule "db_mysql.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "signaling.so"
loadmodule "rr.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
# Uncomment this if you want digest authentication
# db_mysql.so must be loaded !
#loadmodule "auth.so"
#loadmodule "auth_db.so"
# !! Nathelper
loadmodule "nathelper.so"
loadmodule "rtpproxy.so"
# ----------------- setting module-specific parameters ---------------
# -- mi_fifo params --
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
# -- usrloc params --
modparam("usrloc", "db_mode",   0)
# Uncomment this if you want to use SQL database 
# for persistent storage and comment the previous line
#modparam("usrloc", "db_mode", 2)
# -- auth params --
# Uncomment if you are using auth module
#modparam("auth_db", "calculate_ha1", yes)
#
# If you set "calculate_ha1" parameter to yes (which true in this config), 
# uncomment also the following parameter)
#modparam("auth_db", "password_column", "password")
# !! Nathelper
modparam("usrloc","nat_bflag",6)
modparam("nathelper","sipping_bflag",8)
modparam("nathelper", "ping_nated_only", 1)   # Ping only clients behind NAT
# -------------------------  request routing logic -------------------
# main routing logic
route{
    # 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 ($ml >=  2048 ) {
        sl_send_reply("513", "Message too big");
        exit;
    };
    # !! 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("3")) {
        # Allow RR-ed requests, as these may indicate that
        # a NAT-enabled proxy takes care of it; unless it is
        # a REGISTER
        if (is_method("REGISTER") || !is_present_hf("Record-Route")) {
            log("LOG:Someone trying to register from private IP, rewriting
");
            # 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".
            # Rewrite contact with source IP of signalling
            fix_nated_contact();
            if ( is_method("INVITE") ) {
                fix_nated_sdp("1"); # Add direction=active to SDP
            };
            force_rport(); # Add rport parameter to topmost Via
            setbflag(6);    # Mark as NATed
            # if you want sip nat pinging
            # setbflag(8);
        };
    };
    # 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
"); 
        route(1);
        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 (!is_method("REGISTER"))
        record_route();
    if (!is_myself("$rd")) {
        # mark routing logic in request
        append_hf("P-hint: outbound
"); 
        route(1);
        exit;
    };
    # 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 (is_myself("$rd")) {
        if (is_method("REGISTER")) {
            # Uncomment this if you want to use digest authentication
            #if (!www_authorize("siphub.org", "subscriber")) {
            #   www_challenge("siphub.org", "0");
            #   return;
            #};
            save("location");
            exit;
        };
        lookup("aliases");
        if (!is_myself("$rd")) {
            append_hf("P-hint: outbound alias
"); 
            route(1);
            exit;
        };
        # native SIP destinations are handled using our USRLOC DB
        if (!lookup("location")) {
            sl_send_reply("404", "Not Found");
            exit;
        };
    };
    append_hf("P-hint: usrloc applied
"); 
    route(1);
}
route[1] 
{
    # !! Nathelper
    if ($ru=~"[@:](192.168.|10.|172.(1[6-9]|2[0-9]|3[0-1]).)" && !search("^Route:")){
        sl_send_reply("479", "We don't forward to private IP addresses");
        exit;
    };
    # if client or server know to be behind a NAT, enable relay
    if (isbflagset(6)) {
        rtpproxy_offer();
    };
    # 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();
    };
}
# !! Nathelper
onreply_route[1] {
    # NATed transaction ?
    if (isbflagset(6) && $rs =~ "(183)|2[0-9][0-9]") {
        fix_nated_contact();
        rtpproxy_answer();
    # 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();
    };
}

 例子4、Load_balance+NAT

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

log_level=3
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=yes


listen=udp:10.101.26.22:5060
listen=tcp:10.101.26.22:5060
listen=ws:10.101.26.22:8090


 

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




#set module path
mpath="/usr/local/opensips-2.2.3/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)


loadmodule "proto_udp.so"
loadmodule "proto_tcp.so"
loadmodule "proto_ws.so"
modparam("proto_ws","ws_port",8080)
modparam("proto_ws","ws_send_timeout",20000) 
 
#### MYSQL module
loadmodule "db_mysql.so"



#### USeR LOCation module
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "db_mode",   2)
modparam("usrloc", "db_url",
    "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME


#### 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)
modparam("acc", "db_url",
    "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME


#### AUTHentication modules
loadmodule "auth.so"
loadmodule "auth_db.so"
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
modparam("auth_db|uri", "db_url",
    "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME
modparam("auth_db", "load_credentials", "")


#### ALIAS module
loadmodule "alias_db.so"
modparam("alias_db", "db_url",
    "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME






#### DIALOG module
loadmodule "dialog.so"
modparam("dialog", "dlg_match_mode", 1)
modparam("dialog", "default_timeout", 21600)  # 6 hours timeout
modparam("dialog", "db_mode", 2)
modparam("dialog", "db_url",
    "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME


####  NAT modules
loadmodule "nathelper.so"
modparam("nathelper", "natping_interval", 10)
modparam("nathelper", "ping_nated_only", 1) 
modparam("nathelper", "received_avp", "$avp(received_nh)")


######################################################################
## Path Module Parameters
######################################################################
loadmodule "path.so"
modparam("path", "use_received", 1)

 
loadmodule "dispatcher.so"
modparam("dispatcher", "ds_ping_method", "OPTIONS") # CUSTOMIZE ME
modparam("dispatcher", "ds_ping_interval", 3) # CUSTOMIZE ME
modparam("dispatcher", "ds_probing_threshhold", 2) # CUSTOMIZE ME
modparam("dispatcher", "ds_probing_mode", 1) # CUSTOMIZE ME
modparam("dispatcher", "db_url", "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME

loadmodule "load_balancer.so"
modparam("load_balancer", "db_url", "mysql://root:123456789@127.0.0.1/opensips") # CUSTOMIZE ME
modparam("load_balancer", "probing_method", "OPTIONS")
modparam("load_balancer", "probing_interval", 3)
#modparam("load_balancer", "fetch_freeswitch_stats", 1)
#modparam("load_balancer", "initial_freeswitch_load", 1000)


#loadmodule "rtpproxy.so"
#modparam("rtpproxy", "rtpproxy_sock",  "udp:10.7.10.67:7890") # CUSTOMIZE ME


#loadmodule "mediaproxy.so"
#modparam("mediaproxy", "disable", 0)
#modparam("mediaproxy", "mediaproxy_socket", "/var/run/mediaproxy/dispatcher.sock")
#modparam("mediaproxy", "mediaproxy_timeout", 1000)
#modparam("mediaproxy", "signaling_ip_avp", "$avp(nat_ip)")
#modparam("mediaproxy", "media_relay_avp", "$avp(media_relay)")
#modparam("mediaproxy", "ice_candidate", "low-priority")
 

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

#main request 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()) {
             
               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();
            }
 
            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;
    } 
    
    if (ds_is_in_list("$si", "", "1"))
    {
        route(relay);
        exit;
    } 
    
    # check if the clients are using WebSockets or WebSocketSecure
    if (proto == WS || proto == WSS)
    {
        fix_nated_contact();
        setflag(SRC_WS); 
    }
 
    # CANCEL processing
    if (is_method("CANCEL"))
    {
        if (t_check_trans())
            t_relay();
        exit;
    }
 
    t_check_trans();
 
 
   
        
 
    
     # If the request is a register we will pass it along but we need
    # to add the path header (along with the received IP/port info)
    if ( is_method("REGISTER"))
    { 
        if(isflagset(SRC_WS)){
            # if we fail to add the path header then dont let it
            # register because it will cause issues later..
            if (!add_path_received())
            {
                xlog("L_ERR", "$ci|log|unable to add path");
     
                sl_send_reply("503", "Internal path befuddlement");

                xlog("L_INFO", "$ci|end|cleaned up call id from cache");
     
                exit;
            }
            xlog("L_INFO", "$ci|log|added path");
        }
        
        if (isflagset(SRC_WS)){
            fix_nated_register();
            setbflag(DST_WS);
        } 
    }
 
 
    # 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 (!uri==myself) {
        append_hf("P-hint: outbound
"); 
        
        route(relay);
    }
    # requests for my domain
    
    if (is_method("PUBLISH|SUBSCRIBE"))
    {
        sl_send_reply("503", "Service Unavailable");
        exit;
    }
 
    
    
    if (is_method("REGISTER") )
    {    
        if (!ds_select_dst("1", "0")) {
                send_reply("503","Service Unavailable");
                exit;
        } 
    }
    else if (is_method("INVITE")) {
        if (src_ip==10.101.26.107) {
            log("this is internal call
");
            if (!load_balance("1","pstn","1")) {
                    send_reply("503","Service Unavailable");
                    exit;
            }
        } else {
            log("this is external call
");
            if (!load_balance("2","pstn","1")) {
                    send_reply("503","Service Unavailable");
                    exit;
            }
        }
    } 
    
    
    route(relay);
}
 
route[relay] {
    # for INVITEs enable some additional helper routes
    if (is_method("INVITE")) {
         
    #route(media);     
  
    t_on_branch("handle_nat");
        t_on_reply("handle_nat");
        t_on_failure("missed_call");
    }
 
     
 
    if (!t_relay()) {
        send_reply("500","Internal Error");
    };
    exit;
}

#route[media] {
#    if (is_method("BYE") || is_method("CANCEL")) {
#        end_media_session(); 
#    }
#    if (is_method("INVITE")) {
#        engage_media_proxy();
#        use_media_proxy();
#    }
#}

 
 
branch_route[handle_nat] {

    if (!is_method("INVITE") || !has_body("application/sdp"))
        return;

    if (isflagset(SRC_WS) && isbflagset(DST_WS))
        $var(rtpengine_flags) = "ICE=force-relay DTLS=passive";
    else if (isflagset(SRC_WS) && !isbflagset(DST_WS))
        $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";
    else if (!isflagset(SRC_WS) && isbflagset(DST_WS))
        $var(rtpengine_flags) = "UDP/TLS/RTP/SAVPF ICE=force";
    else if (!isflagset(SRC_WS) && !isbflagset(DST_WS))
        $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";

    #rtpengine_offer("$var(rtpengine_flags)");
}
 
 
onreply_route[handle_nat] { 
    if (!has_body("application/sdp"))
        return;

    if (isflagset(SRC_WS) && isbflagset(DST_WS))
        $var(rtpengine_flags) = "ICE=force-relay DTLS=passive";
    else if (isflagset(SRC_WS) && !isbflagset(DST_WS))
        $var(rtpengine_flags) = "UDP/TLS/RTP/SAVPF ICE=force";
    else if (!isflagset(SRC_WS) && isbflagset(DST_WS))
        $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";
    else if (!isflagset(SRC_WS) && !isbflagset(DST_WS))
        $var(rtpengine_flags) = "RTP/AVP replace-session-connection replace-origin ICE=remove";

    #rtpengine_answer("$var(rtpengine_flags)");
}
 
 
failure_route[missed_call] {
    if (t_was_cancelled()) {
        exit;
    }
 
    # 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;
    ##}
 
     
}
 
 

local_route 
{
    
     if (is_method("BYE") ) 
     {
        acc_log_request("internally generated BYE");
     }
}

 五、传输sip代码

#
# OpenSIPS residential configuration script
#     by OpenSIPS Solutions <team@opensips-solutions.com>
#
# This script was generated via "make menuconfig", from
#   the "Residential" scenario.
# You can enable / disable more features / functionalities by
#   re-generating the scenario with different options.#
#
# Please refer to the Core CookBook at:
#      https://opensips.org/Resources/DocsCookbooks
# for a explanation of possible statements, functions and parameters.
#


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

log_level=4
log_stderror=no
log_facility=LOG_LOCAL0

children=4

/* uncomment the following lines to enable debugging */
debug_mode=no

/* 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=no

/* comment the next line to enable the auto discovery of local aliases
   based on reverse DNS on IPs */
auto_aliases=no


listen=udp:192.168.1.100:5060 as 172.29.50.9:5060 # CUSTOMIZE ME



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

#set module path
mpath="/usr/local/lib64/opensips/modules/"
loadmodule "db_mysql.so"
loadmodule "signaling.so"
loadmodule "sl.so"
loadmodule "tm.so"
loadmodule "rr.so"
loadmodule "uri.so"
loadmodule "dialog.so"
loadmodule "maxfwd.so"
loadmodule "textops.so"
loadmodule "mi_fifo.so"
loadmodule "dispatcher.so"
loadmodule "load_balancer.so"
loadmodule "sipmsgops.so"
loadmodule "proto_udp.so"
modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
modparam("dialog", "db_mode", 1)
modparam("dialog", "db_url", "mysql://root:123456@localhost/opensips") 
modparam("rr", "enable_double_rr", 1)
modparam("rr", "append_fromtag", 1)
modparam("tm", "fr_timer", 2)
modparam("dispatcher", "db_url", "mysql://root:123456@localhost/opensips")
modparam("dispatcher", "ds_ping_method", "OPTIONS")
modparam("dispatcher", "ds_ping_interval", 1)
modparam("dispatcher", "ds_probing_threshhold", 2)
modparam("dispatcher", "ds_probing_mode", 5)
modparam("load_balancer", "db_url", "mysql://root:123456@localhost/opensips")
modparam("load_balancer", "probing_method", "OPTIONS")
modparam("load_balancer", "probing_interval", 5)

########## User Location module ########
loadmodule "usrloc.so"
modparam("usrloc", "nat_bflag", "NAT")
modparam("usrloc", "db_url", "mysql://root:123456@localhost/opensips") # CUSTOMIZE ME


########### registrar #########
loadmodule "registrar.so"
modparam("registrar", "received_avp", "$avp(received_nh)")

########## NAT ############
loadmodule "nat_traversal.so"   #加载提供支持的模块
loadmodule "nathelper.so"
modparam("nathelper", "received_avp", "$avp(received_nh)")


#新增的http连接
####### Routing Logic ########

# main request routing logic

route{

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

    if (!has_totag()) {
        # handle hop-by-hop ACK (no routing required)
        record_route();
    }else{
        loose_route();
        t_relay();
        exit;
    }

    # CANCEL processing
    if (is_method("CANCEL")) {
        if (t_check_trans())
            t_relay();
        exit;
    }
    if (is_method("INVITE")) {
        if (!load_balance("1","pstn")) {
               send_reply("503","Service Unavailable");
               exit;
           }
        loose_route();
        t_relay();
        exit;
    }
    else if (is_method("REGISTER")) {
        if (!ds_select_dst("1", "0")) {
            send_reply("503","Service Unavailable");
            exit;
        }
    } else {
        send_reply("405","Method Not Allowed");
        exit;
    }
    if (!t_relay()) {
        sl_reply_error();
    }
}
原文地址:https://www.cnblogs.com/zhangxianrong/p/14251867.html