I moved in to an ONREPLAY route and it seems to be working well with the mangler.

Thank you all.

Edward

From: Daniel-Constantin Mierla <miconda@gmail.com>
Sent: Tuesday, August 4, 2020 12:05 PM
To: Edward Romanenco <edward@telemessage.com>; Kamailio (SER) - Users Mailing List <sr-users@lists.kamailio.org>
Subject: Re: [SR-Users] Manipulating SDP IP for Inbound Calls
 

Hello,


hard to track the execution path without a test environment ... I would suggest to load debugger module and enable cfgtrace for it to see what actions in configuration file are executed, to be sure it gets to the fix_nated_sdp().


Cheers,
Daniel


On 04.08.20 10:44, Edward Romanenco wrote:
I tried using nathelper in the following way -  fix_nated_sdp("2","XX.XX.XX.XX"); - it still shows my internal IP.
Attaching my request routes, can you kindly check and see if I am using it correctly?

SDP
.
v=0.
o=FreeSWITCH 1596486133 1596486134 IN IP4 172.18.0.40.
s=FreeSWITCH.
c=IN IP4 172.18.0.40.
t=0 0.
m=audio 43954 RTP/AVP 8 101.
a=rtpmap:8 PCMA/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.
a=ptime:20.


REQUEST ROUTES
request_route {
    setflag(22);
    route(REQINIT);

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

    route(WITHINDLG);

    if(t_precheck_trans()) {
        t_check_trans();
        exit;
    }
    t_check_trans();

    remove_hf("Route");
    if (is_method("INVITE|SUBSCRIBE")){// && is_present_hf("X-SESSION-ID")){
      record_route();
    }
    if (is_method("INVITE")) {
        setflag(FLT_ACC);
    }

    if ($rU==$null) {
        sl_send_reply("484","Address Incomplete");
        exit;
    }

    route(OUTGOING);
    route(PSTN);
    route(INCOMING);
    route(RELAY);
}

route[REMOVE_X_HEADERS] {
if(is_present_hf("X-SESSION-ID")) {
        remove_hf("X-FS-Support");
   remove_hf("X-Src");
   remove_hf("X-DESTINATIONS");
   remove_hf("X-SESSION-ID");
    }
        xinfo("Remove X Headers; Contact Header is $ct");
}

route[INCOMING] {
    if(is_present_hf("X-SESSION-ID")) {
      return;
    }

if(ds_is_from_list("4")) {
route(TRANSLATE_SRC_IN);
}

route(REQUEST_PERMISSIONS);
fix_nated_sdp("2","XX.XX.XX.XX");
    exit;
}

route[REQUEST_PERMISSIONS] {
    $var(body) = 0;
    $var(from) = $fU;

    if($(var(from){s.substr,1,4})=="0972") {
        $var(from)=$(var(from){s.substr,2,0});
        $fU = $var(from);
    }

    jansson_set("string", "from", "$var(from)", "$var(body)");

    if(is_present_hf("Diversion")) {
        xlog("L_INFO", "Call has been forwarded.");
        jansson_set("string","to","$oU","$var(body)");
    } else {
   jansson_set("string","to","$tU","$var(body)");
    }

    jansson_set("string","forcepstn","false","$var(body)");
    jansson_set("string", "source", "EGRESS", "$var(body)");
    $http_req(all) = $null;
    $http_req(method) = "POST";
    $http_req(hdr) = "Content-Type: application/json";
    $http_req(hdr) = "Accept: application/json";
    $http_req(hdr) = "Connection: keep-alive";
    $http_req(body) = $var(body);
    $var(re_url)= "https://VNVHOST/voiceandvideo/makeCall";
    t_newtran();

    if (http_async_query("$var(re_url)", "REQUEST_PERMISSIONS_REPLY") < 0) {
        t_reply("500", "Server Internal Error");
        exit;
    }
}

route[REQUEST_PERMISSIONS_REPLY] {
    if ($(http_err{s.len})) {
        xlog("L_ERR","Got error from server 1");
   t_reply("500", "Server Internal Error");
        exit;
    } else if ($http_rs != 200) {
        xlog("L_ERR","Got error from server 2");
        t_reply("500", "Server Error");
        exit;
    }

    # Populate dialog variables for CDR Creation
    $var(count) = 0;
    jansson_get("list",$http_rb,"$dlg_var(destinations_array)");
    jansson_get("msgID", $http_rb, "$dlg_var(session_id)");
    jansson_get("resultCode",$http_rb,"$dlg_var(resultCode)");

    if($dlg_var(resultCode)!=0) {
        t_reply("500","Server Internal Error");
        exit;
    }

    ## EGRESS Server Information
    route(ADD_TELEMESSAGE_HDRS);
    $var(setid) = "1";

    if(!ds_select_dst("1", "4")) {
        send_reply("404", "No destination");
        exit;
    }

    route(RELAY);
    exit;
}

