Thursday, July 10, 2008

Asterisk Cookbook

We've been trying to get the Asterisk Cookbook going. It's the same format as other O'Reilly cookbooks - practical instructions for specific problems posted as recipes, just like a cookbook you'd use in the kitchen (at least that's what people usually do with them).

I haven't contributed much but I have an excuse - I don't really work with Asterisk that much anymore. So, a couple of days ago I asked the other authors and editors if we could widen the scope of the book to include some of my favorite technologies. Anyone that reads this blog knows what that means - Cisco, OpenSER, etc. I plan on writing quite a bit about OpenSER. As I said in my OpenSER book review, OpenSER needs more press and documentation. Let's work on that!

I've now contributed three recipes! My SIP DoS/DDoS mitigation script and a couple OpenSER scripts. Some of the OpenSER stuff is a little obscure and probably won't make it to the final book. I'll be adding more OpenSER, Cisco, and SIPp stuff over the next days/weeks/months. Keep checking here and there for updates.

Oh, and if you feel like you have something to add, get a hold of one of the authors (myself, Jim, Leif, Matt, Jared, etc) and we can figure out how to get you an account on the wiki.

Book Review: Building Telephony Systems with OpenSER

I've been looking for and wondering about an OpenSER book for quite some time...

Everyone knows Asterisk is king when it comes to anything open source VoIP or telephony. OpenSER rocks but it just seems so, well, hardcore.

I can't imagine anyone walking into a Borders or Barnes and Noble, grabbing a book about OpenSER and cuddling up in one of those comfy, over-stuffed chairs on a rainy afternoon for some reading. Ok, I don't know anyone that does that anyway, and certainly not anyone with a book about OpenSER. I don't know about you but my tech books always end up getting rammed into my carry on for reading during "electronics prohibited" periods of air travel. That's all the time I care to dedicate to dead tree reads. But hey, it beats SkyMall (Jim Gaffigan: "Hey buddy, I work for SkyMall and I don't appreciate you jabbing us").

Bringing this back into focus (and on topic), is there a market for an OpenSER book? I've worked with two publishing companies in the past doing various amounts of writing and technical reviewing. Mostly O'Reilly but lately another company: Packt Publishing. Well, Packt decided there was a market for an OpenSER book and they decided to publish one. It's called Building Telephony Systems with OpenSER.

I found out about this book and knew I had to read it. What would an OpenSER book look like? What OpenSER features would be explored? What would it cost? What would it smell like? Ok, I'm just kidding about that last one but I was very interested.

I happened to be working on a couple of Packt Publishing projects at the time. I thought I'd contact one of my editors to see if they could hook me up. Turns out the book had already gone to press but they were willing to send me one. Cool!

Before I go any further I need to tell you: I won't be bought and I'm not easily influenced. Just because I've worked with Packt in the past doesn't mean I'm going to spare them any criticism or cut them any slack. If anything I'll go a little harder on them because they usually know how to get good authors and reviewers (me). ;) (Kidding, of course).

So they sent me a book. It's 295 pages and written by Flavio E. Goncalves. Flavio is a Brazilian that runs VoIP training in Brazil. Florianopolis, to be exact. Florianopolis is gorgeous. If you ever go to Brazil check it out. Hey, while you're there take an OpenSER training class from Flavio and get your company to pay for the whole thing!

Anyways, this is where my criticism starts to come in... I'm not one of these American English Nazis (does that make any sense?) that stands in line at the grocery store and freaks out when someone speaks Spanish or any other foreign language. However, I do believe that language exists as a mechanism to effectively communicate between people and sometimes that can be a little tricky even between two speakers of the same language. How many misunderstandings have you had with your friends, relatives, strangers etc while speaking the same language?

Brazilians speak Portuguese and I love it. It's one of the best sounding languages around. Being Brazilian, Flavio's first language is of course, Portuguese. It's also the language this book (Building Telephony Systems with OpenSER) was originally written in. My understanding from reading the book is that the book was developed out of Flavio's original (Portuguese) training course work and later translated to English. This makes for some very interesting and (sometimes) difficult to understand English language usage. There are several instances in the book that are difficult to follow because the language is, well, awkward. It looks like there was a proofreader... Maybe his style is different from mine but I'm pretty sure most people agree with me.

Part of me feels like this criticism is unfair and I wrestled with even mentioning it. Here's my chance to elaborate on this and explain myself.

Neither the author, editor, nor reviewers are native English language speakers yet this is what the book was written in. That's amazing to me. These people, in addition to being remarkably talented in their respective fields (publishing, technology) can all speak multiple languages and work on a team, around the world (India, Romania, Brazil) in a second language. The world is flat, my friend.

I feel like I can barely work and speak English half the time. Most Americans are the same way. We're all lazy, fat, SUV driving slobs that grunt back and forth in something that resembles English (which is already pretty "ugly"). Ok it's not that bad but that's what it's often made out to be... Anyone ever seen Idiocracy?

So for a technical book, my main criticism is English language usage and that's not even that bad. So far they're doing pretty well! On to the technical stuff...

I thought the book did a great job explaining the use of various OpenSER modules and OpenSER scripting in general. I also like how Flavio introduced readers to the various (relevant) SIP RFCs along the way. In working with OpenSER and SIP in general I can't stress how important this is. Many SIP platforms isolate you from the RFCs as much as possible. Everything is taken care of and it magically works (even with Asterisk when compared to OpenSER). With OpenSER this is not the case. You better know your RFCs. You better know the difference between components in a SIP network (Proxy, UAC, UAS, B2BUA, etc). You better know some core aspects of RFC3261 (stateful vs. stateless, strict routing, loose routing, methods, dialogs, domains, etc). Flavio isn't afraid to present this to the reader and he does it in a way that doesn't come across as snobby. Depending on the situation I've been known to quote RFCs and sections before. I probably (almost always) end up looking like a jerk but sometimes, hey, it needs to be done!

While reading I was disappointed to see so much focus on MediaProxy. I don't like MediaProxy. It's written in Python. Yuck. Enough said. I kept reading and by the end of the book Flavio admitted the mistake of more or less ignoring RTPProxy and agreed it was mostly superior. Bravo! No one knows everything, not even the guys that write the books. It was refreshing to see this in print. Once again, well done.

A couple of specific (nit picky) problems... The Asterisk config for a PSTN gateway on pg. 147 is suspect. The type doesn't make it clear which file you are working in and I doubt anyone would really use that SIP configuration in production. There's also no Zaptel config. I know this isn't an Asterisk book (there are plenty of those, the best one is free) but there should at least be a pointer to an online resource for Asterisk/Zaptel configuration or something.

The same thing goes for the Cisco config. If you look closely you'll see the dial-peer uses sip-notify for dtmf-relay. No one uses this and we certainly haven't configured OpenSER for it. Again, it's nit picky but some user could end up pulling all of his hair out trying to get this to work.

I didn't go over the OpenSER script bracket by bracket but it looked pretty good. That's even tougher to comment on because it's practically a programming language and no programmer ever completely loves the way someone else wrote something. That's just how it goes.

Overall, this is a very good book and it deserves to do well, for Flavio, everyone at Packt, OpenSER and the community in general. People who should be running OpenSER aren't. Hopefully this book can help change that!

Thank you to Flavio, the OpenSER team, and everyone at Packt Publishing!

Monday, July 7, 2008

An update on SIP DoS mitigation

After spending a couple of hours on the VoIP User's Conference last week I thought I'd keep working on my SIP DoS/DDoS script a bit and get it to the point where I'd like to run it on some of my systems (if only to collect statistics).

The new version includes several new features, the most exciting (and certainly controversial) are changes to the string pattern matching for SIP requests. I now block ALL tel: URIs by default. I don't like tel: URIs. I think they're anti-SIP and you shouldn't use them. Now my script won't let you (unless you disable it, of course).

Anyways, I had to do this because (as I've already mentioned), I changed the way pattern matching runs on SIP requests. Two big changes:

1) Support a (configurable) offset for searches into the packet.
2) Update the SIP method matches to match "$METHOD sip:"

First of all, we now (by default) only search the first 65 bytes of the packet. That should be more than enough to search the first line for the SIP method and URI. Speaking of URI, I now match the URI along with the method to prevent false matches. Before we were only matching on the method and it was causing some false positives because of things like the Allow: header (where all of the supported methods are listed).

We'll see how this goes.

One thing I wanted to bring up in the VoIP User's call last week but failed to do so is the possible use of OpenSER to protect Asterisk (and other systems) from attack. In addition to supporting cool things like SIP message length filtering (msg:len) you can also use the pike module for some basic (but slightly more intelligent) SIP rate limiting. Of course then you need to support an OpenSER config, which a lot of people don't want to do...

What else is new in the script? Basic support for udp and/or tcp, configurable bursting, fixes to the FORWARD support and more. Check it out, it's free!

Wednesday, July 2, 2008

SIP DoS/DDoS Mitigation

An interesting thread came up on Asterisk-Users the other day...

Someone had problems with some miscreant attempting (and apparently succeeding) to bruteforce a SIP account on his Asterisk system.

That's a problem. Asterisk currently has no means to protect against any type of SIP flooding/bruteforce/DoS (other than running out of resources/crashing). That's ok because some people (like myself) would argue that these types of attacks are best handled via other means...

