Tuesday, March 6, 2012

Making RTPproxy work


Kamailio + RTPproxy  

In response to my previous post related to Kamailio as SBC for Media-Servers, I'm often asked to show how to make this whole setup work with RTPproxy. That means a successful two-way audio call. Remember that the original configuration found on Asipto-Blog is for Public-IPs only.

I had to do alot of hit-&-trial sort of testings with my configuration before making the configurations work for me, so I'll share all that I remember now.

UPDATE: Another new version of this page is available here.

STEP-I : Starting RTPproxy:
Start RTPproxy in bridging mode.

#/usr/sbin/rtpproxy -F -s udp:127.0.0.1:7722 -l PU.BL.IC.IP/10.1.1.1 -d DBUG:LOG_LOCAL0
STEP-II: Kamailio Configuration file:
Define RTPproxy controller port in modparams area.

#RTPproxy instance to be used: 7722 
#PU.BL.IC.IP<<=Transform=>> 10.1.1.1
modparam("rtpproxy", "rtpproxy_sock", "udp:127.0.0.1:7722") 

Then in route[RTPPROXY] we need to know if the call is coming from WAN/internet side or from  LAN/Private Asterisk's side so I had to put the following lines in modparams area as well for DB connectivity. This is required to query the dispatcher tables in RTPPROXY route.

# ------- AVP-OPS params ---------
modparam("avpops","db_url", DBURL)
modparam("avpops","avp_table","dispatcher")

So finally in the route for RTPproxy we querry the DB table dispatcher for inbound or oubound call requests from/to media-servers.

# RTPProxy control
route[RTPPROXY] {
#!ifdef WITH_NAT
 xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in Route[RTPPROXY]\n");
 if (is_method("BYE")) {
  xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in Route[RTPPROXY] unforced RTP Proxy STATS='$rtpstat'\n");
  unforce_rtp_proxy();
 } else if (is_method("INVITE")){
#INCOMING CALL 
  if(avp_db_query("select destination from dispatcher where destination like '%$dd%'")){
   xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in route[RTPPROXY] RTPproxy with IE Flags\n");
#INCOMING CALL NEEDS TO GOTO PRIVATE-IP ASTERISK USE - IE
   rtpproxy_manage("rie");
 
 }
  else if(avp_db_query("select destination from dispatcher where destination='sip:$si:$sp'")){
   xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in route[RTPPROXY] RTPproxy with EI Flags\n");
#INCOMING CALL FROM PRIVATE-IP ASTERISK USE - EI
   rtpproxy_manage("rei");

  }
  else
  {
   rtpproxy_manage("r");
    xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in Route[RTPPROXY] Forcing RTPproxy\n");
  }

 }
 if (!has_totag()){ 
  add_rr_param(";nat=yes");
 }
#!endif
 return;
}

RTPproxy Bridging Network Scenario
Please note that the order of I and E flags. The sequence of these flags depends on the rtpproxy running in the background and the order of PUBLICIP and PRIVATEIP while starting RTPproxy.
#/usr/sbin/rtpproxy -F -s udp:127.0.0.1:7722 -l PU.BL.IC.IP/10.1.1.1 -d DBUG:LOG_LOCAL0

The flags sequence can get inverted if I execut rtpproxy like this.Note the order of Public Ip and Private IP.
#/usr/sbin/rtpproxy -F -s udp:127.0.0.1:7722 -l 10.1.1.1/PU.BL.IC.IP -d DBUG:LOG_LOCAL0

Once done changes in configurations file save it and restart kamailio. Make sure Kamailio detects the RTPproxy socket and announces that support for Rtpproxy is enabled.

Make calls and see the RTPproxy stats at the end of each call. 

Troubleshooting Tips:

Use "tcpdump" on Kamailio server and trace ALL the traffic on ALL the interfaces i.e WAN+LAN interfaces using the following command.

#tcpdump -i any -s 0 -w SIP-TRACE.pcap -vvvv

Once a call is completed stop the trace by hitting CTRL+C; download the pcap file to your windows desktop; open the file in wireshark; analyse VoIP call and see the flow of packets between caller and callee.Reading and understanding SIP/SDP INVITEs packets between caller to Kamailio and then from Kamailio to Media-server is very critical in understanding why we are having no-audio or one-way-audio for  a bad call.

Thats all for now,I'm thinking of exploring Media-Proxy as well. I hope someday I'll post about it too.

