OpenSER Modular Installation

Starting...


This tutorial is designed to help relative newbies (like myself) who wish to understand how exactly to install OpenSER in a slightly unconventional way, as well as understand the basics of OpenSER. The goal of this exercise is to install OpenSER on two PCs, each with a specific task, and have them interact with a MySQL server on an other machine. The design here is academic: one of the OpenSER PC’s will act as a simple stateful proxy, and the other will only act as a registrar.

On a side-note: all the information here is inferred from the scattered documentation and my own use of OpenSER. So it may not be accurate. If I got it wrong somewhere, feel free to tell me. The version this tutorial was based on is 1.1.0, with earlier and later versions of OpenSER there may be variations.

Most of the information in this document can be found elsewhere, but you’ll need to read several documents to put it all together: the SER getting started, a few topics in the OpenSER forums, the dokuwiki, the OpenSER modules and finally this useful beginner’s guide.

The pages on the website that explain how to download and install OpenSER are quite good, so make sure to consult them to have the appropriate libraries OpenSER depends on. In fact in this tutorial I won’t give the detail on how to download, but I will explain the installation. However if you have a problem installing with the .deb or the .tar.gz, don’t hesitate to download a stable version from the CVS!

How does OpenSER work?


If you want to do operations that differ from the usual, you might want to broadly understand the structure of OpenSER. Not the workings of the code (unless you want to do something REALLY special), but how it works once compiled. There’s basically two parts to OpenSER: the core, which is the working executable part, and the modules, which add functionality (especially SIP functionality) to the core.

The modules are by far the most important to give OpenSER its specific task. The useful part of the modules can be divided in two parts: the exported parameters, and the exported functions. These will both be important when it comes to setting up OpenSER with it’s configuration file: openser.cfg (normally located in /usr/local/etc/openser/). Basically the exported parameters will set up the modules to act as you wish, and the exported functions will allow you to program the handling of sip messages. You will also find that some modules depend on other modules to be able to work. For example the Registrar module depends both on the stateless replier module and the User location implementation module. The information about specific modules, as well as their parameters, functions and dependencies can be found here.

The core provides the framework for OpenSER. Whatever else you will find in the configuration file is part of the core (which has parameters, functions, and more – see documentation). Basically, the core parameters will affect local setting, such as debug level, the port to listen on, whether to run in daemon mode, etc… The core routing blocks and routing constructs provide the logical structures for the handling of the messages, and the core functions provides both instruction logic (such as exit()) and instructions for message manipulation (such as rewritehost()).

Setting up the network


For the network we would like to build here’s what we absolutely need:

  • Proxy: OpenSER core, Transaction module (TM) for stateful transactions, Stateless replier module (SL), Record-Route and Route module (RR), Max-Forward processor module (MAXFWD) and the User location implementation (USRLOC), SIP Registrar implementation (REGISTRAR) and MySQL-backend for database API (MYSQL) modules for database connectivity (more on this later).

  • Registrar: OpenSER core, Stateless replier module (SL), User location implementation module (USRLOC), SIP Registrar implementation module (REGISTRAR) and MySQL-backend for database API module (MYSQL).

  • Location service: MySQL server.

I’ll assume that you took my advice and downloaded OpenSER from the CVS. If you used binary packages and managed to get them to work, never fear, it won’t be a problem. Just skip the part about the OpenSER installation. If you really want to follow the rest of the tutorial, go to the directory where the modules are installed (.so files, they should be in /usr/local/lib/openser/) and delete or move (you may want them later) all module files that are not mentioned above.

Modular OpenSER servers installation


To fully understand what is happening, we’ll only install the strict minimum. In order to do this, we will only install those modules that we need and that I mentioned earlier. There’s several ways to achieve this, and here’s what I find the simplest:

Edit the Makefile, and at line 304 change this instruction:



Install: all mk-install-dirs install-cfg install-bin install-modules \
        install-doc install-man


To



Install: openser mk-install-dirs install-cfg install-bin install-modules \
        install-doc install-man