Like the kernel, or preferably the kernel of a completely seperate box.

It got me to thinking - maybe I could whip up a script using some of the cool stuff in iptables/netfilter to mitigate these SIP DoS attacks in the kernel. I don't have a ton of time to elaborate on the script but for now here it is:

http://admin.star2star.com/sipdos

It's not great. It's not very SIP-specific. Who knows how accurate/effective/resource intensive it is. It hasn't been tested (much). For all I know, it will just make things worse. However, I think it is a step in the right direction and hopefully one of many tools that can be used to protect Asterisk and other SIP/VoIP systems.

By the way, I call it "SIP DoS Mitigation" because with any large enough DDoS attack, you are toast. ..

Speaking of other tools... We're all going to celebrate America's birthday this Friday by getting together on a conference call/IRC to talk over some of these issues with the VoIP User's Conference. Hear you there?

Monday, March 24, 2008

Q.931 Problems - Solved, sort of

It's been a long day so I'll keep this one short... Upgrading to Asterisk (libpri|zaptel) 1.4 solved my Cisco AS5350XM problem. However, now I've got a new one.

Zaptel 1.4 required a new version of Wanpipe. The new version of Wanpipe does not seem to work with mixed Ts. My T1 happens to have 12 DS0s for PRI and 12 for PPP.

I'm currently working with Sangoma to get this resolved so I can have it all!

Friday, March 21, 2008

Why I (and presumably other people) hate telecom

Q.931.

That's it. Q-freaking-9-3-1. I suppose it's not bad considering it was developed so long ago, but really for me this protocol (and all it stands for) is why so many people (myself included) get frustrated with telecom.

I spent two hours today trying to get a call up (over PRI) from an Asterisk system to a Cisco gateway. I covered all of the basics:

Asterisk - pri_net - check
Cisco - pri_cpe - check
Asterisk - master clocking - check
T1 params - B8ZS, ESF - check
Switchtype - national/NI2 - check
D chan - 24 - check
T1 crossover cable - check

Voila! D channel up in no time (seriously, five minutes). Try to send a call - SURE, everything looks good (including caller id). The call gets setup and once there is about 1 sec of audio it gets torn down. Hmmm... Granted I am running SIP on the other side of the Cisco gateway (AS5350XM) so I start there. Let's face, if you're reading this blog you know I deal with SIP quite a bit. I'd much rather look at it than the alternative - Q.931...

Sure enough everything looks good on the SIP side. Perfect, actually. Ok fine, I guess we're going to have to go Q.931. I enable Q.931 debugging:

Asterisk:
asterisk -r
pri debug span 3

Cisco:
debug isdn q931
term mon (to log to my SSH session)

Try the call again. Same thing - one second of audio, disconnect. Here is what I get:

Cisco debug:

Mar 21 23:13:45.307: ISDN Se3/0:23 Q931: Applying typeplan for sw-type 0xD is 0x2 0x1, Calling num 5043223199
Mar 21 23:13:45.311: ISDN Se3/0:23 Q931: Applying typeplan for sw-type 0xD is 0x2 0x1, Called num 19412340001
Mar 21 23:13:45.311: ISDN Se3/0:23 Q931: TX -> SETUP pd = 8 callref = 0x00A3
Bearer Capability i = 0x8090A2
Standard = CCITT
Transfer Capability = Speech
Transfer Mode = Circuit
Transfer Rate = 64 kbit/s
Channel ID i = 0xA18381
Preferred, Channel 1
Display i = 'Pcom2'
Calling Party Number i = 0x2180, '5043223199'
Plan:ISDN, Type:National
Called Party Number i = 0xA1, '19412340001'
Plan:ISDN, Type:National
Mar 21 23:13:45.323: ISDN Se3/0:23 Q931: RX <- CALL_PROC pd = 8 callref = 0x80A3
Channel ID i = 0xA98381
Exclusive, Channel 1
Mar 21 23:13:46.371: ISDN Se3/0:23 Q931: RX <- CONNECT pd = 8 callref = 0x80A3
Channel ID i = 0xA98381
Exclusive, Channel 1
Progress Ind i = 0x8182 - Destination address is non-ISDN
Mar 21 23:13:46.371: ISDN Se3/0:23 Q931: TX -> CONNECT_ACK pd = 8 callref = 0x00A3
Mar 21 23:13:46.379: ISDN Se3/0:23 Q931: RX <- STATUS pd = 8 callref = 0x80A3
Cause i = 0x80E2 - Message not compatible with call state or not implemented
Call State i = 0x0A
Mar 21 23:13:46.379: ISDN Se3/0:23 Q931: TX -> RELEASE pd = 8 callref = 0x00A3
Cause i = 0x80E408 - Invalid information element contents
Mar 21 23:13:46.403: ISDN Se3/0:23 Q931: RX <- RELEASE_COMP pd = 8 callref = 0x80A3
Cause i = 0x8190 - Normal call clearing