9 comments:

  1. Hello,

    As usual, good news ... Your blog is very helpful !
    But i have one issue, SDP address wrote on frame is unvalid with NAT and RTPProxy use.

    In asterisk log, something like getaddrinfo("192.168.0.13192.168.0.13", "(null)", ...) is wrote, and in frame, and the same think is wrote in c= item.

    I try to debug, bug i don't understand why... Any ideas ?

    Thanks in advance,
    Loic.

    ReplyDelete
    Replies
    1. Good to know, and the issue you're saying is simple. If you go through RTPproxy related mailing threads on user mailing lists you'll know that this happends when you call the rtpproxy/fix_natted_contact function multiple times in your configurations.

      Write a log line everytime you fix SDP/Engage RTPproxy and ensure that you don't call that function twice.
      Once done you should get something going.

      Delete
    2. I need more then one Asterisk, but realy don't know HOWTO observe ONE cleint with several Asterisks via dispatcher, when user 101 of client A, and user 102 of the same client (A) are members of the one queue (for ex. 1000) for receiving incoming calls to client PSTN numbers (with/without IVR)? Or howto pickup the call to 101 by 102?

      So, I am found just only this soulution: 1 sip proxy for all clients, differents domains for registration and routing via Asterisk-1 if the domain-1, and Asterisk-2 if the doman-2. So I can get scalable in the feature, but without load balancing, unfortunatly.

      A little change official tutorial of Kamailio + Asterisk + realtime (I am change to static host=2.2.2.2 for each clients peer):

      ...

      ## domain=sip1.domain.com.ua
      asterisk1.bindip = "2.2.2.101" desc "Asterisk 1 IP Address"
      asterisk1.bindport = "5080" desc "Asterisk SIP Port"

      ## domain=sip2.domain.com.ua
      asterisk2.bindip = "3.3.3.101" desc "Asterisk 2 Lan2Lan over OpenVPN IP Address"
      asterisk2.bindport = "5080" desc "Asterisk SIP Port"

      ...

      #!ifdef WITH_ASTERISK
      if(is_method("INVITE") && (!route(FROMASTERISK1)) && to_uri=~"sip:.+@sip1.domain.com.ua") {

      route(TOASTERISK1);
      exit;
      }
      if(is_method("INVITE") && (!route(FROMASTERISK2)) && to_uri=~"sip:.+@sip2.domain.com.ua") {

      route(TOASTERISK2);
      exit;
      }
      #!endif

      Delete
    3. Alex you should really go through this: http://saevolgo.blogspot.com/2011/11/how-to-increasing-voip-services.html to understand how dispatcher can help you.

      Also, I'm replying t you on mailing lists but somehow things aren't clearing up for you. Let me see if I can take off some time and help you with this personally.

      Delete
    4. After learning your example with dispatcher LB, as you posted link for me, I can't get info, how you did changed the route[NATMANAGE] (from tutorial Kamailio+Asterisk by Asipto), because there only one inctance of rtpproxy_manage() - without any flags.

      So, finally it's works for me.

      #!define ASTERISK_LAN1 2.2.2.0/24
      # End second LAN for PBXs - tunneling with LAN1 over OpenVPN:
      #!define ASTERISK_LAN2 3.3.3.0.0/24

      rtpproxy in bridge mode.

      And route[NATMANAGE] from Asipto tutorial (http://kb.asipto.com/asterisk:realtime:kamailio-4.0.x-asterisk-11.3.0-astdb) changed for my needs :

      # RTPProxy control
      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((src_ip==ASTERISK_LAN1) || (src_ip==ASTERISK_LAN2))
      {
      rtpproxy_manage("cwei");
      } else {
      rtpproxy_manage("cwie");
      }

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

      My balancing idea is just have hot-spare server of each of PBX (Asterisk [1,2,..n]), and hosts all users of one clients on the one PBX - because a queue, feautures, pickup, etc.

      Delete
  2. Hi!
    Why you need to use AVP and dispatcher table for RTPPROXY illustration? Sorry, but this is more difficult to readers (like me) - IMHO =) I'm not use dispatcher, because it can't help with balancing applications with several asterisk servers (queue, call pickup, etc). So I need to use one privat IP for one client's Asterisk server (which can obtain several clients with own dialplan/contexts).

    For detecting if it comes from Asterisk (from tutorial of Asipto:

    route[FROMASTERISK1] {
    if($si==$sel(cfg_get.asterisk1.bindip) && $sp==$sel(cfg_get.asterisk1.bindport))
    return 1;
    return -1;
    }

    I am realy NEW for Kamailio ;) Thanks to your Blog I can learning HOWTO.

    ReplyDelete
    Replies
    1. Hi Alexandr,
      Well yeah if you want to use just one asterisk then you probably don't need to use Kamailio. This is a sequel to the previous post where we need to use SIP Proxy for facing multiple servers.

      So using just one IP was never part of the show. That is why we need dispatcher to dynamically distribute calls all around and thus we get more calls served.

      So imagine you've multiple clients and each client needs to make more calls than a single Asterisk server can handle!! you'd have to use dispatcher then.

      Delete
  3. I have Kamailio on OpenSUSE with static real Public IP (WAN), for ex. 1.1.1.1. I have LAN IP 2.2.2.2. Asterisk as KVM virtual machine with LAN IP 2.2.2.101 and default GW not the SuSe (2.2.2.2), but 2.2.2.1 pfsense LAN with PUB IP 1.1.1.2) I am configured Registration of UA on Kamailio DB, and on Asterisk side create a static peers with Kamailio LAN ip (host=2.2.2.2).

    RTP Proxy question.

    /usr/sbin/rtpproxy -u daemon -l 1.1.1.1 -s udp:127.0.0.1 12221

    Whe User 1-100 calling User 1-101, on Asterisk side I see:

    -- Called SIP/1-100@sip1.somedomain.com.ua
    -- SIP/sip1.somedomain.com.ua-000004cf is ringing
    -- SIP/sip1.somedomain.com.ua-000004cf answered SIP/1-101-000004ce
    > 0x15bc370 -- Probation passed - setting RTP source address to 1.1.1.1:50868
    > 0x7f2b6044bd10 -- Probation passed - setting RTP source address to 1.1.1.1:35082

    Got RTP packet from 1.1.1.1:50868 (type 00, seq 027109, ts 000160, len 000160)
    Sent RTP packet to 1.1.1.1:35082 (type 00, seq 037469, ts 000160, len 000160)
    Got RTP packet from 1.1.1.1:50868 (type 00, seq 027110, ts 000320, len 000160)
    Sent RTP packet to 1.1.1.1:35082 (type 00, seq 037470, ts 000320, len 000160)
    Got RTP packet from 1.1.1.1:50868 (type 00, seq 027111, ts 000480, len 000160)
    Sent RTP packet to 1.1.1.1:35082 (type 00, seq 037471, ts 000480, len 000160)
    Got RTP packet from 1.1.1.1:50868 (type 00, seq 027112, ts 000640, len 000160)
    Sent RTP packet to 1.1.1.1:35082 (type 00, seq 037472, ts 000640, len 000160)

    Voice transfers OK.
    But why not Kamailio LAN ip I receiving on the Asterisk side with the same LAN?

    And Kamailio log grep:


    skynet:~ # tail -f /var/log/messages | grep rtpproxy
    2013-08-05T19:18:17.508760+03:00 skynet kamailio[25462]: 3(25481) DEBUG: rtpproxy [rtpproxy_funcs.c:148]: check_content_type(): type found valid
    2013-08-05T19:18:17.508875+03:00 skynet kamailio[25462]: 3(25481) DEBUG: rtpproxy [rtpproxy.c:2624]: force_rtp_proxy(): proxy reply: 63566 1.1.1.1
    2013-08-05T19:18:17.530765+03:00 skynet kamailio[25462]: 6(25484) DEBUG: rtpproxy [rtpproxy_funcs.c:148]: check_content_type(): type found valid
    2013-08-05T19:18:17.530876+03:00 skynet kamailio[25462]: 6(25484) DEBUG: rtpproxy [rtpproxy.c:2624]: force_rtp_proxy(): proxy reply: 41958 1.1.1.1
    2013-08-05T19:18:18.625815+03:00 skynet kamailio[25462]: 4(25482) DEBUG: rtpproxy [rtpproxy_funcs.c:148]: check_content_type(): type found valid
    2013-08-05T19:18:18.627131+03:00 skynet kamailio[25462]: 4(25482) DEBUG: rtpproxy [rtpproxy.c:2624]: force_rtp_proxy(): proxy reply: 39876 1.1.1.1
    2013-08-05T19:18:18.632649+03:00 skynet kamailio[25462]: a=nortpproxy:yes
    2013-08-05T19:18:18.648075+03:00 skynet kamailio[25462]: 6(25484) DEBUG: rtpproxy [rtpproxy_funcs.c:148]: check_content_type(): type found valid
    2013-08-05T19:18:18.649615+03:00 skynet kamailio[25462]: 6(25484) DEBUG: rtpproxy [rtpproxy.c:2624]: force_rtp_proxy(): proxy reply: 43500 1.1.1.1
    2013-08-05T19:18:18.653948+03:00 skynet kamailio[25462]: a=nortpproxy:yes
    2013-08-05T19:18:18.688603+03:00 skynet kamailio[25462]: 4(25482) DEBUG: rtpproxy [rtpproxy_funcs.c:148]: check_content_type(): type found valid
    2013-08-05T19:18:18.689762+03:00 skynet kamailio[25462]: 4(25482) DEBUG: rtpproxy [rtpproxy.c:2624]: force_rtp_proxy(): proxy reply: 63566 1.1.1.1
    2013-08-05T19:18:18.701062+03:00 skynet kamailio[25462]: 6(25484) DEBUG: rtpproxy [rtpproxy_funcs.c:148]: check_content_type(): type found valid
    2013-08-05T19:18:18.701405+03:00 skynet kamailio[25462]: 6(25484) DEBUG: rtpproxy [rtpproxy.c:2624]: force_rtp_proxy(): proxy reply: 43500 1.1.1.1
    2013-08-05T19:18:18.705506+03:00 skynet kamailio[25462]: a=nortpproxy:yes


    ReplyDelete
    Replies
    1. Hi Again Alex,

      As far as I can reply to your question regarding why RTP is not being set on LAN IP. As you told how you started RTPProxy,
      The RTPproxy is started to work on PUBLIC 1.1.1.1 interface only and hence when you engage RTPproxy it writes that WAN IP in SDP for asterisk to communicate Audio. You should try to follow the STEP-1 of this tutorial for starting RTPproxy in Bridged mode.

      That should get a proper LAN-LAN media stream established.

      Delete