Operation of a SIP server is not always an easy task. Server administrators face many challenges of broken or misconfigured user agents, network and host failures, hostile attacks and other stress-makers. All such situations may lead to an operational failure. It is sometimes very difficult to figure out the root reason of a failure, particularly in a distributed environment with many SIP components involved. In this section, we share some of our practices and refer to tools which have proven to make the life of administrators easier.
| 4.6.1.1.1. | Message logging. |
Frequently, operational errors are discovered or reported with a delay. Users frustrated by an error frequently approach administrators and scream "even though my SIP requests were absolutely OK yesterday, they were mistakenly denied by your server". If administrators do not record all SIP traffic at their site, they will not be able to identify the reason of the problem. We thus recommend that site operators record all messages passing their site and keep them stored for some period of time. They may use utilities such as ngrep or tcpdump . | |
| 4.6.1.1.2. | Real-time Traffic Watching. |
Looking at SIP messages in real-time may help to gain understanding of problems. Though there are commercial tools available, using a simple, text-oriented tool such as ngrep is sufficient for the job, thanks to SIP's textual nature. Example 4.1. Using ngrep In this example, all messages at port 5060 which include the string “bkraegelin” are captured and displayed. [jiri@fox s]$ ngrep bkraegelin@ port 5060 interface: eth0 (195.37.77.96/255.255.255.240) filter: ip and ( port 5060 ) match: bkraegelin@ # U +0.000000 153.96.14.162:50240 -> 195.37.77.101:5060 REGISTER sip:iptel.org SIP/2.0. Via: SIP/2.0/UDP 153.96.14.162:5060. From: sip:bkraegelin@iptel.org. To: sip:bkraegelin@iptel.org. Call-ID: 0009b7aa-1249b554-6407d246-72d2450a@153.96.14.162. Date: Thu, 26 Sep 2002 22:03:55 GMT. CSeq: 101 REGISTER. Expires: 10. Content-Length: 0. . # U +0.000406 195.37.77.101:5060 -> 153.96.14.162:5060 SIP/2.0 401 Unauthorized. Via: SIP/2.0/UDP 153.96.14.162:5060. From: sip:bkraegelin@iptel.org. To: sip:bkraegelin@iptel.org. Call-ID: 0009b7aa-1249b554-6407d246-72d2450a@153.96.14.162. CSeq: 101 REGISTER. WWW-Authenticate: Digest realm="iptel.org", \ nonce="3d9385170000000043acbf6ba...", algorithm=MD5. Server: Sip EXpress router(0.8.8 (i386/linux)). Content-Length: 0. Warning: 392 127.0.0.1:5060 "Noisy feedback tells: pid=31604 ". | |
| 4.6.1.1.3. | Tracing Errors in Server Chains. |
A request may pass any number of proxy servers on its path to its destination. If an error occurs in the chain, it is difficult for upstream troubleshooters and/or users complaining to administrators to learn more about error circumstances. A nice utility for debugging server chains is sipsak, SIP Swiss Army Knife, traceroute-like tool for SIP developed at iptel.org. It allows you to send OPTIONS request with low, increasing Max-Forwards header-fields and follow how it propagates in SIP network. See its webpage at http://sipsak.berlios.de/ . Example 4.2. Use of SIPSak for Learning SIP Path [jiri@bat sipsak]$ ./sipsak -T -s sip:7271@iptel.org warning: IP extract from warning activated to be more informational 0: 127.0.0.1 (0.456 ms) SIP/2.0 483 Too Many Hops 1: ?? (31.657 ms) SIP/2.0 200 OK without Contact header Note that in this example, the second hop server does not issue any warning header fields in replies and it is thus impossible to display its IP address in SIPsak's output. | |
| 4.6.1.1.4. | Server Status Monitoring. |
It is essential for solid operation to monitor server status continuously. We've been using two tools for this purpose. Sipsak does a great job of “pinging” a server, which may be used for alerting administrators of unresponsive servers. Monit is a server watching utility which alerts administrators when a server dies. | |
| 4.6.1.1.5. | Dealing with DNS. |
The SIP standard leverages DNS. Administrators of SIP servers should be aware of the impact of DNS on server's operation. A server's attempt to resolve an unresolvable address may block a server's process for a duration in the order of seconds. To be safer that the server does not stop responding due to being blocked by DNS resolving, we recommend the following practices:
|
SIP Express Router (SER) is an industrial-strength, free VoIP server based on the Session Initiation Protocol (SIP, RFC3261). It is engineered to power IP telephony infrastructures up to large scale. The server keeps track of users, sets up VoIP sessions, relays instant messages and creates space for new plug-in applications. Its proven interoperability guarantees seamless integration with components from other vendors, eliminating the risk of a single-vendor trap. It has successfully participated in various interoperability tests along with products of other leading SIP vendors.
SIP Express Router is available for download from BerliOS
The newest release can be found in the folder /latest.
The following architectures are supported by SER:
(For other architectures the Makefiles might need to be edited) There are various configuration options defined in the Makefile and Makefile.defs.
Example:
/root>rpm -i ser-08.11-1.i386.rpm
Packages for other popular distributions are available, and can be installed using the appropriate package manager for that distribution.
On many platforms you can start the ser service using:
/etc/init.d/ser start
RedHat based systems will use:
/etc/rc.d/init.d/ser start
That will start the server with the default configuration. You can try to register your SIP user agent (for example MS Messenger) with the server, place first calls as well as send instant messages to other users registered with this server.
The default configuration is very limited, its purpose is to allow to start the server easily and to test the basic functionality. The default configuration does not include authentication, the persistence of the user location database and many other important features.
To install support for a MySQL database you will need to download the package ser-mysql, which is available from the same location from which you downloaded SIP Express Router. This package contains scripts to create the required database and establish permissions for preconfigured accounts. A recent release of MySQL is recommended, you should definitely use version higher than 4.0. Earlier versions may have problems with the syntax required to set permissions in the database.
If you do not already have a copy of MySQL installed, download it from http://www.mysql.com or check out your linux distribution. Many popular linux distribution come with the MySQL server pre-packaged.
Once you have the MySQL server installed and running, execute
/usr/sbin/ser_mysql.sh create
That will create database “ser” and all the tables that are required by SER.
You can verify that the database has been created, and correct permissions assigned by using the MySQL management tool and these steps:
Mysql> select * from user; | Host | User | Password | Select_priv | ... | % | ser | 4e633cf914a735a0 | N | ... | localhost | ser | 4e633cf914a735a0 | Y | ... | % | serro | 7cb73a267cb7bd5f | N | ... | localhost | serro | 7cb73a267cb7bd5f | Y | ...
The above results show that the two users, ser and serro, have been created and granted the permissions needed to access the database. Note that in the above example the permissions have been modified to deny access to these accounts from any system(%) other than the local host.
mysql> connect ser; Connection id: 294 Current database: ser mysql> show tables; +-----------------+ | Tables_in_ser | +-----------------+ | acc | | active_sessions | | aliases | | config | | event | | grp | | location | | missed_calls | | pending | | phonebook | | reserved | | silo | | subscriber | | version | +-----------------+ 14 rows in set (0.00 sec) mysql> select * from subscriber; | phplib_id | USERNAME | PASSWORD | FIRST_NAME | ... | 4cefa7a4d3c8c2dbf6328520bd873a19 | admin | heslo | first | ...
The previous query shows that you have one user account defined and it has administrator privileges. Users with administrator privileges will be allowed to user the admin interface of Serweb.
We will need to add another account to be the administrator for your realm. We will do that later.
This section demonstrates simple examples on how to configure the server's behaviour using the SER request routing language. All configuration scripts follow the SER language syntax, which dictates the following section ordering:
Module loading: these statements link external modules, such as transaction management (tm) or stateless UA server (sl) dynamically.
If modules depend on each other, then the depending modules must be loaded after modules on which they depend. We recommend to load first modules tm and sl because many other modules (auth, usrloc, acc, etc.) depend on them.
The configuration script, ser.cfg, is a part of every SER distribution and defines default behaviour of the server. It allows users to register with the server and have requests proxied to other users registered at the same server as well as to other SIP servers.
After performing routine checks, the script looks whether an incoming request is for the served domain (administrative domain). If this is true and the request is “REGISTER”, SER acts as a SIP registrar and updates the user location database. Optionally, it verifies user's identity first to avoid unauthorized contact manipulation.
Non-REGISTER requests for served domains are then processed using the user location database. If a contact is found for a Requested-URI, script execution proceeds to stateful forwarding, a negative 404 reply is generated otherwise. Requests targeted outside the served domain are always statefuly forwarded.
Note that the default configuration settings as set by this simple script have several limitations:
Example 4.3. Default Configuration Script
#
# simple quick-start config script
#
# ----------- global configuration parameters ------------------------
debug=3 # debug level (cmd line: -dddddddddd)
fork=yes
log_stderror=no # (cmd line: -E)
/* Uncomment these lines to enter debugging mode
fork=no
log_stderror=yes
*/
check_via=no # (cmd. line: -v)
dns=no # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
port=5060
children=4
fifo="/tmp/ser_fifo"
# ------------------ module loading ----------------------------------
# Uncomment this if you want to use SQL database
#loadmodule "/usr/local/lib/ser/modules/mysql.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
# Uncomment this if you want digest authentication
# mysql.so must be loaded !
#loadmodule "/usr/local/lib/ser/modules/auth.so"
#loadmodule "/usr/local/lib/ser/modules/auth_db.so"
# ----------------- setting module-specific parameters ---------------
# -- usrloc params --
modparam("usrloc", "db_mode", 0)
# Uncomment this if you want to use SQL database
# for persistent storage and comment the previous line
#modparam("usrloc", "db_mode", 2)
# -- auth params --
# Uncomment if you are using auth module
#
#modparam("auth_db", "calculate_ha1", yes)
#
# If you set "calculate_ha1" parameter to yes (which true in this config),
# uncomment also the following parameter)
#
#modparam("auth_db", "password_column", "password")
# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)
# ------------------------- 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");
break;
};
if (msg:len >= max_len ) {
sl_send_reply("513", "Message too big");
break;
};
# 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()) {
# mark routing logic in request
append_hf("P-hint: rr-enforced\r\n");
route(1);
break;
};
if (!uri==myself) {
# mark routing logic in request
append_hf("P-hint: outbound\r\n");
route(1);
break;
};
# 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") {
# Uncomment this if you want to use digest authentication
# if (!www_authorize("iptel.org", "subscriber")) {
# www_challenge("iptel.org", "0");
# break;
# };
save("location");
break;
};
lookup("aliases");
if (!uri==myself) {
append_hf("P-hint: outbound alias\r\n");
route(1);
break;
};
# native SIP destinations are handled using our USRLOC DB
if (!lookup("location")) {
sl_send_reply("404", "Not Found");
break;
};
};
append_hf("P-hint: usrloc applied\r\n");
route(1);
}
route[1]
{
# send it out now; use stateful forwarding as it works reliably
# even for UDP2TCP
if (!t_relay()) {
sl_reply_error();
};
}
The redirect example shows how to redirect a request to multiple destinations using a 3xx reply. Redirecting requests as opposed to proxying them is essential to various scalability scenarios. Once a message is redirected, SER discards all related state information and is no more involved in subsequent SIP transactions (unless the redirection addresses point to the same server again).
The key SER actions in this example are append_branch and sl_send_reply (sl module).
The append_branch action adds a new item to the destination set. The destination set always includes the current URI. The sl_send_reply action, if passed SIP reply code 3xx, takes all values in the current destination set and adds them to the “Contact” header field in the reply.
Example 4.4. Redirect Server
#
# this example shows use of ser as stateless redirect server
#
# ------------------ module loading ----------------------------------
loadmodule "modules/sl/sl.so"
# ------------------------- request routing logic -------------------
# main routing logic
route{
# for testing purposes, simply okay all REGISTERs
if (method=="REGISTER") {
log("REGISTER");
sl_send_reply("200", "ok");
break;
};
# rewrite current URI, which is always part of destination ser
rewriteuri("sip:parallel@iptel.org:9");
# append one more URI to the destination ser
append_branch("sip:redirect@iptel.org:9");
# redirect now
sl_send_reply("300", "Redirect");
}
Many services depend on the status of messages relayed downstream: forward on busy and forward on no reply to name the two most well-known. To support implementation of such services, SER allows to return to request processing when forwarding of a request fails. When a request is reprocessed, new request branches may be initiated or the transaction can be completed at the discretion of the script writer.
The primitives used are t_on_failure(r) and failure_route[r]{}. If t_on_failure action is called before a request is statefuly forwarded and a forwarding failure occurs, SER will return to request processing in a failure_route block. Failures include: receipt of a SIP error (status code >= 300 ) from downstream and the absence of a final reply within the final response period.
The duration of the timer is governed by parameters of the tm module. fr_timer is the duration of the timer set for non-INVITE transactions and INVITE transactions for which no provisional response is received. If the timer hits, it indicates that a downstream server is unresponsive. fr_inv_timer governs time to wait for a final reply for an INVITE. It is typically longer than fr_timer because final reply may take a long time until the callee (finds a mobile phone in his pocket and) answers the call.
In Example 4.5, failure_route[1] is set to be entered on error using the t_on_failure(1) action. Within this reply block, SER is instructed to initiate a new branch and try to reach the called party at another destination (sip:nonsense@iptel.org). To deal with the case when none of the alternate destinations succeed, t_on_failure is set again. If this case really occurs, failure_route[2] is entered and a last resort destination (sip:foo@iptel.org) is tried.
Example 4.5. On-Reply Processing
#
# example script showing both types of forking;
# incoming message is forked in parallel to
# 'nobody' and 'parallel', if no positive reply
# appears with final_response timer, nonsense
# is retried (serial forking); than, destination
# 'foo' is given last chance
# ------------------ module loading ----------------------------------
loadmodule "modules/sl/sl.so"
loadmodule "modules/tm/tm.so"
# ----------------- setting module-specific parameters ---------------
# -- tm params --
# set time for which ser will be waiting for a final response;
# fr_inv_timer sets value for INVITE transactions, fr_timer
# for all others
modparam("tm", "fr_inv_timer", 15 )
modparam("tm", "fr_timer", 10 )
# ------------------------- request routing logic -------------------
# main routing logic
route{
# for testing purposes, simply okay all REGISTERs
if (method=="REGISTER") {
log("REGISTER");
sl_send_reply("200", "ok");
break;
};
# try these two destinations first in parallel; the second
# destination is targeted to sink port -- that will make ser
# wait until timer hits
seturi("sip:nobody@iptel.org");
append_branch("sip:parallel@iptel.org:9");
# if we do not get a positive reply, continue at reply_route[1]
t_on_failure("1");
# forward the request to all destinations in destination set now
t_relay();
}
failure_route[1] {
# forwarding failed -- try again at another destination
append_branch("sip:nonsense@iptel.org");
log(1,"first redirection\n");
# if this alternative destination fails too, proceed to ...
t_on_failure("2");
t_relay();
}
failure_route[2] {
# try out the last resort destination
append_branch("sip:foo@iptel.org");
log(1, "second redirection\n");
# we no more call t_on_negative here; if this destination
# fails too, transaction will complete
t_relay();
}
In some scenarios, like termination of calls in the PSTN, SIP administrators may wish to keep track of placed calls. SER can be configured to report on completed transactions. Reports are sent by default to syslog facility. Support for RADIUS and MySQL accounting exists as well.
Note that SER is by no means call-stateful. It reports on completed transactions, i.e., after a successful call set up is reported, it drops any call-related state. When a call is terminated, a transactional state for the BYE request is created and forgotten again after the transaction completes. This is a feature and not a bug -- keeping the state information during transactions only allows to achieve significantly higher scalability. It is then up to the accounting application to correlate call initiation and termination events.
To enable call accounting, tm and acc modules need to be loaded, requests need to be processed statefuly and labeled for accounting. This means that if you want a transaction to be reported, the initial request must have taken the path "setflag(X), t_relay" in the SER script. X must have the value configured in the acc_flag configuration option.
Also note, that by default only transactions that initiate a SIP dialog (typically INVITE) visit a proxy server. Subsequent transactions are exchanged directly between end-devices, do not visit proxy server and cannot be reported. To be able to report on subsequent transactions, you need to force them to visit the proxy server by turning record routing on.
Example 4.6. Configuration with Enabled Accounting
#
# example: accounting calls to numerical destinations
#
# ------------------ module loading ----------------------------------
loadmodule "modules/tm/tm.so"
loadmodule "modules/acc/acc.so"
loadmodule "modules/sl/sl.so"
loadmodule "modules/maxfwd/maxfwd.so"
loadmodule "modules/rr/rr.so"
# ----------------- setting module-specific parameters ---------------
# -- acc params --
# set the reporting log level
modparam("acc", "log_level", 1)
# number of flag, which will be used for accounting; if a message is
# labeled with this flag, its completion status will be reported
modparam("acc", "log_flag", 1 )
# ------------------------- request routing logic -------------------
# main routing logic
route{
/* ********* ROUTINE CHECKS ********************************** */
# filter too old messages
if (!mf_process_maxfwd_header("10")) {
log("LOG: Too many hops\n");
sl_send_reply("483","Too Many Hops");
break;
};
if (len_gt( max_len )) {
sl_send_reply("513", "Wow -- Message too large");
break;
};
# Process record-routing
if (loose_route()) { t_relay(); break; };
# labeled all transaction for accounting
setflag(1);
# record-route INVITES to make sure BYEs will visit our server too
if (method=="INVITE") record_route();
# forward the request statefuly now; (we need *stateful* forwarding,
# because the stateful mode correlates requests with replies and
# drops retransmissions; otherwise, we would have to report on
# every single message received)
if (!t_relay()) {
sl_reply_error();
break;
};
}
SER can report missed calls via the syslog facility or to MySQL. Mysql reporting can be utilized by SER's complementary web interface, Serweb.
Reporting of missed calls is enabled by the acc module. There are two cases, on which you want to report. The first case is when a callee is offline. The other case is when a user is online, but call establishment fails. There may be many failure reasons (call cancellation, inactive phone, busy phone, server timer, etc.), all of them leading to a negative (>=300) reply sent to the caller. The acc module can be configured to issue a missed-call report whenever a transaction completes with a negative status.
The following configuration fragment reports a missed call in both cases. The top half of the condition reports on calls missed due to offline callee status, using the acc_request action. The action is wrapped in transactional processing (t_newtran) to guarantee that reports are not duplicated on receipt of retransmissions.
The bottom half of the condition marks transactions to online users in order to be reported on failure. That is what the setflag(3) action is responsible for, along with the configuration option log_missed_flag. This option configures SER to report on all transactions, which were marked with flag 3.
loadmodule("modules/tm/tm.so");
loadmodule("modules/acc/acc.so");
....
# if a call is labeled using setflag(3) and is missed, it will
# be reported
...
modparam("acc", "log_missed_flag", 3 );
if (!lookup("location")) {
# call invitations to off-line users are reported using the
# acc_request action; to avoid duplicate reports on request
# retransmissions, request is processed statefuly (t_newtran,
# t_reply)
if ((method=="INVITE" || method=="ACK") && t_newtran() ) {
t_reply("404", "Not Found");
acc_request("404 Not Found");
break;
};
# all other requests to off-line users are simply replied
# statelessly and no reports are issued
sl_send_reply("404", "Not Found");
break;
} else {
# user on-line; report on failed transactions; mark the
# transaction for reporting using the same number as
# configured above; if the call is really missed, a report
# will be issued
setflag(3);
# forward to user's current destination
t_relay();
break;
};
Frequently, it is desirable for a user to have multiple addresses in a domain. For example, a user with username “john.doe” wants to be reachable at a shorter address “john” or at a numerical address “12335”, so that PSTN callers with numeric-only key-pads can reach him as well.
With SER, you can maintain a special user location table and translate existing aliases to canonical usernames using the lookup action from the usrloc module. The following script fragment demonstrates the use of lookup for this purpose.
Example 4.7. Configuration of Use of Aliases
if (!uri==myself) { # request not for our domain...
route(1); # go somewhere else, where outbound requests are processed
break;
};
# the request is for our domain -- process registrations first
if (method=="REGISTER") { route(3); break; };
# look now, if there is an alias in the "aliases" table; do not care
# about return value: whether there is some or not, move ahead then
lookup("aliases");
# there may be aliases which translate to other domain and for which
# local processing is not appropriate; check again, if after the
# alias translation, the request is still for us
if (!uri==myself) { route(1); break; };
# continue with processing for our domain...
...
The table with aliases is updated using the serctl tool. The command serctl alias add <alias> <uri> adds a new alias, the command serctl alias show <user> prints an existing alias, and the command serctl alias rm <user> removes it.
[jiri@cat sip_router]$ serctl alias add 1234 sip:john.doe@foo.bar
sip:john.doe@foo.bar
200 Added to table
('1234','sip:john.doe@foo.bar') to 'aliases'
[jiri@cat sip_router]$ serctl alias add john sip:john.doe@foo.bar
sip:john.doe@foo.bar
200 Added to table
('john','sip:john.doe@foo.bar') to 'aliases'
[jiri@cat sip_router]$ serctl alias show john
<sip:john.doe@foo.bar>;q=1.00;expires=1073741811
[jiri@cat sip_router]$ serctl alias rm john
200 user (aliases, john) deleted
Note that the persistence of records needs to be turned on in the usrloc module. All changes to aliases would be otherwise lost on server reboot. To enable the persistence, set the db_mode usrloc parameter to a non-zero value.
# ....load module ...
loadmodule "modules/usrloc/usrloc.so"
# ... turn on persistence -- all changes to user tables are immediately
# flushed to mysql
modparam("usrloc", "db_mode", 1)
# the SQL address:
modparam("usrloc", "db_url","mysql://ser:secret@dbhost/ser")
There are two tasks related to the management of SIP users: maintaining user accounts and maintaining user contacts. Both these jobs can be done using the serctl command-line tool. The complimentary web interface, Serweb, can be used for this purpose as well.
If user authentication is turned on, which is highly advisable, user accounts must be created before users can log in. To create a new user account, use the serctl add utility with the username, password and email as parameters. It is important that the environment variable SIP_DOMAIN is set to your domain and matches the realm values used in your script. The realm value is used for calculation of credentials stored in the subscriber database, which are bound permanently to this value.
[jiri@cat gen_ha1]$ export SIP_DOMAIN=foo.bar [jiri@cat gen_ha1]$ serctl add newuser secret newuser@foo.bar MySql Password: new user added
serctl can also change the user's password or remove existing accounts from the system permanently.
[jiri@cat gen_ha1]$ serctl passwd newuser newpassword MySql Password: password change succeeded [jiri@cat gen_ha1]$ serctl rm newuser MySql Password: user removed
User contacts are typically automatically uploaded by SIP phones to the server during the registration process and administrators do not need to worry about them. However, users may wish to append permanent contacts to PSTN gateways or to locations in other administrative domains. To manipulate the contacts in such cases, use the serctl ul tool. Note that this is the only correct way to update contacts -- direct changes of the back-end MySQL database do not affect server's memory. Also note, that if persistence is turned off (usrloc “db_mode” parameter set to “0”), all contacts will be lost on server reboot. Make sure that the persistence is enabled if you add permanent contacts.
To add a new permanent contact for a user, call serctl ul add <username> <contact>. To delete all user's contacts, call serctl ul rm <username>. The command serctl ul show <username> prints all current contacts of this user.
[jiri@cat gen_ha1]$ serctl ul add newuser sip:666@gateway.foo.bar
sip:666@gateway.foo.bar
200 Added to table
('newuser','sip:666@gateway.foo.bar') to 'location'
[jiri@cat gen_ha1]$ serctl ul show newuser
<sip:666@gateway.foo.bar>;q=1.00;expires=1073741812
[jiri@cat gen_ha1]$ serctl ul rm newuser
200 user (location, newuser) deleted
[jiri@cat gen_ha1]$ serctl ul show newuser
404 Username newuser in table location not found
It is often important to exercise some sort of access control. A typical case is when SER is used to guard a PSTN gateway. If a gateway could not be well guarded, unauthorized users would be able to use it to make calls to the PSTN, inflicting high costs.
There are few issues you need to understand when configuring SER for this purpose. First, if a gateway is built or configured to accept calls from anywhere, callers may easily bypass your access control server and communicate with the gateway directly. You then need to enforce at transport layer that signaling is only accepted if coming via SER and deny SIP packets coming from other hosts and port numbers. Your network must be configured not to allow forged IP addresses. Also, you need to turn on record routing to assure that all session requests will travel via SER. Otherwise, caller's devices would send subsequent SIP requests directly to your gateway, which would fail because of transport filtering.
Authorization (i.e., the process of determining who may call where) is facilitated in SER using the group membership concept. Scripts make decisions on whether a caller is authorized to make a call to a specific destination based on the user's membership in a group. For example, a policy may be set up to allow calls to international destinations only to users, who are members of “int” group. Before user's group membership is checked, his identity must be verified. Without cryptographic verification of the user's identity, it would be impossible to confirm that a caller really is who he claims to be.
The following script demonstrates, how to configure SER as an access control server for a PSTN gateway. The script verifies user identity using digest authentication, checks user's privileges, and forces all requests to visit the server.
Example 4.8. Script for Gateway Access Control
loadmodule "modules/sl/sl.so"
loadmodule "modules/tm/tm.so"
loadmodule "modules/acc/acc.so"
loadmodule "modules/rr/rr.so"
loadmodule "modules/maxfwd/maxfwd.so"
loadmodule "modules/mysql/mysql.so"
loadmodule "modules/auth/auth.so"
loadmodule "modules/auth_db/auth_db.so"
loadmodule "modules/group/group.so"
loadmodule "modules/uri/uri.so"
# ----------------- setting module-specific parameters ---------------
modparam("auth_db", "db_url","mysql:ser:heslo@localhost/ser")
modparam("auth_db", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
# -- acc params --
modparam("acc", "log_level", 1)
# that is the flag for which we will account -- don't forget to
# set the same one :-)
modparam("acc", "log_flag", 1 )
# ------------------------- request routing logic -------------------
# main routing logic
route{
/* ********* ROUTINE CHECKS ********************************** */
# filter too old messages
if (!mf_process_maxfwd_header("10")) {
log("LOG: Too many hops\n");
sl_send_reply("483","Too Many Hops");
break;
};
if (len_gt( max_len )) {
sl_send_reply("513", "Wow -- Message too large");
break;
};
/* ********* RR ********************************** */
/* grant Route routing if route headers present */
if (loose_route()) { t_relay(); break; };
/* record-route INVITEs -- all subsequent requests must visit us */
if (method=="INVITE") {
record_route();
};
# now check if it really is a PSTN destination which should be handled
# by our gateway; if not, and the request is an invitation, drop it --
# we cannot terminate it in PSTN; relay non-INVITE requests -- it may
# be for example BYEs sent by gateway to call originator
if (!uri=~"sip:\+?[0-9]+@.*") {
if (method=="INVITE") {
sl_send_reply("403", "Call cannot be served here");
} else {
forward(uri:host, uri:port);
};
break;
};
# account completed transactions via syslog
setflag(1);
# free call destinations ... no authentication needed
if ( is_user_in("Request-URI", "free-pstn") /* free destinations */
| uri=~"sip:[79][0-9][0-9][0-9]@.*" /* local PBX */
| uri=~"sip:98[0-9][0-9][0-9][0-9]") {
log("free call");
} else if (src_ip==192.168.0.10) {
# our gateway does not support digest authentication;
# verify that a request is coming from it by source
# address
log("gateway-originated request");
} else {
# in all other cases, we need to check the request against
# access control lists; first of all, verify request
# originator's identity
if (!proxy_authorize( "gateway" /* realm */,
"subscriber" /* table name */)) {
proxy_challenge( "gateway" /* realm */, "0" /* no qop */ );
break;
};
# authorize only for INVITEs -- RR/Contact may result in weird
# things showing up in d-uri that would break our logic; our
# major concern is INVITE which causes PSTN costs
if (method=="INVITE") {
# does the authenticated user have a permission for local
# calls (destinations beginning with a single zero)?
# (i.e., is he in the "local" group?)
if (uri=~"sip:0[1-9][0-9]+@.*") {
if (!is_user_in("credentials", "local")) {
sl_send_reply("403", "No permission for local calls");
break;
};
# the same for long-distance (destinations begin with two zeros")
} else if (uri=~"sip:00[1-9][0-9]+@.*") {
if (!is_user_in("credentials", "ld")) {
sl_send_reply("403", " no permission for LD ");
break;
};
# the same for international calls (three zeros)
} else if (uri=~"sip:000[1-9][0-9]+@.*") {
if (!is_user_in("credentials", "int")) {
sl_send_reply("403", "International permissions needed");
break;
};
# everything else (e.g., interplanetary calls) is denied
} else {
sl_send_reply("403", "Forbidden");
break;
};
}; # INVITE to authorized PSTN
}; # authorized PSTN
# if you have passed through all the checks, let your call go to GW!
rewritehostport("192.168.0.10:5060");
# forward the request now
if (!t_relay()) {
sl_reply_error();
break;
};
}
Use the serctl tool to maintain group membership. The command serctl acl grant <username> <group> makes a user member of a group, the command serctl acl show <username> shows groups of which a user is member, and the command serctl acl revoke <username> [<group>] revokes a user's membership in one or all groups.
[jiri@cat sip_router]$ serctl acl grant john int MySql Password: +------+-----+---------------------+ | user | grp | last_modified | +------+-----+---------------------+ | john | int | 2002-12-08 02:09:20 | +------+-----+---------------------+
In this section we will describe an example configuration of the Asterisk PBX. We will focus mainly on the configuration of the SIP part.
Asterisk can be downloaded from http://www.digium.com
Download the tarball and untar it using:
tar xvfz asterisk-0.5.0.tar.gz
Compile the sources:
# cd asterisk-0.5.0 # make # make install # make samples
The configuration files can be found in the /etc/asterisk directory. The most important files are: sip.conf which contains configuration of SIP user agent and extensions.conf which defines dialing plan.
In our simple example we will configure asterisk to act as a simple back-to-back user agent. It will allow SIP user agents to register to it and make calls which will be routed to an outbound proxy.
The file sip.conf contains the following settings:
; ; SIP Configuration for Asterisk ; [general] port = 5060 ; Port to bind to bindaddr = 0.0.0.0 ; Address to bind to context = from-sip ; Default for incoming calls ; register => asterisk:password@iptel.org/jan ; Register with a SIP provider [iptel] type=friend username=asterisk secret=password fromdomain=iptel.org host=iptel.org [jan] type=friend username=jan ;secret=blah host=dynamic canreinvite=no
Section [general] contains some generic settings. We configure asterisk to listen on port 5060 and to listen on all available interfaces. We also specify context to be “from-sip”. The same context must be later configured in extensions.conf !
The line beginning with “register” instructs asterisk to act as a user agent and register with the iptel.org server as user “asterisk” with password “password”. The /jan part indicates that all incoming calls to user asterisk will be forwarded to user “jan” registered at the asterisk server.
Section [iptel] contains configuration of a peer -- in this case it is the iptel.org proxy server, because we will be using this server as an outbound proxy. In this section we specify the parameter “fromdomain” because we want all outgoing messages to have this domain in the “From” header field.
The last section [jan] contains credentials and data for a user that will be able to register with the asterisk server. In this case we will configure one SIP phone with username “jan” and with an empty password and with a phone which will be registered with the asterisk server to receive calls for username “jan”.
The file extensions.conf contains the following settings:
[from-sip]
exten => jan,1,Dial(SIP/jan)
exten => jan,2,Hangup
exten => _3.,1,SetCallerID(jan)
exten => _3.,2,SetCIDName(Jan Janak)
exten => _3.,3,Dial(SIP/${EXTEN:1}@iptel)
exten => _3.,4,Playback(invalid)
exten => _3.,5,Hangup
The first line describes the context which we have configured in sip.conf already. The following lines describe the dialing plan. The “exten” directive means that the extension of the call will be processed. The first parameter after the => is the extension. If the extension starts with an underscore then it will be treated as an expression, otherwise only exact match will be accepted.
In our example, the first two lines match the extension “jan”. The rest of the lines will match any extension starting with digit 3.
The second parameter is the preference of the line in the dialing plan. The last parameter is the action to be executed when the extension matches. The first line says that calls with extension “jan” will be routed to SIP and peer “jan”.
Any extensions beginning with 3 will be routed to the iptel.org server using SIP and username “jan” will be set as the caller ID. If a call fails then asterisk will reply with an error message.
The Vovida Open Communication Application Library (VOCAL) is an open source project targeted at facilitating the adoption of Voice over IP in the marketplace. VOCAL provides the development community with software and tools needed to build Voice over IP features, applications and services. The VOCAL system is a distributed network of servers that provides Voice Over Internet Protocol (Voice over IP) telephony services. VOCAL supports devices that communicate using the Session Initiation Protocol (SIP, RFC3261). VOCAL also supports analog telephones via residential gateways. VOCAL supports on-network and off-network calling. Off-network calling enables subscribers to connect to parties through either the Internet or the Public Switched Telephone Network (PSTN).
The basic software in VOCAL includes a set of SIP based servers (Redirect Server, Feature Server, Provisioning Server and Marshal Proxy Server). This is the stable development branch of the VOCAL server. Moreover, even if the following applications are not included in the current release (1.5.0), their source code remains available in the CVS archive http://www.vovida.org/cgi-bin/fom?file=556.
For a more detailed overview of VOCAL system please refer to http://www.vovida.org
If you have a previous installation of VOCAL that uses the “vocalstart” executable to run, you must stop all servers with “vocalstart stop”. Note that “vocalstart” is no longer used as of version 1.4.0. In order to perform this action and to install VOCAL you must be logged in as root in your Linux system.
There are two options for downloading and installing VOCAL:
Installing from RPM:
Download vocalbin-version-x.i386.rpm from http:/www.vovida.org
Install the RPM as root, typing “rpm -U vocalbin-version-x.i386.rpm”.
Installing from source:
Type the following sequence of commands:
./configure make make install
You must become root before executing make install.
If you want to have more information about compiling and installing VOCAL please refer to the file BUILD.txt.
To set up a basic configuration you have to use the configuration script indicated here:
/usr/local/vocal/bin/allinoneconfigure/allinoneconfigure
Running the “allinoneconfigure” script, you will be asked a number of questions. For basic services setup answer all questions with the default answers.
After such a default configuration an Apache Web Server has been reconfigured on your Linux machine to provide basic web-based configuration (provisioning in VOCAL terms) and must be restarted for this to take effect.
In order to restart the Apache Web Server you should run:
/etc/rc.d/init.d/httpd restart
When the Apache Web Server is restarted you will be able to use the web-based provisioning of the VOCAL system. In order to start provisioning your system you will have to point a web browser to.
http://your.server.name/vocal/
You will be prompted for a password. The username is “vocal”. During configuration, you were asked to enter a password or choose to have one generated for you. If you have forgotten the password from that step, you can regenerate one by running the command:
allinoneconfigure -r
After you have run the allinoneconfigure script, make sure that your VOCAL system is running typing the following command:
/usr/local/vocal/bin/vocalctl status
You have to make sure that you are able to see all of the necessary processes, as follows:
fs 5080 14957 fs 5085 14955 ms 5060 15002 ...
If instead of such a list of actively running servers with the details of the ports they are listening to, you see “vocald is not running”, then your VOCAL system is not running because something went wrong in the configuration.
If your VOCAL system is running, you can verify your installation by running the “verifysip” command.
Passing it the -a option causes “verifysip” to create two test users, test1000 and test1001, and make a call from test1000 to test1001. After testing, “verifysip” will remove the two users. You should be able to run it with a command like this:
/usr/local/vocal/bin/verifysip -a
If your installation is OK, you should see the following text:
VOCAL basic call test passed.
VOCAL 1.5.0 comes with two provisioning systems. Both work on the same configuration data. The first, described in uses a Java application to configure the system. The second uses web-based CGI scripts, which run on the web server to configure and control VOCAL. It can be accessed through your web browser. The web-based provisioning system provides simple access to the most commonly used provisioning options for an all-in-one system. The Java-based application provides complete view to the server's features, and dial plan provisioning.
Both provisioning systems can be used on the same system, but they should not be run at the same time. The web-based provisioning system is more limited than the Java based one, thus some tasks require using the latter. For tasks other than those requiring the Java provisioning system, we recommend using the web-based provisioning system. The provisioning systems allow the system administrators to work with user and server data. Administrators can choose to Add, View, Edit and Delete Users, as well as insert details of the clients / users allowed access to the VOCAL services.
Server data can be used to configure services, as well as install more advanced features.
The server in charge of authentication in the VOCAL system is the Marshal Proxy Server. The Marshal Proxy Server supports these authentication options:
There is a lot of advanced features that can be deployed on VOCAL architecture. In this section we will present an overview of these features. For a more detailed explanation please refer to the VOCAL web pages.
Each Marshal Proxy Server sends the start and stop time of a call to the Call Detail Record (CDR) Server. The CDR Server may forward the data to 3rd party billing systems using the RADIUS accounting protocol.
Redirection of calls, integration with PSTN gateways and conferencing are configured and exploited using other special kinds of Marshal servers.
Support for both SIP to H.323 gateways and SIP to MGCP gateways is under development and the actual implementation is not yet ready to be used in a production environment, even if improvements are planned in the near future.
Dial plans are easily managed by configuring entries in the provisioning system GUI. Redirection services and backup servers, as well as more features like call forwarding and call blocking are carried out using specialized servers. Last but not least, a voice mail server is used to deliver mails with attached voice files containing message registered to the users.