Asterisk debug:
< Protocol Discriminator: Q.931 (8) len=50
< Call Ref: len= 2 (reference 164/0xA4) (Originator)
< Message type: SETUP (5)
< [04 03 80 90 a2]
< Bearer Capability (len= 5) [ Ext: 1 Q.931 Std: 0 Info transfer capability: Speech (0)
< Ext: 1 Trans mode/rate: 64kbps, circuit-mode (16)
< Ext: 1 User information layer 1: u-Law (34)
< [18 03 a1 83 81]
< Channel ID (len= 5) [ Ext: 1 IntID: Implicit, PRI Spare: 0, Preferred Dchan: 0
< ChanSel: Reserved
< Ext: 1 Coding: 0 Number Specified Channel Type: 3
< Ext: 1 Channel: 1 ]
< [28 05 50 63 6f 6d 32]
< Display (len= 5) [ Pcom2 ]
< [6c 0c 21 80 35 30 34 33 32 32 33 31 39 39]
< Calling Number (len=14) [ Ext: 0 TON: National Number (2) NPI: ISDN/Telephony Numbering Plan (E.164/E.163) (1)
< Presentation: Presentation permitted, user number not screened (0) '5043223199' ]
< [70 0c a1 31 39 34 31 32 33 34 30 30 30 31]
< Called Number (len=14) [ Ext: 1 TON: National Number (2) NPI: ISDN/Telephony Numbering Plan (E.164/E.163) (1) '19412340001' ]
-- Making new call for cr 164
-- Processing Q.931 Call Setup
-- Processing IE 4 (cs0, Bearer Capability)
-- Processing IE 24 (cs0, Channel Identification)
-- Processing IE 40 (cs0, Display)
-- Processing IE 108 (cs0, Calling Party Number)
-- Processing IE 112 (cs0, Called Party Number)
> Protocol Discriminator: Q.931 (8) len=10
> Call Ref: len= 2 (reference 164/0xA4) (Terminator)
> Message type: CALL PROCEEDING (2)
> [18 03 a9 83 81]
> Channel ID (len= 5) [ Ext: 1 IntID: Implicit, PRI Spare: 0, Exclusive Dchan: 0
> ChanSel: Reserved
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 ]
-- Accepting call from '5043223199' to '19412340001' on channel 0/1, span 3
-- Executing Wait("Zap/49-1", "1") in new stack
-- Executing Answer("Zap/49-1", "") in new stack
> Protocol Discriminator: Q.931 (8) len=14
> Call Ref: len= 2 (reference 164/0xA4) (Terminator)
> Message type: CONNECT (7)
> [18 03 a9 83 81]
> Channel ID (len= 5) [ Ext: 1 IntID: Implicit, PRI Spare: 0, Exclusive Dchan: 0
> ChanSel: Reserved
> Ext: 1 Coding: 0 Number Specified Channel Type: 3
> Ext: 1 Channel: 1 ]
> [1e 02 81 82]
> Progress Indicator (len= 4) [ Ext: 1 Coding: CCITT (ITU) standard (0) 0: 0 Location: Private network serving the local user (1)
> Ext: 1 Progress Description: Called equipment is non-ISDN. (2) ]
-- Executing MusicOnHold("Zap/49-1", "") in new stack
-- Started music on hold, class 'default', on channel 'Zap/49-1'
< Protocol Discriminator: Q.931 (8) len=5
< Call Ref: len= 2 (reference 164/0xA4) (Originator)
< Message type: CONNECT ACKNOWLEDGE (15)
> Protocol Discriminator: Q.931 (8) len=12
> Call Ref: len= 2 (reference 164/0xA4) (Terminator)
> Message type: STATUS (125)
> [08 02 80 e2]
> Cause (len= 4) [ Ext: 1 Coding: CCITT (ITU) standard (0) 0: 0 Location: User (0)
> Ext: 1 Cause: Wrong message (98), class = Protocol Error (6) ]
> [14 01 0a]
> Call State (len= 3) [ Ext: 0 Coding: CCITT (ITU) standard (0) Call state: Active (10)
< Protocol Discriminator: Q.931 (8) len=10
< Call Ref: len= 2 (reference 164/0xA4) (Originator)
< Message type: RELEASE (77)
< [08 03 80 e4 08]
< Cause (len= 5) [ Ext: 1 Coding: CCITT (ITU) standard (0) 0: 0 Location: User (0)
< Ext: 1 Cause: Invalid information element contents (100), class = Protocol Error (6) ]
< Cause data 1: 08 (8)
-- Processing IE 8 (cs0, Cause)
-- Channel 0/1, span 3 got hangup
-- Stopped music on hold on Zap/49-1
== Spawn extension (pri-in, 19412340001, 3) exited non-zero on 'Zap/49-1'
NEW_HANGUP DEBUG: Calling q931_hangup, ourstate Null, peerstate Release Request
> Protocol Discriminator: Q.931 (8) len=9
> Call Ref: len= 2 (reference 164/0xA4) (Terminator)
> Message type: RELEASE COMPLETE (90)
> [08 02 81 90]
> Cause (len= 4) [ Ext: 1 Coding: CCITT (ITU) standard (0) 0: 0 Location: Private network serving the local user (1)
> Ext: 1 Cause: Normal Clearing (16), class = Normal Event (1) ]
NEW_HANGUP DEBUG: Calling q931_hangup, ourstate Null, peerstate Null
NEW_HANGUP DEBUG: Destroying the call, ourstate Null, peerstate Null
-- Hungup 'Zap/49-1'
s2s-srq-co*CLI>

Everytime I have to look at Q931 I just cringe. I MEAN CRINGE. I hate it. Look at it - all of these goofy messages, number plans, and the worst - IEs (Information Elements). Compare this to SIP (there are plenty of examples on this blog). I guess I just take it for granted. I can fire up ngrep on a network interface, turn on interpretation of carriage returns/linefeeds and go to town with something that just makes more sense. Sure to some people it probably still looks like gibberish but anyone that complains certainly hasn't seen much Q.931!

Let's look at my current problem... It appears that once the call is setup, Asterisk sends a CONNECT message, to which the Cisco quickly acknowledges with a CONNECT ACKNOWLEDGMENT (big surprise there). Here's where things get a little strange... The next message is from Asterisk (STATUS) complaining with "Message not compatible with call state or not implemented". That is pretty helpful, I'll give them that. However, what's not compatible about a standard, simple CONNECT ACK?!?!

This is wear I start to get angry. I'd like to see what's going on a little bit more. I know I have some flexibility with my IEs, for example. If I turn up the debug high enough in Asterisk I can see which IEs Asterisk identifies. I just can't see the data. From a debug standpoint, Cisco appears to give me even less. Cisco does, however, give me some pretty decent control of newer and less than standard IEs to send (and to a lesser extent, receive). That's gotta have something to do with it, I'm sure. It's even telling me "invalid information element contents". Too bad I can't actually see the IE content... Being severely limited with the tools at hand, I began to cycle through all of my IE, number plan, etc options on both sides. I even got lazy at one point and tried to set my switchtype to dms100! No dice.

Want to know the craziest part about all of this? I've done this several times before. I've brought up many a PRI to carriers, with all kinds of switchtypes, b/d channel configs, into all kinds of equipment (including Asterisk and Cisco). I've gone from Asterisk PRI -> Cisco PRI, Cisco PRI -> Cisco PRI, Asterisk PRI -> Asterisk PRI and every other combination you could imagine (although I think I covered all of them). I've never really had problems, although whenever there is a problem it means going through lines and lines of less-than-helpful Q.931 messaging to identify the problem, which gets me back to my point.

That's just the problem with telecom. It's old, slow, and inflexible. If this were a problem with SIP I could grab the packet stream with tcpdump and load it into Wireshark if I got really desperate (I'm rarely that desperate). I could watch it in real time with ngrep, complete with regex matching on payload and BPF syntax. I could try multiple SIP libraries and multiple clients. I could even tap into the WEALTH of information about SIP, including the various RFCs. Sure I know there are a lot of them but hey, at least you know where to look. I could even try different hardware very easily because hey, you don't need a $500 T1 card to play with SIP. Heck you don't even need a network. VmWare or even good ol' fashioned lo0 work just fine.

How can I do this with ISDN? Buy a T-Berd? No thanks. So here it is, Friday night, and I'm obsessing over the PRI that kicked my ass today. Anyone have any ideas?

Wednesday, March 19, 2008

More OpenSER Work

I've been working with OpenSER a lot over the last couple of weeks. I upgraded to 1.2.3, enabled TLS support, and implemented some really cool new features:

- Serial forking class
- English error messages
- Numerous code cleanups
- Much more

I'll try to find out how much of this I can share and get back to you. In the meantime I'm having a problem calling next_gw() from the LCR module. I suspect it's a db problem but I can't be sure yet...

Friday, February 22, 2008

Obscure RFC 3398 Support with OpenSER

I hate SS7. Let me say that again. I HATE SS7. I mean it's cool and everything, but there are parts of it that are unnecessarily confusing...

For instance, this week I got very confused over use of the term "cic" in telco-speak. I had thought cic was "circuit identification code". So, when one of our partners asked me to support embedding the cic in the incoming SIP INVITE, I freaked out. Why is that my responsibility? Why should my proxy ("class 5 switch") have to maintain state of individual DS0s on YOUR media gateways. This sucks! I bitterly started reading RFC 3398 (particularly section 7.2.1.1) and gave up halfway through it, becoming frustrated with the overall language of the section. After all, keeping track of DS0s just isn't my thing, and that's what CICs are about, right?

Turns out I was wrong. Keeping tracks of CICs is my thing. The problem is, these CICs are "Carrier Identification Codes", not "Circuit Identification Codes". I know everyone in networking and telecom loves to have an acronym for everything, but for GODs SAKE PEOPLE don't use the same acronym in the same context. Reading on in RFC 3398, they specifically warn for this confusion:

..
 If the 'cic=' parameter is present in the Request-URI, the
gateway SHOULD consult local policy to make sure that it is
appropriate to transmit this Carrier Identification Code (CIC, not to

be confused with the MTP3 'circuit identification code') in the IAM;

..

Good point. Why didn't you say something sooner? So, now it turns out all I have to do is append a cic= (CARRIER identification code) parameter to the SIP RURI (request uniform resource identifier) on the outbound INVITE to the SIP <-> SS7 gateway. No problem. Thanks to OpenSER, module textops, and subst_uri, this is all I need to do:

avp_printf("$avp(s:cic)", "+15062"); # Set the cic value in an AVP
if (subst_uri('/^sip:([0-9]+)@(.*)$/sip:\1;cic=$avp(s:cic)@\2/i')) {
xlog("Added CIC $avp(s:cic) to RURI"); # tell us about it
};

Here is the INVITE going out to the gateway (cic in red):

U a.b.c.d:5060 -> w.x.y.z:5060
INVITE sip:14145551212;cic=+15062@w.x.y.z:5060 SIP/2.0.
Record-Route: .
Via: SIP/2.0/UDP a.b.c.d;branch=z9hG4bKf1e2.8a4d41b6.0.
Via: SIP/2.0/UDP e.f.g.h:5060;branch=z9hG4bK4e28b419;rport=5060.
From: "Polycom 320" ;tag=as477acc5f.
To: .
Contact: .
Call-ID: 343b661709e271c30bdfafe923a82adb@e.f.g.h.
CSeq: 103 INVITE.
User-Agent: Star2Star StarBox astlinux-s2s-1438-net4801.
Max-Forwards: 69.
Remote-Party-ID: "Polycom 320" ;privacy=off;screen=no.
Date: Fri, 22 Feb 2008 19:48:44 GMT.
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY.
Content-Type: application/sdp.
Content-Length: 265.
.
v=0.
o=root 6183 6184 IN IP4 e.f.g.h.
s=session.
c=IN IP4 e.f.g.h.
t=0 0.
m=audio 19770 RTP/AVP 18 0 101.
a=rtpmap:18 G729/8000.
a=fmtp:18 annexb=no.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.
a=silenceSupp:off - - - -.

Yeah, yeah, you like that?!?

I'm still not sure of the actual CIC format... That isn't EXACTLY what is shown in section 8.2.1.1 of RFC 3398 but it does look like what Cisco expects from their docs I've read (from the BTS 10200). After all, this particular SIP <-> SS7 gateway is made by them (PGW 2200).

Obviously you can get fancy with that and do all sorts of conditionals and DB calls to get the CIC, only append it on certain calls, different CICs for different sources, destinations, etc but the point is you can tweak up the RURI and insert it. I still haven't tested this against Cisco but I'm pretty sure it will work...

After I sorted out my "CIC confusion" it took me less than 30 minutes to implement this. Thanks OpenSER. You make SS7 a lot easier to deal with (as long as SIP is involved)!

Wednesday, February 20, 2008

Missing SIP traffic?

SIP can be cool because it resembles HTTP. OpenSER and SER are cool because they are so powerful. For instance, in OpenSER you don't need to authenticate calls. Or you can specify which request URIs should be challenged with an auth (or which method types, like REGISTER). This is usually done like so:

if (is_method("INVITE")) {

if (uri=~"^sip:1000@") {
rewritehostport("192.168.1.1:5060"); #set destination
route(1); #t_relay, etc is in route(1)
}

if (!allow_trusted()) {
if (!proxy_authorize("star2star.com","subscriber")) {
proxy_challenge("star2star.com","0");
return;
} else if (!check_from()) {
sl_send_reply("403", "Use From=ID");
return;
};

xlog("Creds are good\n");
consume_credentials();

};

if (uri=~"^sip:1[0-9]{10}@") {
route(5); #goto LCR
return;
};
};

So, in this example any SIP endpoint that can reach this proxy can hit RURI:1000 and be forwarded to the voicemail server with no authentication. As we step through this example, the only other URIs that match are after the allow_trusted or proxy_authorize checks. Basically, your source IP address has to be in the trusted table or you have to successfully respond to a 407 Proxy Authentication Required from the proxy.

I've seen this work perfectly between an Asterisk client and OpenSER hundreds of times. Most of the time it works. MOST OF THE TIME. I've noticed a scenario where it does not work, and I am struggling to figure out why...

Here's the architecture:

User's Phone -> Asterisk --(internet)--> OpenSER -> Misc. other systems

Like I said, normally this works and it looks like this (get ready for some SIP):

#
U a.b.c.d:5060 -> e.f.g.h:5060
INVITE sip:9415551212@e.f.g.h SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK2e8b0432;rport.
From: "User Phone" ;tag=as3474f6c4.
To: .
Contact: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 102 INVITE.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Date: Tue, 05 Feb 2008 18:24:11 GMT.
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY.
X-s2s-region: 1.
Content-Type: application/sdp.
Content-Length: 216.
.
v=0.
o=root 1429 1429 IN IP4 a.b.c.d.
s=session.
c=IN IP4 a.b.c.d.
t=0 0.
m=audio 19424 RTP/AVP 0 101.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.
a=silenceSupp:off - - - -.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 100 Trying.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK2e8b0432;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 102 INVITE.
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4363 req_src_ip=a.b.c.d req_src_port=5060 in_uri=sip:9415551212@e.f.g.h out_uri=sip:9415551212@e.f.g.h via_cnt==1".
.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 407 Proxy Authentication Required.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK2e8b0432;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=0dd4490c85a9eb8d48ff967a8700cef0.fcb4.
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 102 INVITE.
Proxy-Authenticate: Digest realm="star2star.com", nonce="valid_nonce".
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4363 req_src_ip=a.b.c.d req_src_port=5060 in_uri=sip:9415551212@e.f.g.h out_uri=sip:9415551212@e.f.g.h via_cnt==1".
.

#
U a.b.c.d:5060 -> e.f.g.h:5060
ACK sip:9415551212@e.f.g.h SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK2e8b0432;rport.
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=0dd4490c85a9eb8d48ff967a8700cef0.fcb4.
Contact: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 102 ACK.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Content-Length: 0.
.

#
U a.b.c.d:5060 -> e.f.g.h:5060
INVITE sip:9415551212@e.f.g.h SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK57af1f44;rport.
From: "User Phone" ;tag=as3474f6c4.
To: .
Contact: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 103 INVITE.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Proxy-Authorization: Digest username="cpesource", realm="star2star.com", algorithm=MD5, uri="sip:9415551212@e.f.g.h", nonce="valid_nonce", response="valid_response", opaque="".
Date: Tue, 05 Feb 2008 18:24:12 GMT.
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY.
X-s2s-region: 1.
Content-Type: application/sdp.
Content-Length: 216.
.
v=0.
o=root 1429 1430 IN IP4 a.b.c.d.
s=session.
c=IN IP4 a.b.c.d.
t=0 0.
m=audio 19424 RTP/AVP 0 101.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.
a=silenceSupp:off - - - -.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 100 Trying.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK57af1f44;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 103 INVITE.
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4361 req_src_ip=a.b.c.d req_src_port=5060 in_uri=sip:9415551212@e.f.g.h out_uri=sip:9415551212@e.f.g.h via_cnt==1".
.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 100 trying -- your call is important to us.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK57af1f44;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 103 INVITE.
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4361 req_src_ip=a.b.c.d req_src_port=5060 in_uri=sip:9415551212@e.f.g.h out_uri=sip:18135551212@w.x.y.z:5060;transport=udp via_cnt==1".
.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 183 Session Progress.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK57af1f44;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=F6697AC-1DCD.
Date: Tue, 05 Feb 2008 18:24:12 GMT.
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
Server: Cisco-SIPGateway/IOS-12.x.
CSeq: 103 INVITE.
Allow: INVITE, OPTIONS, BYE, CANCEL, ACK, PRACK, COMET, REFER, SUBSCRIBE, NOTIFY, INFO, UPDATE, REGISTER.
Allow-Events: telephone-event.
Contact: .
Record-Route: .
Content-Disposition: session;handling=required.
Content-Type: application/sdp.
Content-Length: 238.
.
v=0.
o=CiscoSystemsSIP-GW-UserAgent 2171 1394 IN IP4 w.x.y.z.
s=SIP Call.
c=IN IP4 w.x.y.z.
t=0 0.
m=audio 18722 RTP/AVP 0 101.
c=IN IP4 w.x.y.z.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 200 OK.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK57af1f44;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=F6697AC-1DCD.
Date: Tue, 05 Feb 2008 18:24:12 GMT.
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
Server: Cisco-SIPGateway/IOS-12.x.
CSeq: 103 INVITE.
Allow: INVITE, OPTIONS, BYE, CANCEL, ACK, PRACK, COMET, REFER, SUBSCRIBE, NOTIFY, INFO, UPDATE, REGISTER.
Allow-Events: telephone-event.
Contact: .
Record-Route: .
Content-Type: application/sdp.
Content-Length: 238.
.
v=0.
o=CiscoSystemsSIP-GW-UserAgent 2171 1394 IN IP4 w.x.y.z.
s=SIP Call.
c=IN IP4 w.x.y.z.
t=0 0.
m=audio 18722 RTP/AVP 0 101.
c=IN IP4 w.x.y.z.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.

#
U a.b.c.d:5060 -> e.f.g.h:5060
ACK sip:18135551212@w.x.y.z:5060 SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK38cd41fe;rport.
Route: .
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=F6697AC-1DCD.
Contact: .
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 103 ACK.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Content-Length: 0.
.

#
U a.b.c.d:5060 -> e.f.g.h:5060
BYE sip:18135551212@w.x.y.z:5060 SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK48cf5abc;rport.
Route: .
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=F6697AC-1DCD.
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
CSeq: 104 BYE.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Proxy-Authorization: Digest username="cpesource", realm="star2star.com", algorithm=MD5, uri="sip:18135551212@w.x.y.z:5060", nonce="valid_nonce", response="valid_response", opaque="".
Content-Length: 0.
.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 200 OK.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK48cf5abc;rport=5060.
From: "User Phone" ;tag=as3474f6c4.
To: ;tag=F6697AC-1DCD.
Date: Tue, 05 Feb 2008 18:24:21 GMT.
Call-ID: 2ad4212700f61c3e1294439f1c72c479@a.b.c.d.
Server: Cisco-SIPGateway/IOS-12.x.
Content-Length: 0.
CSeq: 104 BYE.
.

INVITE comes in, 407 goes out and gets ACKd by remote Asterisk instance, INVITE comes back, this time with a Proxy-Authorization: header attached. The call gets forwarded, setup, and everything is fine.

HOWEVER - some times the 407 doesn't make it back to Asterisk (for whatever reason) and the call dies:

#
U a.b.c.d:5060 -> e.f.g.h:5060
INVITE sip:8135551212@e.f.g.h SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK3beb8c07;rport.
From: "User Phone" ;tag=as664fbdbc.
To: .
Contact: .
Call-ID: 165e2edb63fd81b30e629055245b8b28@a.b.c.d.
CSeq: 102 INVITE.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Date: Tue, 05 Feb 2008 18:22:47 GMT.
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY.
X-s2s-region: 1.
Content-Type: application/sdp.
Content-Length: 216.
.
v=0.
o=root 1306 1306 IN IP4 a.b.c.d.
s=session.
c=IN IP4 a.b.c.d.
t=0 0.
m=audio 19154 RTP/AVP 0 101.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16.
a=silenceSupp:off - - - -.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 100 Trying.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK3beb8c07;rport=5060.
From: "User Phone" ;tag=as664fbdbc.
To: .
Call-ID: 165e2edb63fd81b30e629055245b8b28@a.b.c.d.
CSeq: 102 INVITE.
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4363 req_src_ip=a.b.c.d req_src_port=5060 in_uri=sip:8135551212@e.f.g.h out_uri=sip:8135551212@e.f.g.h via_cnt==1".
.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 407 Proxy Authentication Required.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK3beb8c07;rport=5060.
From: "User Phone" ;tag=as664fbdbc.
To: ;tag=0dd4490c85a9eb8d48ff967a8700cef0.d2fe.
Call-ID: 165e2edb63fd81b30e629055245b8b28@a.b.c.d.
CSeq: 102 INVITE.
Proxy-Authenticate: Digest realm="star2star.com", nonce="valid_nonce".
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4363 req_src_ip=a.b.c.d req_src_port=5060 in_uri=sip:8135551212@e.f.g.h out_uri=sip:8135551212@e.f.g.h via_cnt==1".
.

#
U a.b.c.d:5060 -> e.f.g.h:5060
CANCEL sip:8135551212@e.f.g.h SIP/2.0.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK3beb8c07;rport.
From: "User Phone" ;tag=as664fbdbc.
To: .
Call-ID: 165e2edb63fd81b30e629055245b8b28@a.b.c.d.
CSeq: 102 CANCEL.
User-Agent: Asterisk PBX.
Max-Forwards: 70.
Remote-Party-ID: "User Phone" ;privacy=off;screen=no.
Content-Length: 0.
.

#
U e.f.g.h:5060 -> a.b.c.d:5060
SIP/2.0 483 Too Many Hops.
Via: SIP/2.0/UDP a.b.c.d:5060;branch=z9hG4bK3beb8c07;rport=5060.
From: "User Phone" ;tag=as664fbdbc.
To: ;tag=0dd4490c85a9eb8d48ff967a8700cef0.f74a.
Call-ID: 165e2edb63fd81b30e629055245b8b28@a.b.c.d.
CSeq: 102 CANCEL.
Server: OpenSer (1.1.0-notls (i386/linux)).
Content-Length: 0.
Warning: 392 e.f.g.h:5060 "Noisy feedback tells: pid=4365 req_src_ip=e.f.g.h req_src_port=5060 in_uri=sip:8135551212@e.f.g.h out_uri=sip:8135551212@e.f.g.h via_cnt==71".
.


So, in this scenario the INVITE comes in and OpenSER responds with a 407. The remote endpoint (Asterisk) never receives the 407, gives up on the request, sending a CANCEL after about 60 seconds. At this point I'm not really sure what happens but something loops in OpenSER until Max-Forwards: is exceeded.

We can verify from packet captures on the remote Asterisk system that the 407 is not being received and therefore, Asterisk isn't resending the INVITE with auth.

What's doing on here? We're not seeing any other messages being lost, we're not seeing packet loss, what's going on?

Tuesday, December 11, 2007

What a difference a day makes!

DISCLAIMER - I've been sick for a couple of weeks and after reading my last post, I feel I need to warn you that my writing quality will be sub par until I get over this.... Clearly I'm not running at %100!

Yesterday I was ranting about my frustrations with modern technology. Today I'll be making some apologies.

I wrote my post yesterday after struggling with a Snom 360 for a couple of hours. I came at it today, fresh from my five hours of sleep last night and got it working in 10 minutes. A long time ago while working my first real job at Wisconsin Vision Associates, my co-worker taught me the benefits of a "fresh pair of eyes". I had a tendency to obsessively attack a problem until I solved it. This had been an issue of mine for quite some time. I rarely made it to my first class during high school because I would often stay up until 6am working on some computer problem I was facing. Dave used to remind me to stop and try again later with a fresh pair of eyes.

Looks like that's all I needed. I came in today, tried upgrading the firmware (using the bootloader interrupt method) and the Snom 360 came to life. I had a couple of reasons for testing the Snom 360. First, I need to configure them for Star2Star. Secondly, I wanted to test the Asterisk sip-tlstcp branch. Why TCP for SIP? Why TLS? Why bother?

First of all, SIP is pretty insecure. It's 2007. Everything, everywhere should be encrypted. There's just no excuse for it anymore. People transport some pretty valuable data over the telephone. Their credit card numbers, their banking/identity/medical details, their deepest, most private thoughts. Not the kind of stuff you want just anyone to get their hands on.

If you are using standard VoIP, it's probably SIP. SIP is a signalling protocol, it handles session initiation (hey - Session Initiation Protocol) for media sessions that (typically, but don't have to) use RTP (Realtime Transport Protocol). In a typical call scenario, the source and destination phone numbers, caller name, etc would be transported by SIP. While this data isn't terribly important, it could be valuable to an attacker. Most of the good stuff, however, is transported using RTP. This includes DTMF digits (if using inband or RFC2833 signaling) and audio (your voice, music on hold, heavy breathing, whatever). It's more important to secure RTP. The best standard for this is currently SRTP (Secure RTP). The problem is, like all crypto, there has to be an exchange of keys. How do we do this? Easy - SIP. But what if the SIP channel isn't secure? Ah ha. It needs to be. That's where SIP TLS comes in.

Fine, I'll implement SIP TLS then. Well, in Asterisk you have another problem. TLS (usually) requires TCP. The SIP channel driver in Asterisk doesn't support TCP. Why use TCP for SIP? Isn't that bad, doesn't that mean my voice packets will be delayed/blow up/melt my router? Shame on you! You haven't been paying attention. Your voice uses RTP and even with SIP TCP/TLS that's still UDP (even with SRTP). Don't worry about that. Only the session-type stuff (SIP) will use TCP. Why bother with TCP? Well, first of all, it's cool. Secondly, we get to use TLS. Third, TCP allows for packet fragmentation and (ultimately) will allow for more cool stuff to happen. For instance, if you've got some crazy videophone that supports a million types of sessions, codecs, etc your SIP+SDP infoz could possibly exceed the MTU size of your connection. Bad things will happen.

With this branch of Asterisk, we get all of that cool stuff above with the exception of the actual SRTP implementation. Don't get so greedy! I'm sure it's coming. This is open source, after all. If you don't like it you can ask for your money back and deal with some other vendors.

Anyways, back to the original point. I wanted to test this branch and it had already been tested with all of the other equipment Star2Star uses - Cisco gateways, Polycom phones, other Asterisk systems, etc. I wondered if I could get these Snom phones to work with it. But first I had to get them working with Asterisk and standard SIP/UDP. I did, and a little while later, I got it the Snom to use TCP/TLS. From a message I posted to Asterisk-dev:

*CLI> core show version
Asterisk SVN-group-sip-tcptls-r92242-
/trunk built by kris @ krislap on
a i686 running Linux on 2007-12-10 19:29:26 UTC
*CLI> sip show peer snom


* Name : snom
Secret :
MD5Secret :
Context : default
Subscr.Cont. :
Language :
AMA flags : Unknown
Transfer mode: open
CallingPres : Presentation Allowed, Not Screened
Callgroup :
Pickupgroup :
Mailbox :
VM Extension : asterisk
LastMsgsSent : 32767/65535
Call limit : 0
Dynamic : Yes
Callerid : "" <>
MaxCallBR : 384 kbps
Expire : 3028
Insecure : no
Nat : RFC3581
ACL : No
T38 pt UDPTL : No
CanReinvite : Yes
PromiscRedir : No
User=Phone : No
Video Support: Yes
Text Support : No
Trust RPID : Yes
Send RPID : Yes
Subscriptions: Yes
Overlap dial : No
DTMFmode : rfc2833
ToHost :
Addr->IP : 10.16.5.237 Port 2060
Defaddr->IP : 0.0.0.0 Port 5060
Transport : TLS
Def. Username: snom
SIP Options : (none)
Codecs : 0x4 (ulaw)
Codec Order : (ulaw:20)
Auto-Framing: No
100 on REG : No
Status : OK (25 ms)
Useragent : snom360/7.1.30
Reg. Contact : sip:snom@10.16.5.237:2060;transport=tls;line=1sz3a8qe

*CLI> sip show tcp
Host Port Transport Type
10.16.5.237 2077 TLS Server

Not only did I get this phone to work, I got it to work with some super-cool bleeding version of Asterisk. Heck yeah. Plus, it turns out I really like Snom phones. Maybe even more than Polycom!

I'd like to clear the air about something else too... I was really angry at BMW yesterday. So angry that I made an appointment to test drive a potential new car - a Maserati Quattroporte. It's an Italian thoroughbred. With a Ferrari engine, Pininfarina styling, and a legendary name to boot. A few miles down the road, I realized BMW was the car for me. Don't get me wrong, the Maserati is a really nice car but it has some serious shortcomings. The GPS system looks like 8-bit Nintendo. The DuoSelect transmission revs WAY to high and is too clunky. Two serious problems.

In summary, I have some apologies to make - to Snom, to BMW, and to an entire country - Germany. Over-engineered or not, you're still the best at it.

Monday, December 10, 2007

Modern Technology

VoIP really bothers me sometimes... Why is it that even after YEARS of dealing with this stuff do some things just seem to be ridiculously complicated? For instance - today a Snom 360 arrived. My goal is to get this thing ready to integrate with Star2Star. That means:

  • Remote firmware upgrades
  • No (little) touch provisioning
  • Speed dials, monitoring, etc
I've had this thing on my desk for a little over an hour and the first requirement (firmware upgrade) cannot be met because the damn things HTTP/HTTPS server disappears a few seconds after the phone boots up. WTF? Yes, I am working on this now, I am writing this now, and I am angry now. I've been working with this stuff for years and I am AMAZED it still takes this long to get a phone working. Call this progress (no pun intended)? I don't think so. Fifty years ago (if I were alive, I suppose) I could go buy any analog phone, plug it in, and carry on with my life. Instead I'm wasting it away with this phone/computer Frankenstein sitting on my desk.

Reminds me of my car (also German - BMW). About a month ago the remotes just stopped working. After taking it in a few times over the course of a couple of weeks, they FINALLY figured out what was wrong. They replaced almost $1500 worth of parts (still under warranty, thank God) and spent days (literally) "upgrading and rebooting" various computer and software components to ensure compatibility with the new hardware. I get the car back and the computer had been completely re-initialized. Everything needs to be replaced and reprogrammed. Even after setting it up again, my Nokia E-70's bluetooth didn't work with the car. It is paired and recognized but any call results in no audio - makes it kind of tough to talk "hands free". Of course it worked quite well before the software upgrade...

Now I'm trying to figure out why the web server on the Snom keeps disappearing. Is it a bug (running firmware 7.1.8)? Some kind of "feature" (another example of German over-engineering, perhaps)? At the moment I'm leaning towards bug because this thing has got some other really interesting quirks... I changed the VLAN setting, rebooted, and still had the DHCP address from the original VLAN but it wasn't reachable. The phone had joined the new VLAN but did not obtain a new DHCP address. If this were in the field, this phone would be bricked (from a network perspective). If this were Grandstream I would understand (expect) this. From someone with a good reputation like Snom it is very disappointing!

VoIP, Bluetooth, Snom, BMW, Nokia. Are our lives REALLY any better?

Tuesday, August 28, 2007

Monitoring BGP Feeds

Two weeks! I can't believe it has been that long since my last post. That's just crazy!

I know that I can't make it up to you but I will share something I just finished up.

BGP is cool. It is so cool to turn it up on a new router and see the entire internet's routing table with a simple command "sh ip bgp". What's cooler than that?

Feeding that table into a database, that's what!

Putting your BGP feed into a database enables all sorts of cool things. As a matter of fact, some of these are so cool I haven't even thought of them yet! For the last hour or so I've been busy working on getting this going. Here's what you will need:

- BGP feed from an upstream provider, connected to a router
- Linux machine running Quagga
- Linux machine with Perl installed (can be same machine as Quagga, mine is)

First you will need to configure your router with BGP enabled:

en

conf t

ip as-path access-list 1 deny .*

router bgp [your ASN]
neighbor [Quagga IP] remote-as 64512
neighbor [Quagga IP] transport connection-mode passive
neighbor [Quagga IP] description Quagga peer
neighbor [Quagga IP] filter-list 1 in


You will want to make sure that this machine is directly connected. If it isn't you need multihop BGP (which I won't cover right now). Here's what we're doing:

- The as-path with deny updates from your Quagga machine. We don't want some misconfiguration to actually affect your network. We just want some routes from the Cisco!

- Create the neighbor with remote-as 64512 (private ASN)

- Don't initiate a connection to this peer, let them connect to us (passive)

- Apply the filter-list to inbound traffic for this neighbor (don't allow updates from Quagga)

Now we need to configure Quagga. First, you will need to install it. Your distribution should have some packages for you. Use yum, apt, etc to grab it.

It will probably install some config files in /etc/quagga. We only want to setup bgp. This should be a good sample bgpd.conf to get you started:

hostname [your hostname]
password changeme
enable password changeme
log stdout
log syslog
service advanced-vty
!
router bgp 64512
bgp router-id [Quagga IP]
neighbor [Cisco IP] remote-as [your real ASN]
neighbor [Cisco IP] description Internet BGP Feed
neighbor 127.0.0.1 remote-as 64512
neighbor 127.0.0.1 description local db hookup
neighbor 127.0.0.1 port 9179
neighbor 127.0.0.1 passive
neighbor 127.0.0.1 filter-list 1 in
neighbor 127.0.0.1 next-hop-self
neighbor [some public ip] remote-as 64513
neighbor [some public ip] description Remote devel
neighbor [some public ip] passive
neighbor [some public ip] ebgp-multihop 255
neighbor [some public ip] filter-list 1 in
neighbor [some public ip] next-hop-self
!
access-list 1 permit [local class C network] 0.0.0.255
access-list 1 permit 127.0.0.1
access-list 1 deny any
access-list 10 permit [local class C network] 0.0.0.255
access-list 10 permit [remote ip]
access-list 10 deny any
!
ip as-path access-list 1 deny .*
!
line vty
access-class 1


After you apply this, you will want to start bgpd: "bgpd -n". It will tell you which vty you can connect to with telnet:

telnet localhost 2605

That should work. At this point, you should have a connection up to your main router:

sh ip bgp sum
BGP router identifier (deleted), local AS number 64512
29 BGP AS-PATH entries
0 BGP community entries

Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
(deleted) 4 15092 580 129 0 0 0 02:06:29 9845
127.0.0.1 4 64512 167 944 0 0 0 00:58:59 0
(deleted) 4 64513 6 616 0 0 0 00:02:56 0

Total number of neighbors 3

Sweet! Hey, where did that connection from 127.0.0.1 come from? That looks strange...

That connection is the whole point of this exercise. Star2Star is interested in quality, internet routing and the relationship between the two (at least I am). Long ago we realized that having a full BGP feed and being able to analyze updates in real time could be a huge asset to our management and monitoring portfolio.

How could we do this? Within the last week it came up on NANOG. A guy named Bill Nash wrote a Perl script a while back using Net::BGP to connect to a BGP peer and dump it's routes into a MySQL database. This made much more sense than trying to pull them via SNMP or some other hackish mechanism.

Bill wrote this for another employer and no longer had access to it. Evidently enough people asked him about it off list for him to consider re-writing it. I wanted him to do more than consider... I wanted that script!

I contacted Bill and offered to support his work any way possible. This included setting up a read-only BGP feed for him. I didn't want to give him (no offense Bill) a direct connection to our Cisco router (crashing that would be BAD) so I came up with the setup above. The Quagga is read only (by configuration and with -n on the command line not even the local kernel can be updated). And the Cisco is read-only to the Quagga peer. Seems safe enough.

The Quagaa instance is merely a distributor for our BGP feed. That way I can mess with it all I want without any fear (or very little fear) of causing any problems for our main router. I can hammer it all I want with some alpha-quality perl scripts. Worst case (hopefully) I'll just hose Quagga if something goes wrong...

While waiting for Bill to get his Perl script going, I Googled BGP Perl to see if there was anything else out there. Sure enough, there is:

http://briangannon.com/2007/04/23/bgp-perl-route-analyzer/


This is a crude version of what I am looking for. I made a few minor changes because I needed it to run on the same machine as Quagga (already using TCP port 179). I also didn't want to have to run the perl script as root. Here is a mini-diff:

line 20:
-my $bgp = new Net::BGP::Process();
+my $bgp = new Net::BGP::Process( Port => 9179 );

Now when you follow the directions on Brian's blog to INSERT the BGP peer into the SQL table, make sure to just use localhost. Then the perl script will use port 9179 for itself. After all, if nothing needs to connect to it, who cares what the local port is (as long as the peer has been configured properly)? Quagga knows that peer 127.0.0.1 is on port 9179, and it works. Check this out:

6147167 | 4 | 216.134.176.0/22 | 2007-08-28 19:39:51 | 2 | Next Hop Changed,Metric Changed |
| 6147168 | 4 | 216.134.180.0/22 | 2007-08-28 19:39:51 | 2 | Next Hop Changed,Metric Changed |
| 6147169 | 4 | 216.85.83.0/24 | 2007-08-28 19:39:51 | 0 | Removal of network |
| 6147170 | 4 | 216.85.83.0/24 | 2007-08-28 19:39:57 | 1 | Added 216.85.83.0/24 |
| 6147171 | 4 | 216.85.83.0/24 | 2007-08-28 19:40:35 | 0 | Removal of network |
| 6147172 | 4 | 216.85.83.0/24 | 2007-08-28 19:41:22 | 1 | Added 216.85.83.0/24 |
| 6147173 | 4 | 207.250.244.0/23 | 2007-08-28 19:48:32 | 1 | Added 207.250.244.0/23

or the routes:

mysql> select * from route limit 9842,100;
+---------+-----------+------------------+-----------+--------+------------+---------------+
| id | router_id | prefix | next_hop | metric | local_pref | as_path |
+---------+-----------+------------------+-----------+--------+------------+---------------+
| 3045536 | 4 | 216.85.190.0/24 | 127.0.0.1 | | 100 | 15092 4323 |
| 3045638 | 4 | 198.102.2.0/24 | 127.0.0.1 | | 100 | 15092 4323 |
| 3045655 | 4 | 195.85.117.0/24 | 127.0.0.1 | | 100 | 15092 174 209 |
| 3045665 | 4 | 216.85.83.0/24 | 127.0.0.1 | 99999 | 100 | 15092 4323 |
| 3045666 | 4 | 207.250.244.0/23 | 127.0.0.1 | 99999 | 100 | 15092 4323 |
+---------+-----------+------------------+-----------+--------+------------+---------------+


That's from my MySQL db. Pretty cool, huh?

I'll be working more on this in the upcoming weeks. Bill will also be working on a much improved version of the BGP Perl script that I am working with now. I'll make sure to let everyone know how it goes!

Tuesday, August 14, 2007

Social Networking

As of today I rounded out my social networking portfolio.

A year ago I didn't belong to any of these "web 2.0"/"social networking" sites. First it was Orkut. I was in Brazil and it kept coming up. Why not? So I joined.

A couple months ago my friends in Sarasota, FL kept started really bothering me about MySpace. Why not? So I joined.

A couple of days ago I got enough LinkedIn invitations for me to break down and create an account.

Today I signed up for Facebook, much to my chagrin. I was already on three other sites, so why not?

I'll tell you why not. Now I am going to have people complaining about my outdated profiles, lack of interest, etc. Why create an account if you can't keep it up to date?

How am I supposed to maintain accounts on my personal/professional life spread across FOUR different social networking sites?!? This is madness. I can't wait to see what everything looks like in a few months...

So anyways if you are on any of these sites you should try to track me down to see how it all unfolds. I am sure it will be interesting!

Monday, August 13, 2007

Update!

I am still alive - barely.

I haven't been able to post over the last couple of weeks because Star2Star was busy getting another release out. We put out another release every six months (depending on schedule and delays) and you guessed it - it's that time of the year again.

Our latest release is 2.1. It includes a lot of fixes and feature improvements to the overall system, everything from Polycom firmware to OpenSER enhancements (lots of them).

Speaking of OpenSER, it looks like I will be working with it quite a bit over the next few weeks and months for the 2.2 release. I'll also have some interesting Cisco experiences, I'm sure...

So between getting this release out, a car accident, and regular life I have not had much time for this blog. Things should be getting back to normal pretty soon. I like it that way.

Tuesday, July 31, 2007

Getting Multihomed - Part 3/3









Following up to one of my first posts. We FINALLY brought up BGP with all of our providers. A call from our CEO to some people at Verizon got some things moving again. I had the circuit up with BGP the same day. Pretty amazing, huh?

Anyways, now my problem was dealing with the limited memory and tcam allocation for unicast routes. If you recall, I ordered three full BGP feeds from three different providers. With the internet pushing 226,000 routes my 3750G wasn't going to cut it:

sh platform tcam utilization

CAM Utilization for ASIC# 0 Max Used
Masks/Values Masks/values

Unicast mac addresses: 400/3200 13/44
IPv4 IGMP groups + multicast routes: 144/1152 6/26
IPv4 unicast directly-connected routes: 400/3200 13/44
IPv4 unicast indirectly-connected routes: 1040/8320 1023/8134
IPv4 policy based routing aces: 512/512 2/2
IPv4 qos aces: 512/512 8/8
IPv4 security aces: 1024/1024 23/23

Note: Allocation of TCAM entries per feature uses
a complex algorithm. The above information is meant
to provide an abstract view of the current TCAM utilization

So now I've got full feeds from three providers coming in. Luckily I read up on IOS route-map statements before I brought these BGP sessions up. Otherwise things could've gotten ugly. Here's what I started with:

ip as-path access-list 50 permit ^174$
ip as-path access-list 50 permit ^4323$
ip as-path access-list 50 permit ^701$

I started with just getting the ASNs we were directly connected to. And my tcam started to fill, but it wasn't close. I thought, hey, why not get some more routes while I can? I started to read up a bit more on route-maps and I figured out how to get other ASNs into my route table. I only want the networks of providers connected to my providers. Does that make sense?

Without being able to see the full table I would have no idea of what I was doing. What if I wanted Level(3)'s routes, for instance? I needed to see what was going on. Luckily an old client of mine runs FixedOrbit - the coolest site to look at BPG information. All I had to do was query my directly connected ASNs and start picking other routes I wanted. BGP would take care of the rest.

Here is a shortened version of what I ended up with:

ip as-path access-list 50 permit ^174$
ip as-path access-list 50 permit ^174_3356$
ip as-path access-list 50 permit ^174_33363$
ip as-path access-list 50 permit ^4323$
ip as-path access-list 50 permit ^4323_1668$
ip as-path access-list 50 permit ^4323_6983$
ip as-path access-list 50 permit ^4323_11456$
ip as-path access-list 50 permit ^701$
ip as-path access-list 50 permit ^701_19262$
ip as-path access-list 50 permit ^701_3356$

Now I have entries in my route table for my directly connected ASNs (174, 701, 4323) and some ASNs they are peered with - 3356, 33363, 1668, 6983, 11456, 19262. I don't have much room in my tcam but hey, that's what VXRs are for! Wow, I really want one of those (with an NPE-G2, of course) ;).

Friday, July 27, 2007

The Ultimate Geek Watch



















I used to think watches were completely unnecessary and stupid. After all, my cellphone is always with me and is always synced to the right time. Why do I need a watch?

Then I found a white G-Shock. This watch has it all:

  • It's white
  • Atomic synced
  • Shock resistant (tough)
  • Vibration alarm
  • Thermometer
  • Solar Power
  • World Time
  • Movement sensor

I bought it a few months ago from amazon.com. Evidently it's imported by Mister Watch from Japan. Sure enough it came in the mail, complete with price tag (in yen) and a Japanese-only user's manual (G-Shock is made by Casio, a Japanese company).

Because I don't read Japanese it has been difficult to discover all of the features of this watch. The "movement sensor" that I described above is a good example. I was out with my friends one night in a dark bar and I lifted my wrist to look at the time. The back light automatically came on once I twisted my wrist a certain way. At first I thought it was a fluke. My friends were convinced I was somehow controlling it with my wrist, mind, etc. Oh no, it was the movement sensor.

I think it works in combination with the solar panel because it only activates when it is dark (beyond a certain point). In a dark enough room, with just the right wrist snap, I never have to manually push the light button to see what time (or temperature) it is. That's a good thing too, because like any good American, I don't want to have to do ANYTHING that I shouldn't have to do and pushing watch buttons is no exception.

It's too bad that you can't get them anymore because many, many people have asked about the white G-Shock. If anyone knows where you can get them in the US please let me know!

UPDATE: Shinya Amano has translated AstLinux documentation for voip-info.jp and he has done some research on this watch for me. He found the English manual. Thanks Amano!

Wednesday, July 25, 2007

GoDaddy Sucks

As I write this GoDaddy has managed to completely screw up authoritative DNS for krisk.org. They have been my registrar for quite some time. Yesterday I decided to switch my authoritative dns over to them from DynDns. Why would I do this?

I needed e-mail forwarding. KrisK.org used to be hosted on a FreeBSD server that I ran. I started to get more and more busy with AstLinux and other misc. stuff so I moved as many of my services to free or managed solutions.

I couldn't do e-mail forwarding because GoDaddy's recommended MX records were CNAMEs. DynDns does not approve of this (every MX should be an A record). So I needed to move everything to GoDaddy just so I could use their stupid free e-mail forwarding (krisk.org -> gmail).

I tried to get to this blog today and blog.krisk.org wasn't resolving. What gives? I tried digging a few DNS servers that I knew of. All of them returned NXDOMAIN. That's not good. I ran whois and krisk.org to find the authoritative name servers. I was (and still am) on ns5.secureserver.net and ns6.secureserver.net. I tried to do directly against them:

kris@krislap:~$ dig @ns5.secureserver.net

; <<>> DiG 9.3.4 <<>> @ns5.secureserver.net
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 11126
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;. IN NS

;; Query time: 70 msec
;; SERVER: 208.109.78.180#53(208.109.78.180)
;; WHEN: Wed Jul 25 15:22:43 2007
;; MSG SIZE rcvd: 17

Same deal with ns6. That's not good. Some of my other domains on GoDaddy have ns1 and ns2. I tried to dig against those and they worked. The funny thing was ns5 and ns6 were not found as NS records.

I shuddered at the thought of calling GoDaddy support. I certainly don't want to talk to any of "those people". By "those people" I mean script reading drones that would ask me which version of Internet Explorer I was using...

I logged into the extremely horrible GoDaddy portal and clicked "Use default hosting name servers". They were listed as ns5 and ns6. I wasn't hopeful. A few minutes later it appears to be working again:

kris@krislap:~$ dig @ns5.secureserver.net www.krisk.org

; <<>> DiG 9.3.4 <<>> @ns5.secureserver.net www.krisk.org
; (1 server found)
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11574
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 4, ADDITIONAL: 0

;; QUESTION SECTION:
;www.krisk.org. IN A

;; ANSWER SECTION:
www.krisk.org. 3600 IN CNAME godaddy.krisk.org.
godaddy.krisk.org. 3600 IN A 68.178.211.88

;; AUTHORITY SECTION:
krisk.org. 3600 IN NS NS1.SECURESERVER.NET.
krisk.org. 3600 IN NS NS2.SECURESERVER.NET.
krisk.org. 3600 IN NS ns5.SECURESERVER.NET.
krisk.org. 3600 IN NS ns6.SECURESERVER.NET.

;; Query time: 76 msec
;; SERVER: 208.109.78.180#53(208.109.78.180)
;; WHEN: Wed Jul 25 15:32:13 2007
;; MSG SIZE rcvd: 157


Woah! Look at that! ns1, ns2, ns5, and ns6 are listed as authority. Hmmm...

P.S. - If you are still reading this I need to tell you that DynDns is AWESOME!

Saturday, July 21, 2007

Thursday, July 19, 2007

Finding Asterisk

I've run my own Asterisk system for quite some time. My mom lives in Minneapolis, my dad lives in Chicago and my sister lives in Montreal (stinkin' French Canadians - the worst kind). Just kidding, I love my sister and all of my Quebec friends! At this point in time I lived in Wisconsin. Cell phone plans weren't that cheap yet (especially in Canada) and my family was spread out far enough for every call to be long distance.