route[RELAY] {
    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 (!t_relay()) {
        sl_reply_error();
    }

    exit;
}

# Per SIP request initial checks
route[REQINIT] {
#!ifdef WITH_ANTIFLOOD
    # flood detection from same IP and traffic ban for a while
    # be sure you exclude checking trusted peers, such as pstn gateways
    # - local host excluded (e.g., loop to self)
    if(src_ip!=myself) {
        if($sht(ipban=>$si)!=$null) {
            # ip is already blocked
            xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
            exit;
        }
        if (!pike_check_req()) {
            xlog("L_ALERT","ALERT: pike blocking $rm from $fu (IP:$si:$sp)\n");
            $sht(ipban=>$si) = 1;
            exit;
        }
    }
#!endif
    if($ua =~ "friendly-scanner|sipcli|VaxSIPUserAgent") {
        # silent drop for scanners - uncomment next line if want to reply
        # sl_send_reply("200", "OK");
        exit;
    }

    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("Malformed SIP message from $si:$sp\n");
        exit;
    }
}

# Handle requests within SIP dialogs
route[WITHINDLG] {
    xlog("L_ERR","Entering withindlgs");
    if (!has_totag()) return;

    # sequential request withing a dialog should
    # take the path determined by record-routing
    if (loose_route()) {
        xlog("L_ERR","loose route");
        route(DLGURI);
        if (is_method("BYE")) {
            xlog("L_ERR","BYE recevied in loose route");
            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.
            xlog("L_ERR","*****************1 Adding rr");
          record_route();
        }

        route(RELAY);
        exit;
    }

    if (is_method("SUBSCRIBE") && uri == myself) {
        # in-dialog subscribe requests
        route(PRESENCE);
        exit;
    }
    if ( is_method("ACK") ) {
        if ( t_check_trans() ) {
            # no loose-route, but stateful ACK;
            # must be an ACK after a 487
            # or e.g. 404 from upstream server
            route(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);
#!ifdef WITH_NATSIPPING
        # do SIP NAT pinging
        setbflag(FLB_NATSIPPING);
#!endif
    }
    if (!save("location")) {
        sl_reply_error();
    }
    exit;
}

# User location service
route[LOCATION] {

#!ifdef WITH_SPEEDDIAL
    # search for short dialing - 2-digit extension
    if($rU=~"^[0-9][0-9]$") {
        if(sd_lookup("speed_dial")) {
            route(SIPOUT);
        }
    }
#!endif

#!ifdef WITH_ALIASDB
    # search in DB-based aliases
    if(alias_db_lookup("dbaliases")) {
        route(SIPOUT);
    }
#!endif

    $avp(oexten) = $rU;
    if (!lookup("location")) {
        $var(rc) = $rc;
        route(TOVOICEMAIL);
        t_newtran();
        switch ($var(rc)) {
            case -1:
            case -3:
                send_reply("404", "Not Found");
                exit;
            case -2:
                send_reply("405", "Method Not Allowed");
                exit;
        }
    }

    if (is_method("INVITE")) {
        setflag(FLT_ACCMISSED);
    }

    route(RELAY);
    exit;
}

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

    if(is_method("SUBSCRIBE") && $hdr(Event)=="message-summary") {
        route(TOVOICEMAIL);
        # returns here if no voicemail server is configured
        sl_send_reply("404", "No voicemail service");
        exit;
    }

#!ifdef WITH_PRESENCE
    if (!t_newtran()) {
        sl_reply_error();
        exit;
    }

    if(is_method("PUBLISH")) {
        handle_publish();
        t_release();
    } else if(is_method("SUBSCRIBE")) {
        handle_subscribe();
        t_release();
    }
    exit;
#!endif

    # if presence enabled, this part will not be executed
    if (is_method("PUBLISH") || $rU==$null) {
        sl_send_reply("404", "Not here");
        exit;
    }
    return;
}

