Asterisk at large

Planning a large installation with SER or OpenSER


Improving performance

  • Store the voice prompts in RAM instead of harddisk: Take a look at ramfs. All you need then is to create a link (ln -s) in /var/lib/asterisk/sound to then ramdrive you created using ramfs.
  • add "fs.file-max = 131072" to /etc/sysctl.conf - run "sysctl -p"
  • add "ulimit -n32768" to /etc/init.d/asterisk

SIP proxy before Asterisk (e.g. SER)

SER is a very capable SIP router, much more sophisticated than Asterisk as it can look inside packets and route based on what it finds or even re-write packets based on user specified logic.

Howto: Getting to know SER

If you want a good explaination of SER and how to use it start here:
Latest Guide http://www.iptel.org/ser/doc/gettingstarted
Old Guide http://siprouter.onsip.org/doc/gettingstarted/
They have GREAT pre-written configs and walk you through every part of SER. I was about to scrap SER before I found these tutorials.

And then there's the OpenSER documentation on how to integrate with Asterisk in realtime for VoiceMail and MWI. Find even more on the same topic here.

Asterisk, OpenSER and mediaproxy in a WAN environment

Asterisk, OpenSER and WAN
This article discusses some of the problems encountered with OpenSER and Asterisk features when implementing a Enterprise VOIP system - and how to solve them.

Benefits for Asterisk

We are using both, SER and Asterisk, in heavy production environment. SER is the BEST SIP proxy that i found. But it is just sip proxy. It can serve a _LOT_ connections (10,000 users, 20 cals per second). Asterisk is more like telephone switch with lot of features, but far slower.

One nice feature of SER is that users can set up their own SIP accounts using a web interface and not needing to edit *.conf files.

Q: In a large installation (many users) - how do you off-load Asterisk by managing RTP traffic effectively?
A: There's no single truth here, but here's my opinion:

  • If you are all on the same internal network, make sure the SIP phones support re-invites and use that.
  • If you have users all over the Internet, use a SIP proxy (like SER) as a front-end to Asterisk. You will still be forced to handle a lot of RTP streams (because of NAT), but can distribute that over a SIP-proxy network with SRV records, DNS round-robin techniques or forcing the users to register with different proxies.

Example: FWD and SIPGATE both run SER coupled with Asterisk

There's been a couple of suggestions that we should make Asterisk a good SIP proxy. If you spend some time learning to understand Asterisk's architecture, you'll also understand that this would not really work. I'm not saying the SIP channel can't be improved, I'm just saying that it has to work with the rest of Asterisk's architecture. Asterisk in combination with a separate SIP proxy is a very powerful solution.

With a SIP proxy we have the following scenario:


  • Alice's UA sends an INVITE to bob@domain
  • The proxy responsible for this domain receives this and looks up bob in a user location or alias table
  • The proxy FORWARDS the same INVITE to bob@currentlocation, maybe several different locations
  • When Bob answers somewhere, the proxy cancels the call to the non-answering locations and forwards the OK to Alice
  • Alice ACKs the OK to bob and the call is UP

In this scenario, there's only one SIP dialogue, between Alice and Bob with the proxy in the middle of signalling, but acting as a proxy and not as a user agent (the proxy can't and should not answer or originate calls).




A quote

We are using SER together with *. SER is used as a SIP proxy/registrar, * is used as a SIP - PSTN gateway and voicemail/forward/conference server.

Advantages: scalable, very large number of SIP clients with easier RADIUS/database user management, advanced SIP logic/routing options, better SIP interoperability
Disadvantages: you've got two boxes, no IAX on SER so you still have to manage IAX users on asterisk

In my setup * is talking to SIP UA through SER - this is done by setting the record route parameter in SER routing logic. I also pass the media stream through SER - this is done through the rtpproxy module (SER).

In my opinion, if you plan to deploy large number of SIP clients - it's a good idea
-Dawid Mielnik-


Asterisk and SER Diagram

Here is a nice Ser+Asterisk of how to use SER and Asterisk together.

Asterisk and OpenSER integration.


Let's talk about something intreseting. i had started working on ip telephony system last 1 year. i have implemented IP PBX solution of many organization. i have good experties on telephony and Asterisk system. but basicaly Asterisk is not a SIP server but i can support sip protocal thats whay asterisk handle only 200 to 300 number of sip devices ot registration so that on large production its not able to work gr8. finelly i have decided to implement Asterisk on large production with the help of OpenSER. OpenSER is pure sip server so and it is light wieght binary so it can handle 10,000 call per second so i am useing OpenSER front of Asterisk so openser handle my call SIP registration request and my PSTN functionality done by Asterisk caz OpenSER not support telephpny hardware. Asterisk provide media application services like VoiceMail, Confrance, IVR, PSTN function.

I am going to show you how to integrate this both system OpenSER and Asterisk.

My configuration example.

$cat /usr/local/etc/openser/openser.cfg