I started playing with Asterisk in July of 2004. It turns out that I was flying to Montreal to visit my sister during the US Independence Day Holiday (yeah, that makes sense - go to Canada for the 4th). I bought a cheap X100P clone, installed it in a Linux machine, and connected it to the analog line (SBC) at my house in Wisconsin.

I configured a basic (dangerous) Asterisk install over the course of a few days and packed my things for Montreal. Of course I also brought my laptop. I had also managed to install a softphone on it before I left. I got to my sister's apartment, connected my laptop to her VideoTron cable modem and registered with my softphone. Would it actually work? Could I make a call from this softphone to that Linux server (over the internet) and out the PSTN in Wisconsin to one of my friends - for free?

If you are reading this blog you probably know what happened next. It worked perfectly. I was amazed and my friends were impressed. This was awesome.

Over the next couple of weeks I added what I needed to my (lame) Asterisk configuration. Then disaster struck... My air conditioning broke and with it went the hard drive of the Asterisk play server. It was a play server - no backups.

I hate doing things twice. That's exactly how I felt about this. I wasn't going to work through all of that again - compiling, configuration file mess again. I swore I wasn't going to resurrect Asterisk or that machine again.

Then I heard it. Asterisk was calling. I couldn't get the idea of Asterisk out of my mind. I hit the books (voip-info.org, internet mostly) and I learned more about Asterisk - more than enough to simply rebuild my play server. A couple of days later I had it back up and better than before. In the process I also knew what I was going to do with it. I could ship an ATA to each member of my family and we could all call each other, for free. I could also get an account with an ITSP and provide cheap calling to my family members.