Now, making sure that you have super-user privileges, execute:


> make install


Now we have only the core installed, we’ll add the modules that we want to the installation. First, however, we’ll need to build them (make sure that you have the appropriate libraries installed):


> make include_module=”mysql” modules.


Now you simply need to copy the modules you want to the appropriate directory. If you followed my instructions up to here, it should be /usr/local/lib/openser/modules/. For the proxy you will be copying: tm.so, sl.so, rr.so, maxfwd.so, usrloc.so, registrar.so and mysql.so. For the registrar: sl.so, usrloc.so, registrar.so and mysql.so.

Setting up MySQL


I’ll assume that you managed to install MySQL on the PC destined to be a location server. What you now need is the script to install the necessary OpenSER database: openser_mysql.sh create. The script comes with OpenSER, so you may need to download it if only to get that file (feel free to delete it afterward though). When you run the script you will be prompted to enter your MySQL root password (just press ENTER you haven’t put one) and domain. As far as I can ascertain, this information is in fact mostly useless. If you have a domain, enter it here, otherwise put the IP address of the machine. As well as adding the necessary database and tables, the script will also add a read-only and read-write user:

  • read-only : user: openser password: openserro
  • read-write: user: openser password: openserrw.

These users can be either a local or a remote user (fortunately), and I recommend for security reasons that you change their default passwords. If you don’t know how to do this, you may find a MySQL tutorial on the web.

One fianl thing remains to be done before you can use the MySQL location service, and that’s to make it accessible remotely. You’ll need to change a line in /etc/mysql/my.cnf from


Bind-address     = localhost


to


Bind-address   =  __ip address you’ll be listening on__


Setting up OpenSER


To set up OpenSER you will need to modify two files: openser.cfg and openserctlrc.

Setting up openserctl

Modifying openserctlrc is simple, and is the same on both on the proxy and on the registrar. You will have :



 # $Id: openserctlrc,v 1.2 2006/07/05 19:37:20 miconda Exp $
 #
 # openser control tool resource file
 #
 # here you can set variables used in the openserctl
 
 ## your SIP domain
 SIP_DOMAIN= ''your domain…or ip of the pc with the location service''
 
 ## database type: MYSQL or PGSQL, by defaulte none is loaded
 DBENGINE=MYSQL
 
 ## database host
 DBHOST= ''ip of the machine with the location service''
 
 ## database name
 DBNAME=openser
 
 ## database read/write user
 DBRWUSER=openser
 
 ## database read only user
 DBROUSER=openserro
 
 ## password for database read only user
 DBROPW=openserro
 
 ## database super user
 DBROOTUSER="root"
 
 ## type of aliases used: DB - database aliases; UL - usrloc aliases
 ## - default: none
 ALIASES_TYPE="DB"
 
 ## control engine: FIFO or UNIXSOCK
 ## - default FIFO
 CTLENGINE="FIFO"
 
 ## path to FIFO file
 # OSER_FIFO="FIFO"
 
 ## check ACL names; default on (1); off (0)
 VERIFY_ACL=1
 
 ## ACL names - if VERIFY_ACL is set, only the ACL names from below list
 ## are accepted
 ACL_GROUPS="local ld int voicemail free-pstn"
 
 ## verbose - debug purposes - default '0'
 VERBOSE=1


This file is used by the openserctl utility for database manipulation. For the initial configuration this isn’t very useful, but we’ll be using it when we add security. The entries in lines from DBRWUSER to DBROOTUSER will depend on the configuration of your database (default values shown here).

For openser.cfg the file will be different for the proxy and the registrar, as they will treat messages differently.

Setting up the OpenSER proxy


The first part of the openser.cfg pertains to the local configuration, and we’ll basically skip over it. You will note that not all the default code needs to be replaced.


 #
 # $Id: openser.cfg,v 1.6.2.1 2006/07/17 15:51:03 klaus_darilion Exp $
 #
 # simple quick-start config script
 #
 
 # ----------- global configuration parameters ------------------------
 
 #Uncomment these lines to enter debugging mode
 debug=9            # debug level
 Fork=no
 Log_stderror=yes
   
 
 check_via=no    # (cmd. line: -v)
 dns=no          # (cmd. line: -r)
 rev_dns=no      # (cmd. line: -R)
 listen= ip this pc will listen on
 port=5060
 children=4
 fifo="/tmp/openser_fifo"



It gets interesting once we load the modules and set their parameters.


 # ------------------ module loading ----------------------------------
 
 # Uncomment this if you want to use SQL database
 loadmodule "/usr/local/lib/openser/modules/mysql.so"
 
 loadmodule "/usr/local/lib/openser/modules/sl.so"
 loadmodule "/usr/local/lib/openser/modules/tm.so"
 loadmodule "/usr/local/lib/openser/modules/rr.so"
 loadmodule "/usr/local/lib/openser/modules/maxfwd.so"
 loadmodule "/usr/local/lib/openser/modules/usrloc.so"
 
 loadmodule "/usr/local/lib/openser/modules/registrar.so"
 
 # ----------------- setting module-specific parameters ---------------
 
 # -- usrloc params --
 
 modparam("usrloc", "db_url", "mysql://openser:openserrw@__mysql_server_address__/openser")
 
 # Uncomment this if you want to use SQL database
 # for persistent storage and comment the previous line
 modparam("usrloc", "db_mode", 3)
 
 # -- rr params --
 # add value to ;lr param to make some broken UAs happy
 modparam("rr", "enable_full_lr", 1)


You may have been wondering why we use registrar.so while we do not want the proxy to double as registrar… The reason is that the functions to retrieve the location of a user from the database are unfortunately part of this module, so any server that needs to query the location service needs to load it.

As for the parameters, we tell usrloc where the database is situated, and that we do not want to keep a local table for the addresses, only the remote database (modparam("usrloc", "db_mode", 3)). The part of the file that pertains to the handling of messages will naturally reflect the use of a proxy.


 # -------------------------  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 (msg:len >=  2048 ) {
                sl_send_reply("513", "Message too big");
                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 (!method=="REGISTER")
                record_route();
 
        # subsequent messages withing a dialog should take the
        # path determined by record-routing
        if (loose_route()){
                route(1);
        };
 
        if (!uri==myself) {
                route(1);
        };
 
        # 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 (uri==myself) {
 
                if (method=="REGISTER") {
                        route(2);
                        exit;
                };
 
                lookup("aliases");
                if (!uri==myself) {
                        route(1);
                };
 
  #native SIP destinations are handled using our USRLOC DB
                if (!lookup("location")) {
                        sl_send_reply("404", "Not Found");
                        exit;
                };
        };
 
        route(1);
 }
 
 
 route[1] {
        # send it out now; use stateful forwarding as it works reliably
        # even for UDP2TCP
        if (!t_relay()) {
                sl_reply_error();
        };
        exit;
 }
 
 # route[2] will route REGISTER messages towards the registrar
 # No database connectivity is required here, as the registrar then sends the messages to the
 # location server
 route[2] {
        #rewrinting the host allows the registrar to know that the message is destined for it
        rewritehost("''registrar ip address''");
        if(!t_relay("udp: ''registrar ip address'':5060")) {
                sl_reply_error();
        };
        exit;
 }


Basically, the proxy merely routes (relays) the messages to the appropriate location, checking against the database if necessary. As you can see, the proxy also makes a few checks (and modifications) on the message and sends an error message if necessary.

Setting up the OpenSER registrar