# IP authorization and user authentication
route[AUTH] {
#!ifdef WITH_AUTH

#!ifdef WITH_IPAUTH
    if((!is_method("REGISTER")) && allow_source_address()) {
        # source IP allowed
        return;
    }
#!endif

    if (is_method("REGISTER") || from_uri==myself) {
        # authenticate requests
        if (!auth_check("$fd", "subscriber", "1")) {
            auth_challenge("$fd", "0");
            exit;
        }
        # user authenticated - remove auth header
        if(!is_method("REGISTER|PUBLISH"))
            consume_credentials();
    }
    # if caller is not local subscriber, then check if it calls
    # a local destination, otherwise deny, not an open relay here
    if (from_uri!=myself && uri!=myself) {
        sl_send_reply("403","Not relaying");
        exit;
    }

#!endif
    return;
}

# Caller NAT detection
route[NATDETECT] {
#!ifdef WITH_NAT
    force_rport();
    if (nat_uac_test("19")) {
        if (is_method("REGISTER")) {
            fix_nated_register();
        } else {
            if(is_first_hop()) {
                set_contact_alias();
            }
        }
        setflag(FLT_NATS);
    }
#!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")) {
if(ds_is_from_list()){
xdbg("__META rtpengine priv->pub");
rtpengine_manage("replace-session-connection replace-origin direction=priv direction=pub");
} else {
xdbg("__META rtpengine pub->priv");
rtpengine_manage("replace-session-connection replace-origin direction=pub direction=priv");
}
    } else {
if(ds_is_from_list()) {
xdbg("__META rtpengine priv->pub");
rtpengine_manage("replace-session-connection replace-origin trust-address direction=priv direction=pub");
} else {
xdbg("__META rtpengine pub->priv");
rtpengine_manage("replace-session-connection replace-origin trust-address direction=pub direction=priv");
}
    }

    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();
        }
xlog("L_ERR","20202020 in is_reply");
    }
#!endif
    return;
}

# URI update for dialog requests
route[DLGURI] {
#!ifdef WITH_NAT
    if(!isdsturiset()) {
        handle_ruri_alias();
    }
#!endif
    return;
}

# Routing to foreign domains
route[SIPOUT] {
    if (uri==myself) return;
    append_hf("P-hint: outbound\r\n");
    route(RELAY);
    exit;
}

# PSTN GW routing
route[PSTN] {
#!ifdef WITH_PSTN
    # check if PSTN GW IP is defined
    if (strempty($sel(cfg_get.pstn.gw_ip))) {
        xlog("SCRIPT: PSTN routing enabled but pstn.gw_ip not defined\n");
        return;
    }

    # route to PSTN dialed numbers starting with '+' or '00'
    #     (international format)
    # - update the condition to match your dialing rules for PSTN routing
    if(!($rU=~"^(\+|00)[1-9][0-9]{3,20}$")) return;

    # only local users allowed to call
    if(from_uri!=myself) {
        sl_send_reply("403", "Not Allowed");
        exit;
    }

    if (strempty($sel(cfg_get.pstn.gw_port))) {
        $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip);
    } else {
        $ru = "sip:" + $rU + "@" + $sel(cfg_get.pstn.gw_ip) + ":"
                    + $sel(cfg_get.pstn.gw_port);
    }

    route(RELAY);
    exit;
#!endif

    return;
}

# XMLRPC routing
#!ifdef WITH_XMLRPC
route[XMLRPC] {
    # allow XMLRPC from localhost
    if ((method=="POST" || method=="GET")
            && (src_ip==127.0.0.1)) {
        # close connection only for xmlrpclib user agents (there is a bug in
        # xmlrpclib: it waits for EOF before interpreting the response).
        if ($hdr(User-Agent) =~ "xmlrpclib")
            set_reply_close();
        set_reply_no_connect();
        dispatch_rpc();
        exit;
    }
    send_reply("403", "Forbidden");
    exit;
}
#!endif

# Routing to voicemail server
route[TOVOICEMAIL] {
#!ifdef WITH_VOICEMAIL
    if(!is_method("INVITE|SUBSCRIBE")) return;

    # check if VoiceMail server IP is defined
    if (strempty($sel(cfg_get.voicemail.srv_ip))) {
        xlog("SCRIPT: VoiceMail routing enabled but IP not defined\n");
        return;
    }
    if(is_method("INVITE")) {
        if($avp(oexten)==$null) return;

        $ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)
                + ":" + $sel(cfg_get.voicemail.srv_port);
    } else {
        if($rU==$null) return;

        $ru = "sip:" + $rU + "@" + $sel(cfg_get.voicemail.srv_ip)
                + ":" + $sel(cfg_get.voicemail.srv_port);
    }
    route(RELAY);
    exit;
#!endif

    return;
}