Today some instance of that server is still running and my family members can still call each other with a four digit dial, for free.

Monday, July 16, 2007

What's my name?

This is going to be a different kind of post. This post might actually be useful for people trying to solve this problem. Just the facts, ma'am.

One of the things that has repeatedly come up in my line of work is CallerID name delivery in PRI (Primary Rate Interface) ISDN (Integrated Services Digital Network) configurations. I learned more about CallerID name today than I ever wanted to know. Just kidding - I love getting into stuff like this!

PRI is great because call setup is fast and CallerID information is available instantly. Or is it? I always knew that Caller ID name is not carried over the PSTN (usually - in some countries it is). The number does (obviously), but the name is usually looked up in CNAM by the terminating switch, not the originating switch. What I didn't know is that sometimes this isn't done when the initial Q.931 Setup message comes down the PRI to signal a new call.

Sometimes this CNAM lookup takes a little while (fractions of a second) and the name is sent later in a separate Q.931 Facility message. This is true. Cisco says so (PDF). A Cisco ISDN-SIP gateway can be configured to do this one of two ways:

1) Wait until you receive the Q.931 Facility message with name and shove it into the SIP INVITE using either PAI (P-Asserted-Identity) or RPID (Remote-Party-ID). Send the INVITE to the SIP proxy (or wherever).

