Build your own SIP VoIP service with Kamailio, MediaProxy and Serweb

This tutorial will guide you through all the necessary steps to set up your own VoIP service with SIP support. Supported features include SIP phone registration, call routing to external VoIP services (for PSTN access), call forwarding (unconditional, on busy, unreachable, no response), automatic NAT traversal, web based self-configuration for users, call accounting, presence support and ENUM support.

Operating system installation

Install a standard installation of Debian 5.0 (Lenny). The exact steps are out of the scope of this document, but you can find a network installation CD image here and the installation manual here. After the operating system is up and running and you are able to access the Internet, you have to install some additional packages:

aptitude install tcsh sudo openssh-server ntp ntpdate cvs jed screen ngrep
aptitude install libapache2-mod-php5 mysql-client mysql-server libcurl3-gnutls
aptitude install libxmlrpc-c3 libnetfilter-conntrack1 python-application python-cjson
aptitude install python-gnutls python-twisted-names python-sqlobject python-mysqldb
aptitude install python-lxml python-twisted-web python-twisted-web2 python-xml
aptitude install php5-cgi php5 php5-cli php5-curl php5-dev php5-imap
aptitude install php5-memcache php5-mhash php5-mysql php5-xmlrpc
aptitude install debian-builder dpatch libmysqlclient15-dev libexpat1-dev libxml2-dev
aptitude install libpq-dev libradiusclient-ng-dev flex bison unixodbc-dev
aptitude install libxmlrpc-c3-dev libperl-dev libsnmp-dev libdb-dev xsltproc
aptitude install libconfuse-dev libldap2-dev libcurl4-gnutls-dev cdbs python-all-dev
aptitude install libnetfilter-conntrack-dev php-pear
aptitude install libpcre3-dev docbook-xml libpurple-dev

The time on your server has to be synchronized. NTP will not automatically synchronize the time if it is more than a couple of seconds off. Because of this we have to stop the NTP server, force the synchronization using ntpdate and restart the NTP server.

/etc/init.d/ntp stop
ntpdate pool.ntp.org
/etc/init.d/ntp start

Check that we are synchronized with at least one of the predefined NTP servers. The server we are synchronized to should have an asterisk prepended to its name:

# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ns1.amis.net    194.160.23.2     2 u  856 1024  377    0.473   -0.964   0.567
+ns2.amis.net    194.160.23.2     2 u   98 1024  377    3.162   -1.581   0.550
+ns3.amis.net    194.160.23.2     2 u  143 1024  377    2.220   -2.106   0.549
#

Installing Kamailio and MediaProxy

Download Kamailio, build the Debian packages for it and install the resulting *.deb files:

wget http://www.kamailio.org/pub/kamailio/1.5.1/src/kamailio-1.5.1-tls_src.tar.gz
tar xzvf kamailio-1.5.1-tls_src.tar.gz
cd kamailio-1.5.1-tls
# edit packaging/debian/changelog and change version from 1.5.0 to 1.5.1
make deb
cd ..
dpkg -i kamailio_*.deb kamailio-mysql-module_*.deb kamailio-presence-modules_*.deb kamailio-xmlrpc-module_*.deb kamailio-regex-modules_*.deb kamailio-radius-module_*.deb

Download MediaProxy from here. Only version 2.3.2 is supported, because later versions require a newer python-applications package that is not available on Debian Lenny. Next, build Debian packages and install them:

tar xzvf mediaproxy-2.3.2.tar.gz
cd mediaproxy-2.3.2
dpkg-buildpackage
cd ..
dpkg -i mediaproxy*.deb

Next, create the MySQL database for Kamailio:

# kamdbctl create kamailio
MySQL password for root:
INFO: test server charset
INFO: creating database kamailio ...
INFO: Core Kamailio tables succesfully created.
Install presence related tables? (y/n): y
INFO: creating presence tables into kamailio ...
INFO: Presence tables succesfully created.
Install tables for imc cpl siptrace domainpolicy carrierroute userblacklist htable
purple? (y/n): y
INFO: creating extra tables into kamailio ...
INFO: Extra tables succesfully created.
#

