[SR-Users] Kamailio 5.3.8 and RTPengine 9.4.1.1+0~mr9.4.1.1

Mihai Cezar cezar at mokalife.ro
Fri May 21 19:36:02 CEST 2021


Hi All,

I've been using Kamailio as a proxy for asterisk (with public ips),
everything was fine  until i've changed the setup to private ips for
asterisk.

What I did so far:
- Kamailio and rtpengine are on a box with 1 public IP.
- Asterisk containers on private ips each asterisk has 2 trunks (
1trunk voip provider 1trunk the Proxy).

What works:
- Proxy registrations and sip signaling works.

What it does not  work:
- On the asterisk I got only on rtp connexion, my guess is that has
something to do with the SDP, asterisk put the private ip in the SDP
header.

RTPengine is configured using this guide https://github.com/sipwise/rtpengine

Can you have a look at the kamailio config, i think i am missing
something or do something wrong.

Thank you!

command to start was:
rtpengine --table=42 --listen-ng=127.0.0.1:2223
--interface=public/110.20.20.1 --tos=184 --pidfile=/run/rtpengine.pid
--no-fallback

and the Kamailio cfg is this:

#!KAMAILIO

#!define FLT_ACC 1
#!define FLT_ACCMISSED 2
#!define FLT_ACCFAILED 3
#!define FLT_FS 10

#!define FLT_NATS 5
#!define FLB_NATB 6
#!define FLB_NATSIPPING 7

#!define WITH_DEBUG
#!define WITH_NAT


## This is the main configuration file for our proxy!

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

#!ifdef WITH_DEBUG
debug=4
memdbg=5
memlog=5
log_stderror=yes
disable_core_dump=no
sip_warning=yes
#!else
debug=-0
log_stderror=no
sip_warning=no
disable_core_dump=yes
#!endif

log_facility=LOG_LOCAL0

fork=yes
children=8
auto_aliases=no
port=5060
disable_tcp=yes

server_id = 1
server_signature=yes
server_header="Server: proxy"

dns_try_ipv6=no
dns_try_naptr=no
dns_retr_time=1
dns_retr_no=1
rev_dns=no

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

#loadmodule "db_mysql.so"
loadmodule "jsonrpcs.so"
loadmodule "kex.so"
loadmodule "corex.so"
loadmodule "tm.so"
loadmodule "tmx.so"
loadmodule "sl.so"
loadmodule "rr.so"
loadmodule "pv.so"
loadmodule "maxfwd.so"
loadmodule "usrloc.so"
loadmodule "registrar.so"
loadmodule "textops.so"
loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "acc.so"
loadmodule "dispatcher.so"
loadmodule "path.so"
loadmodule "nathelper.so"
loadmodule "rtpengine.so"


####### Modules Settings
# ----------------- setting module-specific parameters ---------------

modparam("xlog", "buf_size", 4096)
modparam("xlog", "prefix", "xlog: ")
modparam("xlog", "log_facility", "LOG_DAEMON")
modparam("xlog", "log_colors", "L_ERR=cr")
modparam("xlog", "log_colors", "L_ERR=cr;L_WARN=px")

# ----- jsonrpcs params -----
modparam("jsonrpcs", "pretty_format", 1)

# ----- tm params -----
modparam("tm", "failure_reply_mode", 3)
modparam("tm", "fr_timer", 30000)
modparam("tm", "fr_inv_timer", 120000)

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

#!ifdef WITH_NAT
modparam("nathelper", "received_avp", "$avp(RECEIVED)")
modparam("nathelper", "nortpproxy_str", "a=sdpmangled:yes\r\n")
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "ping_nated_only", 1)
modparam("nathelper", "sipping_bflag", FLB_NATSIPPING)
modparam("nathelper", "sipping_from", "sip:pinger at proxy")

# params needed for NAT traversal in other modules
modparam("nathelper|registrar", "received_avp", "$avp(RECEIVED)")
modparam("usrloc", "nat_bflag", FLB_NATB)

modparam("rtpengine", "rtpengine_sock", "udp:127.0.0.1:2223")
modparam("rtpengine", "rtpengine_retr", 2)
modparam("rtpengine", "hash_table_size", 256)
modparam("rtpengine", "hash_table_tout", 600)
#!endif