2) Send the INVITE ASAP, and then send a SIP INFO packet when the name shows up in the Q.931 Facility message.

The default is #2, which is screwy. Very cool, but still screwy. It is much harder to design a SIP platform that can accept the initial INVITE, begin to process the call, and then append the PAI or RPID information received in the later INFO.

Thanks to Cisco I now understand more about Q.931 and ISDN. Now I need to get this "thing" to work.

My test setup:

PRI -> Asterisk -> PRI -> AS5350XM -> SIP -> OpenSER -> SIP -> Device

I need to get Caller ID with name delivery through this whole mess, from the first PRI to the last SIP device.

The LEC provided the PRI coming into the Asterisk machine. I provided everything else. I saw several roadblocks:

1) Get the CID Name from the LEC (via PRI)
2) Pass it through Asterisk
3) Get it to the 5350 (via PRI)
4) Get it to OpenSER (via SIP)

Knowing what I now know about Caller ID with name in ISDN I knew just what to do for Asterisk. In zapata.conf, my incoming context is lec-in. Here it is (from extensions.conf):

[lec-in]

exten => NXXNXXXXXX,1,Wait(1)
exten => NXXNXXXXXX,n,DoSomethingElse

Yep, that's right. All you need is to Wait a little to get that second Facility IE. Asterisk doesn't support getting the Facility IE later and it certainly doesn't support sending a subsequent SIP INFO. That's a good thing because as I said the "other" way (SIP INFO) just seems goofy to me.