Kamalio has dropped support for Serweb, so we need to modify some existing tables and add some new tables needed for Serweb manually. Logon to MySQL and connect to kamailio database:

mysql --user=root -p kamailio

Next, execute the following SQL commands:

ALTER table `acc`
  ADD `caller_uuid` varchar(32) NOT NULL default '',
  ADD `callee_uuid` varchar(32) NOT NULL default '',
  ADD `from_uri` varchar(128) default NULL,
  ADD `sip_from` varchar(128) default NULL,
  ADD `to_uri` varchar(128) default NULL,
  ADD `sip_to` varchar(128) default NULL,
  ADD `src_leg` varchar(128) default NULL,
  ADD `dst_leg` varchar(128) default NULL,
  ADD `username` varchar(64) default NULL,
  ADD `domain` varchar(64) default NULL,
  ADD `caller_deleted` enum('0','1') default '0',
  ADD `callee_deleted` enum('0','1') default '0';
DROP TABLE IF EXISTS `missed_calls`;
CREATE TABLE `missed_calls` LIKE `acc`;
ALTER TABLE subscriber
  ADD `first_name` varchar(64) NOT NULL default '',
  ADD `last_name` varchar(64) NOT NULL default '',
  ADD `datetime_created` datetime NOT NULL default '1900-01-01 00:00:01',
  ADD `datetime_modified` datetime NOT NULL default '0000-00-00 00:00:00',
  ADD `timezone` varchar(64) default NULL,
  ADD `phplib_id` varchar(32) NOT NULL default '',
  ADD `phone` varchar(15) NOT NULL default '',
  ADD `confirmation` varchar(64) NOT NULL default '',
  ADD `flag` char(1) NOT NULL default 'o',
  ADD `sendnotification` varchar(50) NOT NULL default '',
  ADD `greeting` varchar(50) NOT NULL default '',
  ADD `allow_find` char(1) NOT NULL default '0',
  ADD UNIQUE KEY `phplib_id` (`phplib_id`);