The registrar is obviously simpler then the proxy server, as the only thing that needs to be done is accept the REGISTER request and record it in the database. As the beginning of the code is essentially the same, we’ll only check it from the addition of the modules:



 # ------------------ module loading ----------------------------------
 
 # Uncomment this if you want to use SQL database
 loadmodule "/usr/local/lib/openser/modules/mysql.so"
 
 loadmodule "/usr/local/lib/openser/modules/sl.so"
 loadmodule "/usr/local/lib/openser/modules/usrloc.so"
 loadmodule "/usr/local/lib/openser/modules/registrar.so"
 
 # ----------------- setting module-specific parameters ---------------
 
 # -- usrloc params --
 
 modparam("usrloc", "db_url", "mysql://openser:openserrw@__mysql_server_address__/openser")
 
 # Uncomment this if you want to use SQL database
 # for persistent storage and comment the previous line
 modparam("usrloc", "db_mode", 3)
 
 # -------------------------  request routing logic -------------------
 
 # main routing logic
 
 route{
 
        # initial sanity checks -- too long messages
        if (msg:len >=  2048 ) {
                sl_send_reply("513", "Message too big");
                exit;
        };
 
        if (!uri==myself) {
                sl_send_reply("400", 
                      "Bad destination, only register messages destined for this server are accepted");
                exit;
        };
 
        # the only valid message for the registrar is the register message
        # other messages are answered with an error message
        if (uri==myself) {
 
                if (method=="REGISTER") {
 
                        sl_send_reply("100", "Trying");
 
                        if(!save("location")) {
                                sl_reply_error();
                        };
                        exit;
                } else {
                        sl_send_reply("403", "Forbidden");
                        exit;
                };
        };
 }


Adding minimal security


We now have a fully functional but extremely insecure network. We will add security so that messages will not be accepted from just any machine. In order to do so, we will add a few modules to each server: Authentication Interface module (AUTH), Database-backend authentication module (AUTH_DB) and URI operation with database support module (URI_DB). The idea is that your users are pre-recorded in the database and both REGISTER and INVITE messages are tested against the database to check if it comes from a valid user. For both the proxy and the registrar, you will need to add the following lines to load and configure the modules correctly:


 loadmodule "/usr/local/lib/openser/modules/auth.so"
 loadmodule "/usr/local/lib/openser/modules/auth_db.so"
 loadmodule "/usr/local/lib/openser/modules/uri_db.so"
 
 modparam("auth_db", "calculate_ha1", yes)
 
 #this line tells auth_db the name of the password column
 #(for the ha1 calculation)
 modparam("auth_db", "password_column", "password")


For the proxy we’ll want to modify the way INVITE messages are handled (this code replaces the if ( method==”REGISTER)):


 if (method=="ACK") {
         route(1);
         exit;
 } if (method=="INVITE") {
         route(3);11
         exit;
 } else if (method=="REGISTER") {
         route(2);
         exit;
 };


And add the corresponding route at the end of the code:


route[3] {
         # -----------------------------------------------------------------
         # INVITE Message Handler
         # -----------------------------------------------------------------
         if (!proxy_authorize("/*your domain name*/","subscriber")) {
                 proxy_challenge("/*your domain name*/ ","0");
                 exit;
         } else if (!check_from()) {
                 sl_send_reply("403", "Use From=ID");
                 break;
         };
         consume_credentials();
         lookup("aliases");
         if (uri!=myself) {
                 route(1);
                 exit;
         };
         if (!lookup("location")) {
                 sl_send_reply("404", "User Not Found");
                 exit;
         };
         route(1);
 }


And for the registrar you only need to add the following lines before the if(!save("location")):


 if (!www_authorize(" /*your domain name*/ ", "subscriber")) {
         www_challenge(" /*your domain name*/ ", "1");
         exit;
 };
 
 if (!check_to()) {
         sl_send_reply("401", "Unauthorized");
         exit;
 };
 
 consume_credentials();


It would of course also be useful to add tls support for greater security, but fortunately there’s already a good guide for that in the OpenSER documentation.

Credits


This tutorial was originally wrote by 'adoswald' to OpenSER web forum:

http://www.voipuser.org/forum_topic_8040.html
http://www.voipuser.org/forum_view_24.html

See also



Starting...