Now I needed to get the CallerID name to the 5350. It didn't seem to work. I start looking at "pri debug span 3" output to see the Q.931 goodness coming from Asterisk. I fired up "debug isdn q931" on the 5350. No dice. It looked like this bug in libpri was killing me:

http://bugs.digium.com/view.php?id=9651

This was committed to libpri SVN about a month ago. I update libpri from SVN, recompile Asterisk, and install the new chan_zap.so. I give it another shot. It looks like the 5350 is now getting the name over Q. 931. Using ngrep I look at the SIP INVITE coming into OpenSER from the 5350. I have an RPID header, but it looks strange. The name field in the Remote-Party-ID header is "pending". What the heck is that about? "pending" was not what I was seeing in Asterisk!

I opened up ngrep a bit to let my see any SIP INFO messages that might be coming later. Sure enough shortly after the SIP INVITE comes a SIP INFO message with my Caller ID name. Going back to my two configuration choices on the 5350 I knew I preferred option #1 (send everything in one SIP INVITE), even if it meant there was a little delay before the caller got audio. How could I configure the 5350 to wait a little and put it all in one SIP INVITE before the Cisco fired it off to OpenSER?

I dug around on cisco.com for a bit. Nothing - at least nothing obvious. You have to love Cisco configuration and Cisco docs. I decided to look around the internet and see if anyone else had this problem.