# ----- registrar params -----
modparam("registrar", "method_filtering", 1)
modparam("registrar", "append_branches", 0)
modparam("registrar", "max_expires", 3600)
modparam("registrar", "gruu_enabled", 1)

# ----- acc params -----
modparam("acc", "early_media", 0)
modparam("acc", "report_ack", 0)
modparam("acc", "report_cancels", 0)
modparam("acc", "detect_direction", 0)
modparam("acc", "log_flag", FLT_ACC)
modparam("acc", "log_missed_flag", FLT_ACCMISSED)
modparam("acc", "log_extra",
"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd;src_ip=$si")
modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)

# ----- dispatcher params -----
modparam("dispatcher", "list_file", "/etc/kamailio/plugins/dispatcher.list")
modparam("dispatcher", "xavp_dst", "_dsdst_")
modparam("dispatcher", "xavp_ctx", "_dsctx_")
modparam("dispatcher", "ds_ping_from", "sip:ping at proxy")
modparam("dispatcher", "ds_probing_mode", 1)

modparam("path", "use_received", 1)


####### Routing Logic ###########
# main request routing logic

request_route {

    # per request initial checks
    route(REQINIT);

    # NAT detection
    route(NATDETECT);

    if(ds_is_from_list()) {
            setflag(FLT_FS);
    }

    # CANCEL processing
    if (is_method("CANCEL")) {
        rtpengine_delete();
        if (t_check_trans()) {
            route(RELAY);
        }
        exit;
    }

    # handle retransmissions
    if (!is_method("ACK")) {
        if(t_precheck_trans()) {
            t_check_trans();
            exit;
        }
        t_check_trans();
    }

    # handle requests within SIP dialogs
    route(WITHINDLG);

    if (isflagset(FLT_FS)) {
            route(FROM_WORLD);
            exit;
    }

    ### only initial requests (no To tag)

    # record routing for dialog forming requests (in case they are routed)
    # - remove preloaded route headers
    remove_hf("Route");
    if (is_method("INVITE|SUBSCRIBE")) {
        record_route();
    }

    # account only INVITEs
    if (is_method("INVITE")) {
        setflag(FLT_ACC); # do accounting
        sl_send_reply("100","Trying");
    }

    # handle presence related requests
    route(PRESENCE);

    # handle registrations
    route(REGISTRAR);

    if ($rU==$null) {
        # request with no Username in RURI
        sl_send_reply("484","Address Incomplete");
        exit;
    }

    # dispatch destinations
    route(DISPATCH);
}

route[FROM_WORLD]
{
        record_route();
        route(RELAY);
        exit;
}

route[RELAY] {
    if (!t_relay()) {
        sl_reply_error();
    }

    if (!add_path()) {
        sl_send_reply("503", "Internal Path Error");
    }

    if (is_method("INVITE|BYE|SUBSCRIBE|UPDATE")) {
        if(!t_is_set("branch_route")) t_on_branch("MANAGE_BRANCH");
    }
    if (is_method("INVITE|SUBSCRIBE|UPDATE")) {
        if(!t_is_set("onreply_route")) t_on_reply("MANAGE_REPLY");
    }
    if (is_method("INVITE")) {
        if(!t_is_set("failure_route")) t_on_failure("MANAGE_FAILURE");
    }

    if (has_body("application/sdp")) {
            rtpengine_manage();
    }

    append_hf("Supported: path\r\n");
    exit;
}

# Per SIP request initial checks
route[REQINIT] {

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

    if(is_method("OPTIONS") && uri==myself && $rU==$null) {
        sl_send_reply("200","Keepalive");
        exit;
    }

    if(!sanity_check("1511", "7")) {
        xlog("L_WARN","Malformed SIP message from $si:$sp\n");
        exit;
    }
}