This tutorial is designed to help relative newbies (like myself) who wish to understand how exactly to install OpenSER in a slightly unconventional way, as well as understand the basics of OpenSER. The goal of this exercise is to install OpenSER on two PCs, each with a specific task, and have them interact with a MySQL server on an other machine. The design here is academic: one of the OpenSER PC’s will act as a simple stateful proxy, and the other will only act as a registrar.

On a side-note: all the information here is inferred from the scattered documentation and my own use of OpenSER. So it may not be accurate. If I got it wrong somewhere, feel free to tell me. The version this tutorial was based on is 1.1.0, with earlier and later versions of OpenSER there may be variations.

Most of the information in this document can be found elsewhere, but you’ll need to read several documents to put it all together: the SER getting started, a few topics in the OpenSER forums, the dokuwiki, the OpenSER modules and finally this useful beginner’s guide.

The pages on the website that explain how to download and install OpenSER are quite good, so make sure to consult them to have the appropriate libraries OpenSER depends on. In fact in this tutorial I won’t give the detail on how to download, but I will explain the installation. However if you have a problem installing with the .deb or the .tar.gz, don’t hesitate to download a stable version from the CVS!

How does OpenSER work?


If you want to do operations that differ from the usual, you might want to broadly understand the structure of OpenSER. Not the workings of the code (unless you want to do something REALLY special), but how it works once compiled. There’s basically two parts to OpenSER: the core, which is the working executable part, and the modules, which add functionality (especially SIP functionality) to the core.

The modules are by far the most important to give OpenSER its specific task. The useful part of the modules can be divided in two parts: the exported parameters, and the exported functions. These will both be important when it comes to setting up OpenSER with it’s configuration file: openser.cfg (normally located in /usr/local/etc/openser/). Basically the exported parameters will set up the modules to act as you wish, and the exported functions will allow you to program the handling of sip messages. You will also find that some modules depend on other modules to be able to work. For example the Registrar module depends both on the stateless replier module and the User location implementation module. The information about specific modules, as well as their parameters, functions and dependencies can be found here.

The core provides the framework for OpenSER. Whatever else you will find in the configuration file is part of the core (which has parameters, functions, and more – see documentation). Basically, the core parameters will affect local setting, such as debug level, the port to listen on, whether to run in daemon mode, etc… The core routing blocks and routing constructs provide the logical structures for the handling of the messages, and the core functions provides both instruction logic (such as exit()) and instructions for message manipulation (such as rewritehost()).

Setting up the network


For the network we would like to build here’s what we absolutely need:

  • Proxy: OpenSER core, Transaction module (TM) for stateful transactions, Stateless replier module (SL), Record-Route and Route module (RR), Max-Forward processor module (MAXFWD) and the User location implementation (USRLOC), SIP Registrar implementation (REGISTRAR) and MySQL-backend for database API (MYSQL) modules for database connectivity (more on this later).

  • Registrar: OpenSER core, Stateless replier module (SL), User location implementation module (USRLOC), SIP Registrar implementation module (REGISTRAR) and MySQL-backend for database API module (MYSQL).

  • Location service: MySQL server.

I’ll assume that you took my advice and downloaded OpenSER from the CVS. If you used binary packages and managed to get them to work, never fear, it won’t be a problem. Just skip the part about the OpenSER installation. If you really want to follow the rest of the tutorial, go to the directory where the modules are installed (.so files, they should be in /usr/local/lib/openser/) and delete or move (you may want them later) all module files that are not mentioned above.

Modular OpenSER servers installation


To fully understand what is happening, we’ll only install the strict minimum. In order to do this, we will only install those modules that we need and that I mentioned earlier. There’s several ways to achieve this, and here’s what I find the simplest:

Edit the Makefile, and at line 304 change this instruction:



Install: all mk-install-dirs install-cfg install-bin install-modules \
        install-doc install-man


To



Install: openser mk-install-dirs install-cfg install-bin install-modules \
        install-doc install-man