I looked on Google and found this:

http://puck.nether.net/pipermail/cisco-voip/2005-June/005485.html

I wondered if Mr. Adam Rothschild ever found the solution to his (my) problem. I open up another tab and write him an e-mail. Three minutes later (literally) he sends me this configuration snippet:

---Begin IOS Configuration---
interface Serial3/0:23
no ip address
load-interval 30
isdn switch-type primary-ni
isdn incoming-voice modem
isdn supp-service name calling
isdn negotiate-bchan
no isdn outgoing display-ie
no cdp enable
exit
gateway
timer receive-rtp 1200
sip-ua
disable-early-media 180
retry invite 3
retry response 3
retry bye 3
retry cancel 3
timers buffer-invite 500

---End IOS Configuration---

Let's get away from this technical mumbo-jumbo and talk about people for a minute...

Mr. Adam Rothschild got an e-mail from a random stranger across the internet referencing an obscure technical problem that he had over two years ago. In less than three minutes he dug up the solution and wrote me back. I have a SmartNet support contract on this 5350 but I doubt the techs at Cisco could have helped me any better or faster than a nice guy (Adam) helping a stranger (me).

Wipe away your tears, you sentimental fool. We're getting back to configuration. This blog is hardcore. Couldn't you tell?

I applied Adam's config to my AS5350XM running IOS 12.4(15)T. Here is the SIP INVITE from the 5350 to OpenSER:

U 192.168.0.1:61306 -> 192.168.0.10:5060
INVITE sip:9418675309@192.168.0.10:5060 SIP/2.0.
Via: SIP/2.0/UDP 192.168.0.1:5060;x-ds0num="ISDN 3/1:D 3/1:DS1
1:DS0";branch=z9hG4bK901AB9.
Remote-Party-ID: "STAR2STAR COMM"
;party=calling;screen=no;privacy=off.
From: "STAR2STAR COMM" ;tag=971D8C-1203.
To: .
Date: Mon, 16 Jul 2007 21:57:24 GMT.
Call-ID: 5E99C7DC-331E11DC-8126E6C7-399CBB13@192.168.0.1.
Supported: 100rel,timer,resource-priority,replaces.
Min-SE: 1800.
Cisco-Guid: 1586976572-857608668-2150694933-1673067056.
User-Agent: Cisco-SIPGateway/IOS-12.x.
Allow: INVITE, OPTIONS, BYE, CANCEL, ACK, PRACK, UPDATE, REFER,
SUBSCRIBE, NOTIFY, INFO, REGISTER.
CSeq: 101 INVITE.
Max-Forwards: 70.
Timestamp: 1184623044.
Contact: .
Expires: 300.
Allow-Events: telephone-event.
Content-Type: application/sdp.
Content-Disposition: session;handling=required.
Content-Length: 288.
.
v=0.
o=CiscoSystemsSIP-GW-UserAgent 7275 8957 IN IP4 192.168.0.1.
s=SIP Call.
c=IN IP4 192.168.0.1.
t=0 0.
m=audio 20746 RTP/AVP 18 0 101.
c=IN IP4 192.168.0.1.
a=rtpmap:18 G729/8000.
a=fmtp:18 annexb=no.
a=rtpmap:0 PCMU/8000.
a=rtpmap:101 telephone-event/8000.
a=fmtp:101 0-16

Yeah yeah! Look at that Caller ID name in that Remote-Party-ID header! I feel like that's the best looking SIP INVITE I have ever seen. How does one SIP INVITE look better than any other? If you don't know the answer to that question, you haven't been following along.

I wrote Adam back to let him know how it turned out. He wrote me back again, happy to hear that it worked for me. Wow, just wow.

So many things shine through in this post. In one evening I found (and patched) a bug in libpri. I learned more about Q.931 and Caller ID. I found a guy to help me put it all together. The open source development model worked. The promise of easy access to information via the internet skooled me in ISDN. Social networking proved to be very effective, even while using pre-web 2.0 technology (e-mail). Google worked (a lot).

Now I get to put it all together in this blog post to give back a little. Hopefully the next guy (or girl) trying to get some mixed up mess of SIP and ISDN devices to work together with Caller ID Name delivery will get out of the office just a little bit earlier.