DROP TABLE IF EXISTS `pending`;
CREATE TABLE `pending` LIKE `subscriber`;
DROP TABLE IF EXISTS `active_sessions`;
CREATE TABLE `active_sessions` (
  `sid` varchar(32) NOT NULL default '',
  `name` varchar(32) NOT NULL default '',
  `val` text,
  `changed` varchar(14) NOT NULL default '',
  PRIMARY KEY  (`name`,`sid`),
  KEY `changed` (`changed`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `admin_privileges`;
CREATE TABLE `admin_privileges` (
  `username` varchar(64) NOT NULL default '',
  `domain` varchar(64) NOT NULL default '',
  `priv_name` varchar(64) NOT NULL default '',
  `priv_value` varchar(64) NOT NULL default '',
  PRIMARY KEY  (`username`,`priv_name`,`priv_value`,`domain`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `phonebook`;
CREATE TABLE `phonebook` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `username` varchar(64) NOT NULL default '',
  `domain` varchar(64) NOT NULL default '',
  `fname` varchar(32) NOT NULL default '',
  `lname` varchar(32) NOT NULL default '',
  `sip_uri` varchar(64) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `server_monitoring`;
CREATE TABLE `server_monitoring` (
  `id` int(10) unsigned NOT NULL default '0',
  `time` datetime NOT NULL default '1900-01-01 00:00:01',
  `param` varchar(32) NOT NULL default '',
  `value` int(10) NOT NULL default '0',
  `increment` int(10) NOT NULL default '0',
  PRIMARY KEY  (`id`,`param`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE IF EXISTS `server_monitoring_agg`;
CREATE TABLE `server_monitoring_agg` (
  `param` varchar(32) NOT NULL default '',
  `s_value` int(10) NOT NULL default '0',
  `s_increment` int(10) NOT NULL default '0',
  `last_aggregated_increment` int(10) NOT NULL default '0',
  `av` float NOT NULL default '0',
  `mv` int(10) NOT NULL default '0',
  `ad` float NOT NULL default '0',
  `lv` int(10) NOT NULL default '0',
  `min_val` int(10) NOT NULL default '0',
  `max_val` int(10) NOT NULL default '0',
  `min_inc` int(10) NOT NULL default '0',
  `max_inc` int(10) NOT NULL default '0',
  `lastupdate` datetime NOT NULL default '1900-01-01 00:00:01',
  PRIMARY KEY  (`param`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DROP TABLE IF EXISTS `usr_preferences_types`;
CREATE TABLE `usr_preferences_types` (
  `att_name` varchar(32) NOT NULL default '',
  `att_rich_type` varchar(32) NOT NULL default 'string',
  `att_raw_type` int(11) NOT NULL default '2',
  `att_type_spec` text NOT NULL,
  `default_value` varchar(100) NOT NULL default '',
  PRIMARY KEY  (`att_name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `usr_preferences_types` VALUES ('cfu','sip_adr',2,'',''),
  ('cfb','sip_adr',2,'',''),('cfnr','sip_adr',2,'',''),('clir','boolean',1,'','0');
INSERT INTO `version` VALUES ('pending',6),('phonebook',1),('usr_preferences_types',1),
  ('server_monitoring',1),('server_monitoring_agg',1),('admin_privileges',1);

Let’s do some initial configuration of Kamailio. We will create an account for the admin user and also add the domain our SIP server will be running under. Execute the following SQL commands, replacing sip.example.com with the name your SIP server should be operating under:

INSERT INTO `subscriber` VALUES
  (1,'admin','sip.example.com','admin','root@localhost',
  '34a96729c3802381f80bf0f652fc42b9','6e5eb03088d033a8372b6ad7bfec052c',
  NULL,'Initial','Admin',NOW(),'0000-00-00 00:00:00',NULL,
  '6b19c8e047095913592230aed298a4c7','123','57DaSIPuCm52UNe54LF545750cfdL48OMZfroM53',
  'o','','','0');
INSERT INTO `admin_privileges` VALUES ('admin','sip.example.com','change_privileges','1'),
  ('admin','sip.example.com','is_admin','1');
INSERT INTO `domain` VALUES (1,'sip.example.com',NOW());

Edit the file /etc/default/kamailio and change the variable RUN_KAMAILIO to yes. Edit the file /etc/mediaproxy/config.ini and set dispatchers to 127.0.0.1:

dispatchers = 127.0.0.1

Edit /etc/sysctl.conf and set net.ipv4.ip_forward to 1:

net.ipv4.ip_forward=1

If you don’t want to reboot your server at this point, you can manually set net.ipv4.ip_forward to 1 by executing the following command:

sysctl net.ipv4.ip_forward=1

Next, start up MediaProxy and Kamailio:

/etc/init.d/mediaproxy-dispatcher start
/etc/init.d/mediaproxy-relay start
/etc/init.d/kamailio start

At this point your SIP server is up and running. You should be able to configure your SIP phone with the DNS name of your server (sip.example.com in our case) and logon using username “admin” and password “admin”. If this works, you can proceed to the installation of Serweb, the web administration tool.

Installing SerwebSerweb needs some Perl modules, which we will install first:

pear install DB
pear install XML_RPC

It also depends on Runkit, which unfortunately has to be built manually, because the version in the Pear repository is out of date. We will create a temporary build directory, checkout Runkit from the CVS repository, then build and install it:

mkdir temp
cd temp
cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/runkit
cd pecl/runkit
phpize
./configure
make
cp modules/runkit.so /usr/lib/php5/20060613+lfs/

We have to enable the Runkit module in PHP by creating the file /etc/php5/conf.d/runkit.ini with the following contents:

extension=runkit.so

Also create a file called /etc/apache2/conf.d/serweb with the following contents:

Alias /serweb "/home/blaz/serweb/html"

Reload the configuration of the Apache server:

/etc/init.d/apache2 reload

At this point you should be all set. Point your browser at http://sip.example.com/serweb/admin (of course replace sip.example.com with the name of your server) and you should see the Serweb administration page.

Related Posts