# Handle requests within SIP dialogs
route[WITHINDLG] {
    if (has_totag()) {
        # sequential request withing a dialog should
        # take the path determined by record-routing
        if (loose_route()) {
            if (is_method("BYE")) {
                rtpengine_delete();
                setflag(FLT_ACC); # do accounting ...
                setflag(FLT_ACCFAILED); # ... even if the transaction fails
            } else if ( is_method("ACK") ) {
                # ACK is forwarded statelessly
                route(NATMANAGE);
            } else if ( is_method("NOTIFY") ) {
                # Add Record-Route for in-dialog NOTIFY as per RFC 6665.
                record_route();
            }
            route(RELAY);
            # exit;

        } else {

            if (is_method("SUBSCRIBE") && uri == myself) {
                # in-dialog subscribe requests
                route(PRESENCE);
                exit;
            }
            if ( is_method("ACK") ) {
                if ( t_check_trans() ) {
                    # non loose-route, but stateful ACK; must be 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;
    }
}

# Handle SIP registrations
route[REGISTRAR] {

    if(!is_method("REGISTER"))
        return;

    if(isflagset(FLT_NATS)) {
        setbflag(FLB_NATB);
    }

    if (!add_path_received()) {
        sl_send_reply("503", "Internal Path Error");
    };

    route(DISPATCH);
}

# Presence server route
route[PRESENCE] {
    if(!is_method("PUBLISH|SUBSCRIBE"))
        return;

    sl_send_reply("404", "Not found");
    exit;
}


# Dispatch requests
route[DISPATCH] {
    # to add more servers in k8s
    if (!ds_select_dst("1", "4")) {
                    send_reply(503, "Service Unavailable $fd");
                    exit;
    }

    t_on_failure("RTF_DISPATCH");
    route(RELAY);
    exit;
}

# Caller NAT detection
route[NATDETECT] {
#!ifdef WITH_NAT
     if (nat_uac_test("3")) {
               if (is_method("REGISTER")) {
                           xlog("L_WARN", "natdetect
fix_nated_register ip: $si\n");
                       fix_nated_register();
               } else {
                           xlog("L_WARN", "natdetect set_contact_alias
ip: $si\n");
                       fix_nated_contact();
               }
               force_rport();
       }
       if (has_body("application/sdp") && nat_uac_test("8")) {
               xlog("L_WARN", "sdp fix ip: $si\n");
               fix_nated_sdp("10");
       }
#!endif
    return;
}

# RTPProxy control and signaling updates for NAT traversal
route[NATMANAGE] {
#!ifdef WITH_NAT
        if (is_request()) {
                if(has_totag()) {
                        if(check_route_param("nat=yes")) {
                                setbflag(FLB_NATB);
                        }
                }
        }
        if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB))) return;

        if(nat_uac_test("8")) {
            xlog("L_WARN", "nat_uac_test 1...");
            rtpengine_manage("replace-origin
replace-session-connection direction=public ICE=force");
        } else {
            xlog("L_WARN", "nat_uac_test addrtp...");
            rtpengine_manage("codec-strip-all codec-transcode-PCMA
codec-transcode-PCMU codec-transcode-G729 replace-origin
replace-session-connection direction=public ICE=force ");
        }

        if (is_request()) {
                if (!has_totag()) {
                        if(t_is_branch_route()) {
                                add_rr_param(";nat=yes");
                        }
                }
        }
        if (is_reply()) {
                if(isbflagset(FLB_NATB)) {
                        if(is_first_hop())
                                set_contact_alias();
                }
        }
#!endif
        return;
}

# Manage outgoing branches
branch_route[MANAGE_BRANCH] {
    xlog("L_WARN", "new branch [$T_branch_idx] to $ru\n");
    route(NATMANAGE);
}

# Manage incoming replies
onreply_route[MANAGE_REPLY] {
        xlog("L_WARN", "incoming reply\n");

        if(status=~"[12][0-9][0-9]") {
                route(NATMANAGE);
        }
        if (has_body("application/sdp")) {
                rtpengine_manage();
        }

}

onreply_route[REPLY_ROUTE] {
    if(status=~"2[0-9][0-9]") {
        rtpengine_answer("replace-session-connection replace-origin");
    }
    if (has_body("application/sdp")) {
        rtpengine_offer();
    }
}

# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
    xlog("L_WARN", "failure route\n");
    route(NATMANAGE);
    if (t_is_canceled()) exit;
}

# Try next destionations in failure route
failure_route[RTF_DISPATCH] {
    if (t_is_canceled()) {
        exit;
    }
    # next DST - only for 500 or local timeout
    if (t_check_status("500")
            or (t_branch_timeout() and !t_branch_replied())) {
        if(ds_next_dst()) {
            xlog("Retrying to <$ru> via <$du> (attrs:
$xavp(_dsdst_=>attrs))\n");
            t_on_failure("RTF_DISPATCH");
            route(RELAY);
            exit;
        }
    }
}



More information about the sr-users mailing list