Now, making sure that you have super-user privileges, execute:


> make install


Now we have only the core installed, we’ll add the modules that we want to the installation. First, however, we’ll need to build them (make sure that you have the appropriate libraries installed):


> make include_module=”mysql” modules.


Now you simply need to copy the modules you want to the appropriate directory. If you followed my instructions up to here, it should be /usr/local/lib/openser/modules/. For the proxy you will be copying: tm.so, sl.so, rr.so, maxfwd.so, usrloc.so, registrar.so and mysql.so. For the registrar: sl.so, usrloc.so, registrar.so and mysql.so.

Setting up MySQL


I’ll assume that you managed to install MySQL on the PC destined to be a location server. What you now need is the script to install the necessary OpenSER database: openser_mysql.sh create. The script comes with OpenSER, so you may need to download it if only to get that file (feel free to delete it afterward though). When you run the script you will be prompted to enter your MySQL root password (just press ENTER you haven’t put one) and domain. As far as I can ascertain, this information is in fact mostly useless. If you have a domain, enter it here, otherwise put the IP address of the machine. As well as adding the necessary database and tables, the script will also add a read-only and read-write user:

  • read-only : user: openser password: openserro
  • read-write: user: openser password: openserrw.

These users can be either a local or a remote user (fortunately), and I recommend for security reasons that you change their default passwords. If you don’t know how to do this, you may find a MySQL tutorial on the web.

One fianl thing remains to be done before you can use the MySQL location service, and that’s to make it accessible remotely. You’ll need to change a line in /etc/mysql/my.cnf from


Bind-address     = localhost


to


Bind-address   =  __ip address you’ll be listening on__


Setting up OpenSER


To set up OpenSER you will need to modify two files: openser.cfg and openserctlrc.

Setting up openserctl

Modifying openserctlrc is simple, and is the same on both on the proxy and on the registrar. You will have :



 # $Id: openserctlrc,v 1.2 2006/07/05 19:37:20 miconda Exp $
 #
 # openser control tool resource file
 #
 # here you can set variables used in the openserctl
 
 ## your SIP domain
 SIP_DOMAIN= ''your domain…or ip of the pc with the location service''
 
 ## database type: MYSQL or PGSQL, by defaulte none is loaded
 DBENGINE=MYSQL
 
 ## database host
 DBHOST= ''ip of the machine with the location service''
 
 ## database name
 DBNAME=openser
 
 ## database read/write user
 DBRWUSER=openser
 
 ## database read only user
 DBROUSER=openserro
 
 ## password for database read only user
 DBROPW=openserro
 
 ## database super user
 DBROOTUSER="root"
 
 ## type of aliases used: DB - database aliases; UL - usrloc aliases
 ## - default: none
 ALIASES_TYPE="DB"
 
 ## control engine: FIFO or UNIXSOCK
 ## - default FIFO
 CTLENGINE="FIFO"
 
 ## path to FIFO file
 # OSER_FIFO="FIFO"
 
 ## check ACL names; default on (1); off (0)
 VERIFY_ACL=1
 
 ## ACL names - if VERIFY_ACL is set, only the ACL names from below list
 ## are accepted
 ACL_GROUPS="local ld int voicemail free-pstn"
 
 ## verbose - debug purposes - default '0'
 VERBOSE=1


This file is used by the openserctl utility for database manipulation. For the initial configuration this isn’t very useful, but we’ll be using it when we add security. The entries in lines from DBRWUSER to DBROOTUSER will depend on the configuration of your database (default values shown here).

For openser.cfg the file will be different for the proxy and the registrar, as they will treat messages differently.

Setting up the OpenSER proxy