//convert phone number from international to internal
//+972112223344 <-> 011222334
route[TRANSLATE_DST_OUT] {
        xinfo("__META TRANSLATE_DST_OUT");
        xdbg("__META To: $hdr(To)");
        xdbg("__META Regexp: NUM_TRANSLATE_OUT_RE");

        if(subst_uri("/NUM_TRANSLATE_OUT_RE/0\2/"))
                xdbg("__META URI translated");
        else
                xdbg("__META Not translating number in URI");

        if(subst_hf("To", "/NUM_TRANSLATE_OUT_RE/0\2/", "a"))
                xdbg("__META To header translated");
        else
                xdbg("__META Not translating number in to header");
}

//convert phone number from internal format to international
//011222334 <-> +<972>112223344
route[TRANSLATE_SRC_IN] {
$var(number)=$rU;
        if($(var(number){s.substr,1,4})=="+972") {
 $rU="0"+$(var(number){s.substr,5,0});
}
}
/////////////////////////////////////////////////////////////////////////////

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

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

    // fix_nated_contact();
    xlog("L_ERR","2020202020202 Got reply $ct");

    if(status=~"[12][0-9][0-9]") {
        route(NATMANAGE);
    }

if(is_method("INVITE") && is_present_hf("P-Asserted-Identity")) {
remove_hf("P-Asserted-Identity");
}
}

# Manage failure routing cases
failure_route[MANAGE_FAILURE] {
    xlog("Failure! Going to failure route.");
    route(NATMANAGE);
    if (t_is_canceled()) exit;

#!ifdef WITH_BLOCK3XX
    # block call redirect based on 3xx replies.
    if (t_check_status("3[0-9][0-9]")) {
        t_reply("404","Not found");
        exit;
    }
#!endif

#!ifdef WITH_BLOCK401407
    # block call redirect based on 401, 407 replies.
    if (t_check_status("401|407")) {
        t_reply("404","Not found");
        exit;
    }
#!endif

#!ifdef WITH_VOICEMAIL
    # serial forking
    # - route to voicemail on busy or no answer (timeout)
    if (t_check_status("486|408")) {
        $du = $null;
        route(TOVOICEMAIL);
        exit;
    }
#!endif
}

event_route[topoh:msg-outgoing] {
  if($sndto(ip)=="freeswitch") {
    drop;
  }
  if($sndto(ip)=="81.24.193.248") {
    drop;
  }
}

Edward

From: Daniel-Constantin Mierla <miconda@gmail.com>
Sent: Tuesday, August 4, 2020 11:19 AM
To: Kamailio (SER) - Users Mailing List <sr-users@lists.kamailio.org>; Edward Romanenco <edward@telemessage.com>
Subject: Re: [SR-Users] Manipulating SDP IP for Inbound Calls
 

Hello,

the mangler module does not have any idea of inbound/outbound directions, so you can use it for any of them.


Also, the nathelper module should have a function allowing to change the ip in the sdp, iirc.


On the other hand, if you use rtppengine for the calls, then the ips should be replaced by it.


Do not forget to use msg_apply_changes() in case you want those changes to be visible immediately in the configuration file.


Cheers,
Daniel


On 29.07.20 13:18, Edward Romanenco wrote:
Hey guys,

I am working on a project involving Kamailio dockerezation, which is meant to run alongside Freeswitch and RTPEngine containers, on the basis of a Docker-Compose file which is launched on top of a CentOS 7.7 host system.

Anyway, I would love to know if there is any way to manipulate / mask the IP addresses that are being appended to a status 183 response for an incoming invite.

For some reason which I am trying to figure out in parallel, Freeswitch uses the local network bridge subnet instead of the defined external RTP IPs, and I was wondering - Can I manipulate them using Kamailio? I know that Mangler module can do it for outbound calls, but can I do the same for inbound?

v=0.
o=FreeSWITCH 1595974788 1595974789 IN IP4 172.18.0.40.
s=FreeSWITCH.
c=IN IP4 172.18.0.40.
t=0 0.
m=audio 45878 RTP/AVP 8 101.
a=rtpmap:8 PCMA/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16

Edward

_______________________________________________
Kamailio (SER) - Users Mailing List
sr-users@lists.kamailio.org
https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-users
-- 
Daniel-Constantin Mierla -- www.asipto.com
www.twitter.com/miconda -- www.linkedin.com/in/miconda
Funding: https://www.paypal.me/dcmierla
-- 
Daniel-Constantin Mierla -- www.asipto.com
www.twitter.com/miconda -- www.linkedin.com/in/miconda
Funding: https://www.paypal.me/dcmierla