debug=6
fork=yes
log_stderror=yes
port=5060
children=4
fifo="/tmp/ser_fifo"
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"
modparam("usrloc", "db_mode",   0)
modparam("rr", "enable_full_lr", 1)
route{
        if (!mf_process_maxfwd_header("10")) {
                sl_send_reply("483","Too Many Hops");
                break;
        };
        if (msg:len >=  2048 ) {
                sl_send_reply("513", "Message too big");
                break;
        };

        if (!method=="REGISTER") record_route();
        if (loose_route()) {
                append_hf("P-hint: rr-enforced\r\n");
                route(1);
                break;
        };
        if (!uri==myself) {
                append_hf("P-hint: outbound\r\n");
                route(1);
                break;
        };
        if (uri==myself) {
                if (method=="REGISTER") {
                        save("location");
                        break;
                };
                if(method=="INVITE") {            ; When SIP new INVITE message arrived & if  URI digit start from "0" (zero) the go to route(3) otherwise fine it in local database 
                        if (uri =~ "sip:0[[0-9]@*"){
                        route(3);
                        break;
                }
                }
                lookup("aliases");
                if (!uri==myself) {
                        append_hf("P-hint: outbound alias\r\n");
                        route(1);
                        break;
                };
                if (!lookup("location")) {
                        sl_send_reply("404", "Not Found");
                        break;
                };
        };
        append_hf("P-hint: usrloc applied\r\n");
        route(1);
}
route[1]
{
        if (!t_relay()) {
                sl_reply_error();
        };
}
route[3]{

   if (uri =~ "sip:0[0-9]@*"){                        ; again digit match first 0 digit. ( optional in my case ).
        log(1, "Forwarding to Asterisk \n");          ; Log for information or debug.
        rewritehostport("192.168.104.20:5060");       ; modifiy URI and forward to Asterisk.
        route(1);
        break;
    }



Asterisk configuration for openser.


sip.conf


[203.124.16.109]
type=friend                                   ; We allow incoming and outgoing calls. Use peer if you are only doing MWI
context=outgoing                           ; This is the context incoming calls land in
host=<openser_server_ip>                           ; This is the hostname or IP address of your SER server
fromdomain=<openser_server_ip>               ; This is your SER_DOMAIN
insecure=very                                           ; This allows incoming calls from the phones routing through ser to be passed into asterisk
mailbox=user@context


extention.conf


[globals]
SERADDRESS=xxx.xxx.xxx.xxx

[outgoing]
exten => _XXXX,1,Dial(SIP/${EXTEN}@${SERADDRESS},20,r)
exten => _0XXXXXXXXXX,1,Dial(Zap/g1/${EXTEN},60)


MWI - message waiting indication

See also Asterisk MWI for related info

Method 1

I don't use Asterisk as a UA, no SIP users are registered to Asterisk, instead all that is handled by SER. So Asterisk just needs to be able to reach the phone. For this you need a "peer" statement for each phone in sip.conf (which could be created based upon the SER registry data and using ast_data / res_data). Note that this peer never takes calls and is solely used for MWI purposes.

So we just need a way for Asterisk to contact the phone when it has a MWI notification (host=phone_ip). Yet another way to supply this IP is through with DDNS records.

In any case you will need a peer like this - for each phone:

[2114]
type=peer
username=2114
insecure=yes
canreinvite=no
context=default
mailbox=2114
host=SIP003094C274B3.bna01.isdn.net

Method 2 - by Andreas Granig

Q: I assume that asterisk would have to send the SIP NOTIFY message to the registered SIP clients via ser. So will I have to create a custom Asterisk and ser modules to get this to work?
A: Asterisk sends NOTIFY only to UACs that are registered at the Asterisk. If you just forward voicemail calls to Asterisk and the UACs are registered at SER, you have to use the 'externnotify'-option in voicemail.conf of Asterisk. We use a script wrapped around sipsak to turn on/off MWI by sending proper NOTIFY messages.

Details by Paul (aka Java Rockx): I use sipsak to send the message from my Asterisk server to my ser proxy. I use the Asterisk "externnotify" in the voicemail.conf file to specify an external bash script. This script then simply "touches" a file in /var/spool/mwi/ for later processing by cron.

My cron job comes along after the fact and picks up all the files in /var/spool/mwi/ and generates the appropriate SIP NOTIFY message and then it uses sipsak to "shoot" it to the ser proxy. Note that asterisk is a registered UA with ser. Doing this I assumed I could simply use sipsak from the asterisk server to send NOTIFY messages to the ser box.

This works really well for me when I need to turn on the MWI for a UA. What I still can't do is turn the MWI off when there are no new messages. I'm really having a hard time trying to determine how to hook the "Hang-Up" event in Asterisk. I need to essentially have an "externnotify" for hang ups so I can check the message status for a the mailbox and cancel the MWI if there are no new messages.

I also need to handle SUBSCRIBE messages that the SIP proxy gets. I'm planning on have the ser.cfg file execute an external script that will get a message to the cron job on my Asterisk box. Once the Asterisk box gets notified of the SUBSCRIBE message, it will process the same as if the user just had a voice mail left and the externnotify event got fired.

...and here is the solution!

Method 3

Q: If you have your SIP phones registered with SER but your voicemail is handled by asterisk, how do you get the MWI (Message Waiting Indicator) light to function on the phone?

A: In sip.conf create a section pointing at your SER router.

[ser]
type=friend ; We allow incoming and outgoing calls. Use peer if you are only doing MWI
context=ser ; This is the context incoming calls land in
host=ser.server.tld ; This is the hostname or IP address of your SER server
fromdomain=ser.server.rld ; This is your SER_DOMAIN
insecure=very ; This allows incoming calls from the phones routing through ser to be passed into asterisk
mailbox=user@context ; This is where you list the voicemail boxes to monitor

This tells asterisk that if a voicemail comes in to "user" then it needs to send a SIP NOTIFY message to the "ser.server.tld" phone. Well this is all well and good except how does SER deliver this NOTIFY to the phones? First thing is that you need to make a tiny change to the asterisk code to pass the mailbox user in the SIP NOTIFY packet.


--- channels/chan_sip.c.orig    Thu Jul 14 12:03:18 2005
+++ channels/chan_sip.c Thu Jul 14 12:05:26 2005
@@ -9710,6 +9710,7 @@
        /* Called with peerl lock, but releases it */
        struct sip_pvt *p;
        int newmsgs, oldmsgs;
+       char *s;

        /* Check for messages */
        ast_app_messagecount(peer->mailbox, &newmsgs, &oldmsgs);
@@ -9735,6 +9736,10 @@
        /* Recalculate our side, and recalculate Call ID */
        if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
                memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
+       strcpy(p -> username, peer -> mailbox);  /* Username = Mailbox name */
+       s = strchr(p -> username, '@');          /* Remove the context part */
+       if (s != NULL)
+                *s = 0;
        build_via(p, p->via, sizeof(p->via));
        build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
        /* Send MWI */


After this patch is applied, the MWI NOTIFY messages coming from asterisk will have the URI user@ser.server.tld. This can be then routed with ser to the correct phone with normal SER routing rules. ie. SER does a lookup("location") and then a t_relay(). I don't believe this patch should effect any non-ser controlled sip phones.

For me, this method was a lot easier then Method 2 listed above. You can add as may mailbox's as you like into the mailbox= line in the asterisk sip.conf file. One possible problem is if you have a mailbox called 1000@cx1 and another called 1000@cx2, this patch will make the MWI indicator light up for phone 1000@ser.server.tld when either mailbox gets a message. A simple modification to the patch and SER could be used to handle multiple contexts if required however this simplification is sufficient for me.

Method 4 - using realtime (ARA) and loading all SIP peers at Asterisk startup

Q: We use the Asterisk RealtimeArchitecture for voicemail users and SIP peers. The database table for the sip peers is a view from the OpenSER subscriber table.
The MWI for a user will only work, if the user object (sip peer) is loaded into memory and visible with the CLI command "sip show peers". This happens, for example, if the user call his own mailbox for checking voicemail.
Is their a possibility to load all peers from database on asterisk startup so that the users will get their NOTIFY without calling their own mailbox first?

A: See here: http://article.gmane.org/gmane.comp.telephony.pbx.asterisk.user/134846

A: If the phone wants MWI notifications, it should send a SUBSCRIBE with header "Event: message-summary". That should be routed to Asterisk, which will make ut load the peer in memory. Starting with the config from Realtime Integration Of Asterisk With OpenSER, you can add:

    if(is_method("SUBSCRIBE")
            && search("^Event: message-summary"))
    {
        # if there is no R-URI username, grab From URI
        if(!uri=~"sip:.+@")
        { # add From username as R-URI username
            avp_pushto("$ruri/username","$fU");
        }
        # fix some broken subscriptions
        if(!search("^Accept: application/simple-message-summary"))
            append_hf("Accept: application/simple-message-summary\r\n");
        setdsturi("sip:__asterisk_ip__:__asterisk_port__");
        t_relay();
        exit;
    }


Method 5

Assuming you have a simliar setup to method 3 where Asterisk handles voicemail, and you don't need to reach the phone from Asterisk.. It is possible to have MWI sip notify messages sent to SER without patching. In Asterisk's sip.conf, use host field for each phone to send sip notify messages to SER.
Example:
SER server - sip.zxy.com
In sip.conf:

[phonea]
..
host=sip.zxy.com
..

The setup of your dial plan may matter for this to work. In some cases it wasn't necessary to change the dial plan. If you find calls getting routed back to SER (eg 2 missed calls instead of 1), then change your Dial plan/macro for the phone.
Example:
exten => 2222,1,Voicemail(2222@default)


Example installation

Working with both Asterisk and SER:
1. Configure diferent sip listening ports for SER (/etc/ser/ser.cfg) and Asterisk (/etc/asterisk/sip.conf).
2. Configure SER (/etc/ser/ser.cfg) for forwarding calls based in destination. For example adding:

if (uri=~"^sip:0[0-9]*@yourdomain") {
forward( 10.10.10.10, 5070 ); //Where local asterisk is listening
break;
}

Method 6

if you enable the presence module in OpenSER/OpenSips/SER/Kamailio it will take care of your ser interaction.
then you just need to send the sip packet to the proxy.

I based my solution on Method 2 ( thanks Andreas Granig )

I am using a file system watch utility called iwatch, and sipsak to send the packet

start iwatch this way

iwatch -d -f /usr/local/mwi/etc/mwi.xml

here is the mwi.xml

<?xml version="1.0" ?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >

<config>
  <guard email="root@localhost" name="IWatch"/>
  <watchlist>
    <title>MWI</title>
    <contactpoint email="root@localhost" name="Administrator"/>
    <path type="recursive" alert="off" exec="/usr/bin/perl /usr/local/mwi/bin/mwi.pl %f" events="moved_to,delete">/var/spool/asterisk/voicemail/default</path>
  </watchlist>
</config>

this is the mwi.pl script

#!/usr/bin/perl

$host = "<ser ip>";
$localhost = "<my local ip>";
$port = <ser sip port>;

my @parts = split(/\//, $ARGV[0]);

if ($parts[7] eq 'INBOX' || $parts[7] eq 'Old') {
        #open LOGFILE, ">>/usr/local/mwi/log/mwi.log";
        #print LOGFILE "$ARGV[0]\n";
        #close(LOGFILE);
        if ($parts[8] =~ m/msg\d+\.txt/) {
                @newFiles = </var/spool/asterisk/voicemail/default/$parts[6]/INBOX/*.txt>;
                @oldFiles = </var/spool/asterisk/voicemail/default/$parts[6]/Old/*.txt>;
                $numNew = $#newFiles + 1;
                $numOld = $#oldFiles + 1;
                #this is the ternary operator fancy way of doing if (($#newFiles +1) != 0) { $hasNew = "yes"; } else { $hasNew = "no"; }  
                $hasNew = (($#newFiles + 1) != 0) ? "yes" : "no";
                $length = 34;
                $length += length $numNew;
                $length += length $hasNew;
                $length += length $numOld;
                #the spacing change is necessary here or it will screw up the sip packet
                $message = "NOTIFY sip:$parts[6]\@$host SIP/2.0
Via: SIP/2.0/UDP $host:$port
From: <sip:asterisk\@$localhost>
To: <sip:$parts[6]\@$host>
Contact: <sip:$parts[6]\@$host>
Call-ID: 4d61cf9e505d40e905032a18329d61ec\@$host
CSeq: 1 NOTIFY
User-Agent: VoiceMail
Event: message-summary
Content-Type: application/simple-message-summary
Content-Length: $length\n\n
Messages-Waiting: $hasNew
Voicemail: $numNew/$numOld\n";
                $file = "/home/pciadmin/mwi/tmp/$parts[6]";
                open MYFILE, "+>$file";
                print MYFILE $message;
                close(MYFILE);
                exec("sipsak shoot -a number4 -f /home/pciadmin/mwi/tmp/$parts[6] -s sip:$parts[6]\@$host:$port");
                #I was sleeping here and deleting the file, but i decided that I liked having the last sip packet sent to the host 
                #sleep 1;
                #unlink($file);
        }
}


this is just like Method 2 only the events happen off the file system changes so theoretically any voicemail system could be adapted to use this as long as you can run a couple of perl scripts
I did it this way because the original method described in method 2 did not suit my particular situation

I hope this helps someone like Andreas Granig's solution helped me

load testing on this script revealed 10,000 iterations of the script took approx. 4.5 seconds on a p3 1.2 with a 1gig of ram
Linux asterisk-ser 2.6.26-2-686 #1 SMP Thu Mar 26 01:08:11 UTC 2009 i686 GNU/Linux


Asterisk and SER on same box


>If Asterisk is directed to speak SIP on port 5061 and SER
>remains on port 5060, then how do you get Asterisk to talk
>to SER and vice versa?

It is something like this:
Asterisk extensions.conf:

[globals]
SERADDRESS=XXX.XXX.XXX.XXX:5060

[context]
exten => <yourexten>,1,Dial(SIP/${EXTEN}@${SERADDRESS},20,r)

In ser.cfg:

if (method == "INVITE") {
if (uri =~ "sip:1[0-9]{10}@*"){
log(1, "Forwarding to Asterisk\n");
rewritehostport("XXX.XXX.XXX.XXX:5061");
t_relay();
break;
}
}

(Documentation in SER admin guide: http://www.iptel.org/ser/doc/seruser/seruser.html)
3. Configure Asterisk as PSTN gateway. I haven't experience in this point.

Intro on differences between Asterisk and SER

by Alex Barnes

Many people say that it allows * to scale better for SIP. For example
assuming your SIP proxy is stateful the proxy will handle all
retransmissions / redirections / register lookups / call logging / ????,
all of which would be hidden from the *.

Multiple registrations:
Asterisk doesn't support multiple registrations. A registrar proxy
will be able to do this, allowing such things as forking (sequential /
parrellel / combinations of both).

Grey Areas (Functionality that crosses over between * and a proxy)

CPL:
Any proxy worth its salt will have a CPL engine built in
allowing some pretty powerful scripting of incoming / outgoing calls on
a individual user basis.

Application Servers:
A proxy may also be an application server. Which could be used
to make any number of technologies available. For example Ubiquity make
a HA SIP App Server that can do pretty much anything including RMI
client/server apps, SOAP, link with Web Application Servers (Websphere /
Weblogic), Java Eventlets that let you write your own interfaces using
our SIP SDK's for call handling.

HOWEVER

I don't think that Asterisk is quite ready to support all live
deployment scenarios that include a 3rd party SIP proxy.
One problem I ran into was Asterisk does not handle looped back calls.

For example a call comes in over PSTN to Asterisk, Asterisk forwards to
your SIP registrar proxy, Registrar does a lookup on the SIP address and
finds that the user is register'd to an analogue phone.
If the SIP registrar redirected using a 3xx response the * will play
along happily, but if the proxy wishes to stay in the loop (maybe you
have a billing application running on it) it would add a Record-Route
header to the SIP request , to say it wishes to receive all subsequent
messages for this call, and then proxy back to the *. The * will ignore
this INVITE totally.
If the user had been registered to a proper SIP end point then the loop
back wouldn't have happened and this works a treat.


Load balancing with SER

See discussion here: http://article.gmane.org/gmane.comp.telephony.pbx.asterisk.user/162042
Partial quote:

"SER/OpenSER can get around call forwarding/transfer problems. You just need
to account for those SIP dialogue's that can be problematic, and bypass
using the dispatcher module for those situations.

One thing to remember is to replicate usr-loc info that is cached in memory,
otherwise load-balancing for INVITE's will fail if passed to a proxy that
did not receive the REGISTER request for sending party. The standard
t_replicate() function only supports replication between two SER/OpenSER
proxies, so if you are looking to add in any more, you will need a more
manual approach. OpenSER 1.1.0 actually offers the ability to operate
completely out of a database, even for usr-loc, which could work for you.

Other approaches for load balancing include DNS round-robin techniques, and
separate software or hardware appliances dedicated to load distribution. I
have successfully worked with Foundry ServerIron's, and Vovida's Open Source
load-balancing proxy, in the past."

Example: SER, Asterisk and Lucent TNT

by Michael Shuler
You can do what we did and setup 2 SER servers which are load balanced by a Foundry ServerIron XL (you could use UltraMonkey for free if you prefer). The 2 SER machines handle the REGISTER messages, NAT and final delivery to the VoIP devices and to the media gateways. The SER machines don't know what to do with a call they only know to hand it over to Asterisk for routing/CLASS features or whatever you want the call to do. You then have a separate set of Asterisk boxes that are nothing but media gateways/transcoders that have the PRI cards in them. We don't actually use Asterisk as media gateways in our setup we use the Lucent TNTs but it accomplishes the same thing but on a much larger scale. As far as sharing the common configs we use http://svn.asteriskdocs.org/res_data/ to read all of our configs (sip.conf, extensions.conf, etc.) live from a MySQL database. Just apply the patch and go.

So far we have seen no limit as to the scalability of this setup. If the 2 SER servers get overloaded we just add another. If the Asterisk routing servers get overloaded we just add another. IF we run out of PRI's we add another TNT and more PRI's from our Plexus 9000 switch. So the system in theory has no real-world limits.

Here is the sample configuration for SER.

Example TeleSIP

Q: Are you aware of any documentation on how to configure SER to be a front-end to Asterisk?

A: At TeleSIP we run a cluster of several geographically distributed SER Servers that hande all our SIP Routing. SER is a robust, fast and stable platform which has worked flawlessly for us. We use * as our company PBX and PSTN Gateway. Basically what you need to do is to devise a numbering plan so that SERs routing logic can forward the call to * when it needs to.

R: Another example can be found in the SER handbook, found on IPtel.org. The
example mentions how to use SER as a frontend to a Cisco PSTN gateway, but also applies to using SER as a frontend to Asterisk.

See also



Go back to Asterisk administration

Planning a large installation with SER or OpenSER


Improving performance

  • Store the voice prompts in RAM instead of harddisk: Take a look at ramfs. All you need then is to create a link (ln -s) in /var/lib/asterisk/sound to then ramdrive you created using ramfs.
  • add "fs.file-max = 131072" to /etc/sysctl.conf - run "sysctl -p"
  • add "ulimit -n32768" to /etc/init.d/asterisk

SIP proxy before Asterisk (e.g. SER)

SER is a very capable SIP router, much more sophisticated than Asterisk as it can look inside packets and route based on what it finds or even re-write packets based on user specified logic.

Howto: Getting to know SER

If you want a good explaination of SER and how to use it start here:
Latest Guide http://www.iptel.org/ser/doc/gettingstarted
Old Guide http://siprouter.onsip.org/doc/gettingstarted/
They have GREAT pre-written configs and walk you through every part of SER. I was about to scrap SER before I found these tutorials.

And then there's the OpenSER documentation on how to integrate with Asterisk in realtime for VoiceMail and MWI. Find even more on the same topic here.

Asterisk, OpenSER and mediaproxy in a WAN environment

Asterisk, OpenSER and WAN
This article discusses some of the problems encountered with OpenSER and Asterisk features when implementing a Enterprise VOIP system - and how to solve them.

Benefits for Asterisk

We are using both, SER and Asterisk, in heavy production environment. SER is the BEST SIP proxy that i found. But it is just sip proxy. It can serve a _LOT_ connections (10,000 users, 20 cals per second). Asterisk is more like telephone switch with lot of features, but far slower.

One nice feature of SER is that users can set up their own SIP accounts using a web interface and not needing to edit *.conf files.

Q: In a large installation (many users) - how do you off-load Asterisk by managing RTP traffic effectively?
A: There's no single truth here, but here's my opinion:

  • If you are all on the same internal network, make sure the SIP phones support re-invites and use that.
  • If you have users all over the Internet, use a SIP proxy (like SER) as a front-end to Asterisk. You will still be forced to handle a lot of RTP streams (because of NAT), but can distribute that over a SIP-proxy network with SRV records, DNS round-robin techniques or forcing the users to register with different proxies.

Example: FWD and SIPGATE both run SER coupled with Asterisk

There's been a couple of suggestions that we should make Asterisk a good SIP proxy. If you spend some time learning to understand Asterisk's architecture, you'll also understand that this would not really work. I'm not saying the SIP channel can't be improved, I'm just saying that it has to work with the rest of Asterisk's architecture. Asterisk in combination with a separate SIP proxy is a very powerful solution.

With a SIP proxy we have the following scenario:


  • Alice's UA sends an INVITE to bob@domain
  • The proxy responsible for this domain receives this and looks up bob in a user location or alias table
  • The proxy FORWARDS the same INVITE to bob@currentlocation, maybe several different locations
  • When Bob answers somewhere, the proxy cancels the call to the non-answering locations and forwards the OK to Alice
  • Alice ACKs the OK to bob and the call is UP

In this scenario, there's only one SIP dialogue, between Alice and Bob with the proxy in the middle of signalling, but acting as a proxy and not as a user agent (the proxy can't and should not answer or originate calls).




A quote

We are using SER together with *. SER is used as a SIP proxy/registrar, * is used as a SIP - PSTN gateway and voicemail/forward/conference server.

Advantages: scalable, very large number of SIP clients with easier RADIUS/database user management, advanced SIP logic/routing options, better SIP interoperability
Disadvantages: you've got two boxes, no IAX on SER so you still have to manage IAX users on asterisk

In my setup * is talking to SIP UA through SER - this is done by setting the record route parameter in SER routing logic. I also pass the media stream through SER - this is done through the rtpproxy module (SER).

In my opinion, if you plan to deploy large number of SIP clients - it's a good idea
-Dawid Mielnik-


Asterisk and SER Diagram

Here is a nice Ser+Asterisk of how to use SER and Asterisk together.

Asterisk and OpenSER integration.


Let's talk about something intreseting. i had started working on ip telephony system last 1 year. i have implemented IP PBX solution of many organization. i have good experties on telephony and Asterisk system. but basicaly Asterisk is not a SIP server but i can support sip protocal thats whay asterisk handle only 200 to 300 number of sip devices ot registration so that on large production its not able to work gr8. finelly i have decided to implement Asterisk on large production with the help of OpenSER. OpenSER is pure sip server so and it is light wieght binary so it can handle 10,000 call per second so i am useing OpenSER front of Asterisk so openser handle my call SIP registration request and my PSTN functionality done by Asterisk caz OpenSER not support telephpny hardware. Asterisk provide media application services like VoiceMail, Confrance, IVR, PSTN function.

I am going to show you how to integrate this both system OpenSER and Asterisk.

My configuration example.

$cat /usr/local/etc/openser/openser.cfg

debug=6
fork=yes
log_stderror=yes
port=5060
children=4
fifo="/tmp/ser_fifo"
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"
modparam("usrloc", "db_mode",   0)
modparam("rr", "enable_full_lr", 1)
route{
        if (!mf_process_maxfwd_header("10")) {
                sl_send_reply("483","Too Many Hops");
                break;
        };
        if (msg:len >=  2048 ) {
                sl_send_reply("513", "Message too big");
                break;
        };

        if (!method=="REGISTER") record_route();
        if (loose_route()) {
                append_hf("P-hint: rr-enforced\r\n");
                route(1);
                break;
        };
        if (!uri==myself) {
                append_hf("P-hint: outbound\r\n");
                route(1);
                break;
        };
        if (uri==myself) {
                if (method=="REGISTER") {
                        save("location");
                        break;
                };
                if(method=="INVITE") {            ; When SIP new INVITE message arrived & if  URI digit start from "0" (zero) the go to route(3) otherwise fine it in local database 
                        if (uri =~ "sip:0[[0-9]@*"){
                        route(3);
                        break;
                }
                }
                lookup("aliases");
                if (!uri==myself) {
                        append_hf("P-hint: outbound alias\r\n");
                        route(1);
                        break;
                };
                if (!lookup("location")) {
                        sl_send_reply("404", "Not Found");
                        break;
                };
        };
        append_hf("P-hint: usrloc applied\r\n");
        route(1);
}
route[1]
{
        if (!t_relay()) {
                sl_reply_error();
        };
}
route[3]{

   if (uri =~ "sip:0[0-9]@*"){                        ; again digit match first 0 digit. ( optional in my case ).
        log(1, "Forwarding to Asterisk \n");          ; Log for information or debug.
        rewritehostport("192.168.104.20:5060");       ; modifiy URI and forward to Asterisk.
        route(1);
        break;
    }



Asterisk configuration for openser.


sip.conf


[203.124.16.109]
type=friend                                   ; We allow incoming and outgoing calls. Use peer if you are only doing MWI
context=outgoing                           ; This is the context incoming calls land in
host=<openser_server_ip>                           ; This is the hostname or IP address of your SER server
fromdomain=<openser_server_ip>               ; This is your SER_DOMAIN
insecure=very                                           ; This allows incoming calls from the phones routing through ser to be passed into asterisk
mailbox=user@context


extention.conf


[globals]
SERADDRESS=xxx.xxx.xxx.xxx

[outgoing]
exten => _XXXX,1,Dial(SIP/${EXTEN}@${SERADDRESS},20,r)
exten => _0XXXXXXXXXX,1,Dial(Zap/g1/${EXTEN},60)


MWI - message waiting indication

See also Asterisk MWI for related info

Method 1

I don't use Asterisk as a UA, no SIP users are registered to Asterisk, instead all that is handled by SER. So Asterisk just needs to be able to reach the phone. For this you need a "peer" statement for each phone in sip.conf (which could be created based upon the SER registry data and using ast_data / res_data). Note that this peer never takes calls and is solely used for MWI purposes.

So we just need a way for Asterisk to contact the phone when it has a MWI notification (host=phone_ip). Yet another way to supply this IP is through with DDNS records.

In any case you will need a peer like this - for each phone:

[2114]
type=peer
username=2114
insecure=yes
canreinvite=no
context=default
mailbox=2114
host=SIP003094C274B3.bna01.isdn.net

Method 2 - by Andreas Granig

Q: I assume that asterisk would have to send the SIP NOTIFY message to the registered SIP clients via ser. So will I have to create a custom Asterisk and ser modules to get this to work?
A: Asterisk sends NOTIFY only to UACs that are registered at the Asterisk. If you just forward voicemail calls to Asterisk and the UACs are registered at SER, you have to use the 'externnotify'-option in voicemail.conf of Asterisk. We use a script wrapped around sipsak to turn on/off MWI by sending proper NOTIFY messages.

Details by Paul (aka Java Rockx): I use sipsak to send the message from my Asterisk server to my ser proxy. I use the Asterisk "externnotify" in the voicemail.conf file to specify an external bash script. This script then simply "touches" a file in /var/spool/mwi/ for later processing by cron.

My cron job comes along after the fact and picks up all the files in /var/spool/mwi/ and generates the appropriate SIP NOTIFY message and then it uses sipsak to "shoot" it to the ser proxy. Note that asterisk is a registered UA with ser. Doing this I assumed I could simply use sipsak from the asterisk server to send NOTIFY messages to the ser box.

This works really well for me when I need to turn on the MWI for a UA. What I still can't do is turn the MWI off when there are no new messages. I'm really having a hard time trying to determine how to hook the "Hang-Up" event in Asterisk. I need to essentially have an "externnotify" for hang ups so I can check the message status for a the mailbox and cancel the MWI if there are no new messages.

I also need to handle SUBSCRIBE messages that the SIP proxy gets. I'm planning on have the ser.cfg file execute an external script that will get a message to the cron job on my Asterisk box. Once the Asterisk box gets notified of the SUBSCRIBE message, it will process the same as if the user just had a voice mail left and the externnotify event got fired.

...and here is the solution!

Method 3

Q: If you have your SIP phones registered with SER but your voicemail is handled by asterisk, how do you get the MWI (Message Waiting Indicator) light to function on the phone?

A: In sip.conf create a section pointing at your SER router.

[ser]
type=friend ; We allow incoming and outgoing calls. Use peer if you are only doing MWI
context=ser ; This is the context incoming calls land in
host=ser.server.tld ; This is the hostname or IP address of your SER server
fromdomain=ser.server.rld ; This is your SER_DOMAIN
insecure=very ; This allows incoming calls from the phones routing through ser to be passed into asterisk
mailbox=user@context ; This is where you list the voicemail boxes to monitor

This tells asterisk that if a voicemail comes in to "user" then it needs to send a SIP NOTIFY message to the "ser.server.tld" phone. Well this is all well and good except how does SER deliver this NOTIFY to the phones? First thing is that you need to make a tiny change to the asterisk code to pass the mailbox user in the SIP NOTIFY packet.


--- channels/chan_sip.c.orig    Thu Jul 14 12:03:18 2005
+++ channels/chan_sip.c Thu Jul 14 12:05:26 2005
@@ -9710,6 +9710,7 @@
        /* Called with peerl lock, but releases it */
        struct sip_pvt *p;
        int newmsgs, oldmsgs;
+       char *s;

        /* Check for messages */
        ast_app_messagecount(peer->mailbox, &newmsgs, &oldmsgs);
@@ -9735,6 +9736,10 @@
        /* Recalculate our side, and recalculate Call ID */
        if (ast_sip_ouraddrfor(&p->sa.sin_addr,&p->ourip))
                memcpy(&p->ourip, &__ourip, sizeof(p->ourip));
+       strcpy(p -> username, peer -> mailbox);  /* Username = Mailbox name */
+       s = strchr(p -> username, '@');          /* Remove the context part */
+       if (s != NULL)
+                *s = 0;
        build_via(p, p->via, sizeof(p->via));
        build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain);
        /* Send MWI */


After this patch is applied, the MWI NOTIFY messages coming from asterisk will have the URI user@ser.server.tld. This can be then routed with ser to the correct phone with normal SER routing rules. ie. SER does a lookup("location") and then a t_relay(). I don't believe this patch should effect any non-ser controlled sip phones.

For me, this method was a lot easier then Method 2 listed above. You can add as may mailbox's as you like into the mailbox= line in the asterisk sip.conf file. One possible problem is if you have a mailbox called 1000@cx1 and another called 1000@cx2, this patch will make the MWI indicator light up for phone 1000@ser.server.tld when either mailbox gets a message. A simple modification to the patch and SER could be used to handle multiple contexts if required however this simplification is sufficient for me.

Method 4 - using realtime (ARA) and loading all SIP peers at Asterisk startup

Q: We use the Asterisk RealtimeArchitecture for voicemail users and SIP peers. The database table for the sip peers is a view from the OpenSER subscriber table.
The MWI for a user will only work, if the user object (sip peer) is loaded into memory and visible with the CLI command "sip show peers". This happens, for example, if the user call his own mailbox for checking voicemail.
Is their a possibility to load all peers from database on asterisk startup so that the users will get their NOTIFY without calling their own mailbox first?

A: See here: http://article.gmane.org/gmane.comp.telephony.pbx.asterisk.user/134846

A: If the phone wants MWI notifications, it should send a SUBSCRIBE with header "Event: message-summary". That should be routed to Asterisk, which will make ut load the peer in memory. Starting with the config from Realtime Integration Of Asterisk With OpenSER, you can add:

    if(is_method("SUBSCRIBE")
            && search("^Event: message-summary"))
    {
        # if there is no R-URI username, grab From URI
        if(!uri=~"sip:.+@")
        { # add From username as R-URI username
            avp_pushto("$ruri/username","$fU");
        }
        # fix some broken subscriptions
        if(!search("^Accept: application/simple-message-summary"))
            append_hf("Accept: application/simple-message-summary\r\n");
        setdsturi("sip:__asterisk_ip__:__asterisk_port__");
        t_relay();
        exit;
    }


Method 5

Assuming you have a simliar setup to method 3 where Asterisk handles voicemail, and you don't need to reach the phone from Asterisk.. It is possible to have MWI sip notify messages sent to SER without patching. In Asterisk's sip.conf, use host field for each phone to send sip notify messages to SER.
Example:
SER server - sip.zxy.com
In sip.conf:

[phonea]
..
host=sip.zxy.com
..

The setup of your dial plan may matter for this to work. In some cases it wasn't necessary to change the dial plan. If you find calls getting routed back to SER (eg 2 missed calls instead of 1), then change your Dial plan/macro for the phone.
Example:
exten => 2222,1,Voicemail(2222@default)


Example installation

Working with both Asterisk and SER:
1. Configure diferent sip listening ports for SER (/etc/ser/ser.cfg) and Asterisk (/etc/asterisk/sip.conf).
2. Configure SER (/etc/ser/ser.cfg) for forwarding calls based in destination. For example adding:

if (uri=~"^sip:0[0-9]*@yourdomain") {
forward( 10.10.10.10, 5070 ); //Where local asterisk is listening
break;
}

Method 6

if you enable the presence module in OpenSER/OpenSips/SER/Kamailio it will take care of your ser interaction.
then you just need to send the sip packet to the proxy.

I based my solution on Method 2 ( thanks Andreas Granig )

I am using a file system watch utility called iwatch, and sipsak to send the packet

start iwatch this way

iwatch -d -f /usr/local/mwi/etc/mwi.xml

here is the mwi.xml

<?xml version="1.0" ?>
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >

<config>
  <guard email="root@localhost" name="IWatch"/>
  <watchlist>
    <title>MWI</title>
    <contactpoint email="root@localhost" name="Administrator"/>
    <path type="recursive" alert="off" exec="/usr/bin/perl /usr/local/mwi/bin/mwi.pl %f" events="moved_to,delete">/var/spool/asterisk/voicemail/default</path>
  </watchlist>
</config>

this is the mwi.pl script

#!/usr/bin/perl

$host = "<ser ip>";
$localhost = "<my local ip>";
$port = <ser sip port>;

my @parts = split(/\//, $ARGV[0]);

if ($parts[7] eq 'INBOX' || $parts[7] eq 'Old') {
        #open LOGFILE, ">>/usr/local/mwi/log/mwi.log";
        #print LOGFILE "$ARGV[0]\n";
        #close(LOGFILE);
        if ($parts[8] =~ m/msg\d+\.txt/) {
                @newFiles = </var/spool/asterisk/voicemail/default/$parts[6]/INBOX/*.txt>;
                @oldFiles = </var/spool/asterisk/voicemail/default/$parts[6]/Old/*.txt>;
                $numNew = $#newFiles + 1;
                $numOld = $#oldFiles + 1;
                #this is the ternary operator fancy way of doing if (($#newFiles +1) != 0) { $hasNew = "yes"; } else { $hasNew = "no"; }  
                $hasNew = (($#newFiles + 1) != 0) ? "yes" : "no";
                $length = 34;
                $length += length $numNew;
                $length += length $hasNew;
                $length += length $numOld;
                #the spacing change is necessary here or it will screw up the sip packet
                $message = "NOTIFY sip:$parts[6]\@$host SIP/2.0
Via: SIP/2.0/UDP $host:$port
From: <sip:asterisk\@$localhost>
To: <sip:$parts[6]\@$host>
Contact: <sip:$parts[6]\@$host>
Call-ID: 4d61cf9e505d40e905032a18329d61ec\@$host
CSeq: 1 NOTIFY
User-Agent: VoiceMail
Event: message-summary
Content-Type: application/simple-message-summary
Content-Length: $length\n\n
Messages-Waiting: $hasNew
Voicemail: $numNew/$numOld\n";
                $file = "/home/pciadmin/mwi/tmp/$parts[6]";
                open MYFILE, "+>$file";
                print MYFILE $message;
                close(MYFILE);
                exec("sipsak shoot -a number4 -f /home/pciadmin/mwi/tmp/$parts[6] -s sip:$parts[6]\@$host:$port");
                #I was sleeping here and deleting the file, but i decided that I liked having the last sip packet sent to the host 
                #sleep 1;
                #unlink($file);
        }
}


this is just like Method 2 only the events happen off the file system changes so theoretically any voicemail system could be adapted to use this as long as you can run a couple of perl scripts
I did it this way because the original method described in method 2 did not suit my particular situation

I hope this helps someone like Andreas Granig's solution helped me

load testing on this script revealed 10,000 iterations of the script took approx. 4.5 seconds on a p3 1.2 with a 1gig of ram
Linux asterisk-ser 2.6.26-2-686 #1 SMP Thu Mar 26 01:08:11 UTC 2009 i686 GNU/Linux


Asterisk and SER on same box


>If Asterisk is directed to speak SIP on port 5061 and SER
>remains on port 5060, then how do you get Asterisk to talk
>to SER and vice versa?

It is something like this:
Asterisk extensions.conf:

[globals]
SERADDRESS=XXX.XXX.XXX.XXX:5060

[context]
exten => <yourexten>,1,Dial(SIP/${EXTEN}@${SERADDRESS},20,r)

In ser.cfg:

if (method == "INVITE") {
if (uri =~ "sip:1[0-9]{10}@*"){
log(1, "Forwarding to Asterisk\n");
rewritehostport("XXX.XXX.XXX.XXX:5061");
t_relay();
break;
}
}

(Documentation in SER admin guide: http://www.iptel.org/ser/doc/seruser/seruser.html)
3. Configure Asterisk as PSTN gateway. I haven't experience in this point.

Intro on differences between Asterisk and SER

by Alex Barnes

Many people say that it allows * to scale better for SIP. For example
assuming your SIP proxy is stateful the proxy will handle all
retransmissions / redirections / register lookups / call logging / ????,
all of which would be hidden from the *.

Multiple registrations:
Asterisk doesn't support multiple registrations. A registrar proxy
will be able to do this, allowing such things as forking (sequential /
parrellel / combinations of both).

Grey Areas (Functionality that crosses over between * and a proxy)

CPL:
Any proxy worth its salt will have a CPL engine built in
allowing some pretty powerful scripting of incoming / outgoing calls on
a individual user basis.

Application Servers:
A proxy may also be an application server. Which could be used
to make any number of technologies available. For example Ubiquity make
a HA SIP App Server that can do pretty much anything including RMI
client/server apps, SOAP, link with Web Application Servers (Websphere /
Weblogic), Java Eventlets that let you write your own interfaces using
our SIP SDK's for call handling.

HOWEVER

I don't think that Asterisk is quite ready to support all live
deployment scenarios that include a 3rd party SIP proxy.
One problem I ran into was Asterisk does not handle looped back calls.

For example a call comes in over PSTN to Asterisk, Asterisk forwards to
your SIP registrar proxy, Registrar does a lookup on the SIP address and
finds that the user is register'd to an analogue phone.
If the SIP registrar redirected using a 3xx response the * will play
along happily, but if the proxy wishes to stay in the loop (maybe you
have a billing application running on it) it would add a Record-Route
header to the SIP request , to say it wishes to receive all subsequent
messages for this call, and then proxy back to the *. The * will ignore
this INVITE totally.
If the user had been registered to a proper SIP end point then the loop
back wouldn't have happened and this works a treat.


Load balancing with SER

See discussion here: http://article.gmane.org/gmane.comp.telephony.pbx.asterisk.user/162042
Partial quote:

"SER/OpenSER can get around call forwarding/transfer problems. You just need
to account for those SIP dialogue's that can be problematic, and bypass
using the dispatcher module for those situations.

One thing to remember is to replicate usr-loc info that is cached in memory,
otherwise load-balancing for INVITE's will fail if passed to a proxy that
did not receive the REGISTER request for sending party. The standard
t_replicate() function only supports replication between two SER/OpenSER
proxies, so if you are looking to add in any more, you will need a more
manual approach. OpenSER 1.1.0 actually offers the ability to operate
completely out of a database, even for usr-loc, which could work for you.

Other approaches for load balancing include DNS round-robin techniques, and
separate software or hardware appliances dedicated to load distribution. I
have successfully worked with Foundry ServerIron's, and Vovida's Open Source
load-balancing proxy, in the past."

Example: SER, Asterisk and Lucent TNT

by Michael Shuler
You can do what we did and setup 2 SER servers which are load balanced by a Foundry ServerIron XL (you could use UltraMonkey for free if you prefer). The 2 SER machines handle the REGISTER messages, NAT and final delivery to the VoIP devices and to the media gateways. The SER machines don't know what to do with a call they only know to hand it over to Asterisk for routing/CLASS features or whatever you want the call to do. You then have a separate set of Asterisk boxes that are nothing but media gateways/transcoders that have the PRI cards in them. We don't actually use Asterisk as media gateways in our setup we use the Lucent TNTs but it accomplishes the same thing but on a much larger scale. As far as sharing the common configs we use http://svn.asteriskdocs.org/res_data/ to read all of our configs (sip.conf, extensions.conf, etc.) live from a MySQL database. Just apply the patch and go.

So far we have seen no limit as to the scalability of this setup. If the 2 SER servers get overloaded we just add another. If the Asterisk routing servers get overloaded we just add another. IF we run out of PRI's we add another TNT and more PRI's from our Plexus 9000 switch. So the system in theory has no real-world limits.

Here is the sample configuration for SER.

Example TeleSIP

Q: Are you aware of any documentation on how to configure SER to be a front-end to Asterisk?

A: At TeleSIP we run a cluster of several geographically distributed SER Servers that hande all our SIP Routing. SER is a robust, fast and stable platform which has worked flawlessly for us. We use * as our company PBX and PSTN Gateway. Basically what you need to do is to devise a numbering plan so that SERs routing logic can forward the call to * when it needs to.

R: Another example can be found in the SER handbook, found on IPtel.org. The
example mentions how to use SER as a frontend to a Cisco PSTN gateway, but also applies to using SER as a frontend to Asterisk.

See also



Go back to Asterisk administration
Created by: JustRumours, Last modification: Wed 16 of May, 2012 (13:56 UTC) by feptias
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+