The first part of the openser.cfg pertains to the local configuration, and we’ll basically skip over it. You will note that not all the default code needs to be replaced.


 #
 # $Id: openser.cfg,v 1.6.2.1 2006/07/17 15:51:03 klaus_darilion Exp $
 #
 # simple quick-start config script
 #
 
 # ----------- global configuration parameters ------------------------
 
 #Uncomment these lines to enter debugging mode
 debug=9            # debug level
 Fork=no
 Log_stderror=yes
   
 
 check_via=no    # (cmd. line: -v)
 dns=no          # (cmd. line: -r)
 rev_dns=no      # (cmd. line: -R)
 listen= ip this pc will listen on
 port=5060
 children=4
 fifo="/tmp/openser_fifo"



It gets interesting once we load the modules and set their parameters.


 # ------------------ module loading ----------------------------------
 
 # Uncomment this if you want to use SQL database
 loadmodule "/usr/local/lib/openser/modules/mysql.so"
 
 loadmodule "/usr/local/lib/openser/modules/sl.so"
 loadmodule "/usr/local/lib/openser/modules/tm.so"
 loadmodule "/usr/local/lib/openser/modules/rr.so"
 loadmodule "/usr/local/lib/openser/modules/maxfwd.so"
 loadmodule "/usr/local/lib/openser/modules/usrloc.so"
 
 loadmodule "/usr/local/lib/openser/modules/registrar.so"
 
 # ----------------- setting module-specific parameters ---------------
 
 # -- usrloc params --
 
 modparam("usrloc", "db_url", "mysql://openser:openserrw@__mysql_server_address__/openser")
 
 # Uncomment this if you want to use SQL database
 # for persistent storage and comment the previous line
 modparam("usrloc", "db_mode", 3)
 
 # -- rr params --
 # add value to ;lr param to make some broken UAs happy
 modparam("rr", "enable_full_lr", 1)


You may have been wondering why we use registrar.so while we do not want the proxy to double as registrar… The reason is that the functions to retrieve the location of a user from the database are unfortunately part of this module, so any server that needs to query the location service needs to load it.

As for the parameters, we tell usrloc where the database is situated, and that we do not want to keep a local table for the addresses, only the remote database (modparam("usrloc", "db_mode", 3)). The part of the file that pertains to the handling of messages will naturally reflect the use of a proxy.


 # -------------------------  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 (msg:len >=  2048 ) {
                sl_send_reply("513", "Message too big");
                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 (!method=="REGISTER")
                record_route();
 
        # subsequent messages withing a dialog should take the
        # path determined by record-routing
        if (loose_route()){
                route(1);
        };
 
        if (!uri==myself) {
                route(1);
        };
 
        # 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 (uri==myself) {
 
                if (method=="REGISTER") {
                        route(2);
                        exit;
                };
 
                lookup("aliases");
                if (!uri==myself) {
                        route(1);
                };
 
  #native SIP destinations are handled using our USRLOC DB
                if (!lookup("location")) {
                        sl_send_reply("404", "Not Found");
                        exit;
                };
        };
 
        route(1);
 }
 
 
 route[1] {
        # send it out now; use stateful forwarding as it works reliably
        # even for UDP2TCP
        if (!t_relay()) {
                sl_reply_error();
        };
        exit;
 }
 
 # route[2] will route REGISTER messages towards the registrar
 # No database connectivity is required here, as the registrar then sends the messages to the
 # location server
 route[2] {
        #rewrinting the host allows the registrar to know that the message is destined for it
        rewritehost("''registrar ip address''");
        if(!t_relay("udp: ''registrar ip address'':5060")) {
                sl_reply_error();
        };
        exit;
 }


Basically, the proxy merely routes (relays) the messages to the appropriate location, checking against the database if necessary. As you can see, the proxy also makes a few checks (and modifications) on the message and sends an error message if necessary.

Setting up the OpenSER registrar


The registrar is obviously simpler then the proxy server, as the only thing that needs to be done is accept the REGISTER request and record it in the database. As the beginning of the code is essentially the same, we’ll only check it from the addition of the modules:



 # ------------------ module loading ----------------------------------
 
 # Uncomment this if you want to use SQL database
 loadmodule "/usr/local/lib/openser/modules/mysql.so"
 
 loadmodule "/usr/local/lib/openser/modules/sl.so"
 loadmodule "/usr/local/lib/openser/modules/usrloc.so"
 loadmodule "/usr/local/lib/openser/modules/registrar.so"
 
 # ----------------- setting module-specific parameters ---------------
 
 # -- usrloc params --
 
 modparam("usrloc", "db_url", "mysql://openser:openserrw@__mysql_server_address__/openser")
 
 # Uncomment this if you want to use SQL database
 # for persistent storage and comment the previous line
 modparam("usrloc", "db_mode", 3)
 
 # -------------------------  request routing logic -------------------
 
 # main routing logic
 
 route{
 
        # initial sanity checks -- too long messages
        if (msg:len >=  2048 ) {
                sl_send_reply("513", "Message too big");
                exit;
        };
 
        if (!uri==myself) {
                sl_send_reply("400", 
                      "Bad destination, only register messages destined for this server are accepted");
                exit;
        };
 
        # the only valid message for the registrar is the register message
        # other messages are answered with an error message
        if (uri==myself) {
 
                if (method=="REGISTER") {
 
                        sl_send_reply("100", "Trying");
 
                        if(!save("location")) {
                                sl_reply_error();
                        };
                        exit;
                } else {
                        sl_send_reply("403", "Forbidden");
                        exit;
                };
        };
 }


Adding minimal security


We now have a fully functional but extremely insecure network. We will add security so that messages will not be accepted from just any machine. In order to do so, we will add a few modules to each server: Authentication Interface module (AUTH), Database-backend authentication module (AUTH_DB) and URI operation with database support module (URI_DB). The idea is that your users are pre-recorded in the database and both REGISTER and INVITE messages are tested against the database to check if it comes from a valid user. For both the proxy and the registrar, you will need to add the following lines to load and configure the modules correctly:


 loadmodule "/usr/local/lib/openser/modules/auth.so"
 loadmodule "/usr/local/lib/openser/modules/auth_db.so"
 loadmodule "/usr/local/lib/openser/modules/uri_db.so"
 
 modparam("auth_db", "calculate_ha1", yes)
 
 #this line tells auth_db the name of the password column
 #(for the ha1 calculation)
 modparam("auth_db", "password_column", "password")


For the proxy we’ll want to modify the way INVITE messages are handled (this code replaces the if ( method==”REGISTER)):


 if (method=="ACK") {
         route(1);
         exit;
 } if (method=="INVITE") {
         route(3);11
         exit;
 } else if (method=="REGISTER") {
         route(2);
         exit;
 };


And add the corresponding route at the end of the code:


route[3] {
         # -----------------------------------------------------------------
         # INVITE Message Handler
         # -----------------------------------------------------------------
         if (!proxy_authorize("/*your domain name*/","subscriber")) {
                 proxy_challenge("/*your domain name*/ ","0");
                 exit;
         } else if (!check_from()) {
                 sl_send_reply("403", "Use From=ID");
                 break;
         };
         consume_credentials();
         lookup("aliases");
         if (uri!=myself) {
                 route(1);
                 exit;
         };
         if (!lookup("location")) {
                 sl_send_reply("404", "User Not Found");
                 exit;
         };
         route(1);
 }


And for the registrar you only need to add the following lines before the if(!save("location")):


 if (!www_authorize(" /*your domain name*/ ", "subscriber")) {
         www_challenge(" /*your domain name*/ ", "1");
         exit;
 };
 
 if (!check_to()) {
         sl_send_reply("401", "Unauthorized");
         exit;
 };
 
 consume_credentials();


It would of course also be useful to add tls support for greater security, but fortunately there’s already a good guide for that in the OpenSER documentation.

Credits


This tutorial was originally wrote by 'adoswald' to OpenSER web forum:

http://www.voipuser.org/forum_topic_8040.html
http://www.voipuser.org/forum_view_24.html

See also



Created by: miconda, Last modification: Sat 03 of Feb, 2007 (20:35 UTC)
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+