Opensips + Trixbox realtime intergration

2009-11-03
2013-05-09
  • Karnith Jarrek

    Karnith Jarrek - 2009-11-03

    I have finally integrated opensips with trixbox using opensips as a registrar and perimeter cloud for Trixbox. I have alterted it so that opensips accuires the accounts from trixbox dynamically through a view. The reason I did this is because I like the user page of trixbox and plan to enhance it for a users full control over thier account. There is a lot left to do and this solution is far from perfect, so any added input would be welcome.

    How it works:

    Clients register with opensips using thier trixbox username (extention) and password. When calls are made, opensips first looks at the accounts it has. When the accout can’t be found, it then forwards the call to trixbox. By doing this, features using the *NNN sequence get passed automatically to trixbox without the need to  hardcode the paths. I have yet to test outgoing calls from asterisk through opensips, but I think this should work.

    What I did:

    I altered the opensips settings to point at my trixbox server.

        nano /usr/local/etc/opensips/opensipsctlrc

    I changed the DBHOST= to my trixbox server ip.

    Next I changed the opensips.cfg db_url to point to my trixbox server for each module I have activated that uses the db_url.

    e.g

        modparam("usrloc", "db_url",
          "mysql://opensips:opensipsrw@{trixboxserverip}/opensips")

    Once this is done, log into you trixbox via SSH (I have webmin installed so I used this) and create a new user root with access from your opensips server ip with grant all permissions.

    The reason for this is that we will use the opensipsdbctl to create the opensips database on the trixbox server (because opensips is our registrar, I felt it wise to keep all the dbs on the trixbox server as it will not be accepting outside connections, other than http request to the user and maint pages).

    So, in your console type opensipsdbctl create to start the process. You will need to give your root password of the user you created for the connection.

    Once this is done, you should have the opensips db on trixbox with the opensips users created for you by opensips for access to the opensips dbs.

    Next you will need to drop the subscriber table from opensips as we will be creating a view for this.

    On the trixbox server connect to mysql and create this view: (be sure to enter the domain name for the view)

        CREATE VIEW `opensips`.`subscriber` AS select
          `asterisk`.`sip`.`id` AS `id`,
          `asterisk`.`sip`.`id` AS `username`,
          _latin1'{enter domain name here}' AS `domain`,
          `asterisk`.`sip`.`data` AS `password`,
          _latin1'' AS `ha1`,
          _latin1'' AS `ha2`,
          _latin1'' AS `rpid`
        from `asterisk`.`sip` where keyword='secret';

    for those of you that want to use the domain table of opensips:
    *I have not tried this with multiple domains yet, but with an alteration to the view this could be done, I assume.

        CREATE VIEW `opensips`.`subscriber` AS select
          `asterisk`.`sip`.`id` AS `id`,
          `asterisk`.`sip`.`id` AS `username`,
          `opensips`.`domain`.`domain` AS `domain`,
          `asterisk`.`sip`.`data` AS `password`,
          _latin1'' AS `ha1`,
          _latin1'' AS `ha2`,
          _latin1'' AS `rpid`
        from `asterisk`.`sip`, `opensips`.`domain` where keyword='secret';

    *you will need to enter a domain in the domain table of opensips in order to load the accounts. After adding the domain, you will need to run this command:

        opensipsctl fifo domain_reload

    Now when you create extensions in trixbox, opensips will recieve those accounts automatically and customers will be able to register with opensips.

    The last thing we need to do is add the asterisk hooks to the opensips.cfg for our routes

        ####### Global Parameters #########
       
        debug=3
        log_stderror=no
        log_facility=LOG_LOCAL0
       
        fork=yes
        children=4
       
        /* uncomment the following lines to enable debugging */
        #debug=6
        #fork=no
        #log_stderror=yes
       
        /* uncomment the next line to disable TCP (default on) */
        #disable_tcp=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
       
        /* uncomment the next line to disable the auto discovery of local aliases
           based on revers DNS on IPs (default on) */
        #auto_aliases=no
       
        /* uncomment the following lines to enable TLS support  (default off) */
        #disable_tls = no
        #listen = tls:your_IP:5061
        #tls_verify_server = 1
        #tls_verify_client = 1
        #tls_require_client_certificate = 0
        #tls_method = TLSv1
        #tls_certificate = "/usr/local/etc/opensips/tls/user/user-cert.pem"
        #tls_private_key = "/usr/local/etc/opensips/tls/user/user-privkey.pem"
        #tls_ca_list = "/usr/local/etc/opensips/tls/user/user-calist.pem"
       
       
        port=5060
       
        /* uncomment and configure the following line if you want opensips to
           bind on a specific interface/port/proto (default bind on all available) */
        #listen=udp:192.168.1.2:5060
       
       
        ####### Modules Section ########
       
        #set module path
        mpath="/usr/local/lib64/opensips/modules/"
       
        /* uncomment next line for MySQL DB support */
        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 "xlog.so"
        loadmodule "acc.so"
        /* uncomment next lines for MySQL based authentication support
           NOTE: a DB (like db_mysql) module must be also loaded */
        loadmodule "auth.so"
        loadmodule "auth_db.so"
        /* uncomment next line for aliases support
           NOTE: a DB (like db_mysql) module must be also loaded */
        #loadmodule "alias_db.so"
        /* uncomment next line for multi-domain support
           NOTE: a DB (like db_mysql) module must be also loaded
           NOTE: be sure and enable multi-domain support in all used modules
                 (see "multi-module params" section ) */
        loadmodule "domain.so"
        /* uncomment the next two lines for presence server support
           NOTE: a DB (like db_mysql) module must be also loaded */
        #loadmodule "presence.so"
        #loadmodule "presence_xml.so"
       
       
        # ----------- setting module-specific parameters ----------
       
       
        # --- mi_fifo params ---
        modparam("mi_fifo", "fifo_name", "/tmp/opensips_fifo")
       
       
        # --- rr params ---
        # add value to ;lr param to cope with most of the UAs
        modparam("rr", "enable_full_lr", 1)
        # do not append from tag to the RR (no need for this script)
        modparam("rr", "append_fromtag", 0)
       
       
        # --- registrar params ---
        /* uncomment the next line not to allow more than 10 contacts per AOR */
        #modparam("registrar", "max_contacts", 10)
       
       
        # --- usrloc params ---
        #modparam("usrloc", "db_mode",   0)
        /* uncomment the following lines if you want to enable DB persistency
           for location entries */
        modparam("usrloc", "db_mode",   2)
        modparam("usrloc", "db_url",
        "mysql://opensips:opensipsrw@192.168.1.105/opensips")
       
       
        # --- uri params ---
        modparam("uri", "use_uri_table", 0)
       
       
        # --- acc params ---
        /* what sepcial events should be accounted ? */
        modparam("acc", "early_media", 1)
        modparam("acc", "report_ack", 1)
        modparam("acc", "report_cancels", 1)
        /* by default ww 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)
        /* account triggers (flags) */
        modparam("acc", "failed_transaction_flag", 3)
        modparam("acc", "log_flag", 1)
        modparam("acc", "log_missed_flag", 2)
        /* uncomment the following lines to enable DB accounting also */
        modparam("acc", "db_flag", 1)
        modparam("acc", "db_missed_flag", 2)
       
       
        # --- auth_db params ---
        /* uncomment the following lines if you want to enable the DB based
           authentication */
        modparam("auth_db", "calculate_ha1", yes)
        modparam("auth_db", "password_column", "password")
        modparam("auth_db", "db_url",
        "mysql://opensips:opensipsrw@192.168.1.105/opensips")
        modparam("auth_db", "load_credentials", "")
       
       
        # --- alias_db params ---
        /* uncomment the following lines if you want to enable the DB based
           aliases */
        #modparam("alias_db", "db_url",
        # "mysql://opensips:opensipsrw@localhost/opensips")
       
       
        # --- domain params ---
        /* uncomment the following lines to enable multi-domain detection
           support */
        modparam("domain", "db_url",
        "mysql://opensips:opensipsrw@192.168.1.105/opensips")
        modparam("domain", "db_mode", 1)   # Use caching
       
       
        # --- multi-module params ---
        /* uncomment the following line if you want to enable multi-domain support
           in the modules (dafault off) */
        #modparam("alias_db|auth_db|usrloc|uri", "use_domain", 1)
       
       
        # --- presence params ---
        /* uncomment the following lines if you want to enable presence */
        #modparam("presence|presence_xml", "db_url",
        # "mysql://opensips:opensipsrw@localhost/opensips")
        #modparam("presence_xml", "force_active", 1)
        #modparam("presence", "server_address", "sip:192.168.1.2:5060")
       
       
        ####### 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("BYE")) {
        setflag(1); # do accounting …
        setflag(3); # … even if the transaction fails
        } 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();
        }
        # route it out to whatever destination was set by loose_route()
        # in $du (destination URI).
        route(1);
        } else {
        /* uncomment the following lines if you want to enable presence */
        ##if (is_method("SUBSCRIBE") && $rd == "your.server.ip.address") {
        ## # in-dialog subscribe requests
        ## route(2);
        ## 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;
        }
       
        #initial requests
       
        # CANCEL processing
        if (is_method("CANCEL"))
        {
        if (t_check_trans())
        t_relay();
        exit;
        }
       
        t_check_trans();
       
        # authenticate if from local subscriber (uncomment to enable auth)
        # authenticate all initial non-REGISTER request that pretend to be
        # generated by local subscriber (domain from FROM URI is local)
        ##if (!(method=="REGISTER") && from_uri==myself) /*no multidomain version*/
        if (!(method=="REGISTER") && is_from_local())  /*multidomain version*/
        {
        if (!proxy_authorize("", "subscriber")) {
        proxy_challenge("", "0");
        exit;
        }
        if (!db_check_from()) {
        sl_send_reply("403","Forbidden auth ID");
        exit;
        }
       
        consume_credentials();
        # caller authenticated
        }
       
        # preloaded route checking
        if (loose_route()) {
        xlog("L_ERR",
        "Attempt to route with preloaded Route's ");
        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")) {
        setflag(1); # do accounting
        }
        if (!uri==myself)
        ## replace with following line if multi-domain support is used
        ##if (!is_uri_host_local())
        {
        append_hf("P-hint: outbound\r\n");
        # if you have some interdomain connections via TLS
        ##if($rd=="tls_domain1.net") {
        ## t_relay("tls:domain1.net");
        ## exit;
        ##} else if($rd=="tls_domain2.net") {
        ## t_relay("tls:domain2.net");
        ## exit;
        ##}
        route(1);
        }
       
        # requests for my domain
       
        ## uncomment this if you want to enable presence server
        ##   and comment the next 'if' block
        ##   NOTE: uncomment also the definition of route from  below
        ##if( is_method("PUBLISH|SUBSCRIBE"))
        ## route(2);
       
        if (is_method("PUBLISH"))
        {
        sl_send_reply("503", "Service Unavailable");
        exit;
        }
       
       
        if (is_method("REGISTER"))
        {
        # authenticate the REGISTER requests (uncomment to enable auth)
        if (!www_authorize("{your opensips ip}", "subscriber"))
        {
        www_challenge("{your opensips ip}", "0");
        exit;
        }
       
        if (!db_check_to())
        {
        sl_send_reply("403","Forbidden auth ID");
        exit;
        }
       
        if (!save("location"))
        sl_reply_error();
       
        exit;
        }
       
        if ($rU==NULL) {
        # request with no Username in RURI
        sl_send_reply("484","Address Incomplete");
        exit;
        }
         
       
        # apply DB based aliases (uncomment to enable)
        ##alias_db_lookup("dbaliases");
       
        # do lookup with method filtering
        if (!lookup("location","m")) {
        # ASTERISK HOOK - BEGIN
        # callee is not registered, so different to Voicemail
        # First add the VM recording prefix to the RURI
        #prefix("VMR_");
        # forward to the call to Asterisk (replace below with real IP and port)
         rewritehostport("192.168.1.105:5060");
        route(1);
        # ASTERISK HOOK - END
        ##switch ($retcode) {
        ## case -1:
        ## case -3:
        ## t_newtran();
        ## t_reply("404", "Not Found");
        ## exit;
        ## case -2:
        ## sl_send_reply("405", "Method Not Allowed");
        exit;
        #}
        }
       
        # when routing via usrloc, log the missed calls also
        setflag(2);
       
        # arm a failure route in order to catch failed calls
        # targeting local subscribers; if we fail to deliver
        # the call to the user, we send the call to voicemail
        t_on_failure("1");
       
        route(1);
        }
       
       
        route {
        ## for INVITEs enable some additional helper routes
        if (is_method("INVITE")) {
        t_on_branch("2");
        t_on_reply("2");
        t_on_failure("1");
        }
       
        if (!t_relay()) {
        sl_reply_error();
        };
        exit;
        }
       
       
        # Presence route
        /* uncomment the whole following route for enabling presence
           NOTE: do not forget to enable the call of this route from the main
             route */
        ##route
        ##{
        ## 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;
        ##}
       
       
        branch_route {
        xlog("new branch at $ru\n");
        }
       
       
        onreply_route {
        xlog("incoming reply\n");
        }
       
       
        failure_route {
        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")) {
        ##t_reply("404","Not found");
        ## exit;
        ##}
       
        # uncomment the following lines if you want to redirect the failed
        # calls to a different new destination
        if (t_check_status("486|408")) {
        # ASTERISK HOOK - BEGIN
        # First revert the RURI to get the original user in RURI
        # Then add the VM recording prefix to the RURI
        revert_uri();
        prefix("VMR_");
        # forward to the call to Asterisk (replace below with real IP and port)
         rewritehostport("192.168.1.105:5060");
        t_relay();
        # ASTERISK HOOK - END
        exit;
       
        ## sethostport("192.168.2.100:5060");
        ## # do not set the missed call flag again
        ## t_relay();
        }
        }

    I hope this helps some and will keep working to make the intergration even better.

    ~Karnith

     
  • Kevin Makar

    Kevin Makar - 2013-04-08

    Karnith,

    I'm know it's been a few years since you wrote this, but I'm just embarking on this journey now.  Is there any insight/experiences you could share after having implemented this?

    Thanks in advance,
    kmakar89

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks