Sunday, November 25, 2007

XBOX meets GrandCentral

Today I felt I needed to come up with a fun hack to get myself out of a bit of a rut. I recently started messing around XBMC again and wanted to see what it could do and, being a casual phreak, the caller ID script caught my eye.

After digging into it a bit I understood a few basic things about it:

It is a simple Python script that listens for TCP connections on port 10629.
It will display any message I’d like over XBMC and pause whatever is playing.
The messages don’t have to be formatted. The system just displays whatever you send it verbatim.

I’m pretty bad with my phone because it’s never charged, never in the room I’m in, and the ringer is almost always (mysteriously) off. I setup a GrandCentral account for myself a few months ago to combat this problem since I can have GrandCentral ring my Skype or Gizmo numbers which are always running on my laptop. This works pretty well unless I’m taking a break and using XBMC...

Now I started wondering how I could get my GrandCentral caller ID on my XBOX. It actually turns out that in my case it’s pretty easy since I have all of the essential plumbing set up for work. Here’s how my system operates:

My colocated Asterisk box receives the phone call from a VOIP provider on a specific VOIP line
Asterisk then connects to my home server over OpenVPN on TCP port 10629
My home server then forwards the OpenVPN connection to my XBOX via the “portfwd” application also on the TCP port 10629
The XBOX displays the caller ID on the screen and pauses whatever is playing

To do all of this you’ll really just need a VOIP number and an Asterisk box that receives calls on that VOIP number. I won’t go into the basic configuration for that here but free numbers and configuration assistance are available from IPKall and TRX Telecom.

Assuming your Asterisk server and XBOX are on the same network you only have two more steps to go. First, add this new inbound number to your GrandCentral configuration so that it rings simultaneously with your cell phone and/or whatever other phones you have set up. Second, configure your Asterisk box to run these dialplan entries when that number rings:

exten => xyz,1,System(/bin/echo -e "${CALLERID(num)}" | nc xbox 10629)
exten => xyz,2,Hangup

“xyz” should be your VOIP number or whatever other value your dialplan needs to identify this DID. “xbox” should be an entry in your /etc/hosts file that points to your XBOX’s static IP. Here I use netcat (nc) instead of telnet because my Gentoo box didn’t have it installed. It’s also easier to use since it doesn’t expect the session to be interactive. Some implementations of telnet can be a real pain when trying to pipe data to it. Just using netcat gets around all of that potential hassle.

Keep in mind that this number exists only to capture the caller ID and doesn’t need to be answered. If you’d like to answer it and send the call to anything further in the dialplan you can always just remove the hangup line and continue from there.

Anyway, in my setup it wasn’t quite this simple. My XBOX is behind a NAT router but conveniently I do have a home server that has a persistent OpenVPN connection to my Asterisk server. In my case I basically replaced “xbox” above with the OpenVPN IP address of my home server and then set up port forwarding. I didn’t go for kernel port forwarding, instead I just did it in userspace with “portfwd”. In Gentoo my steps were as follows:

1) emerge portfwd
2) Edit /etc/conf.d/portfwd and remove the “-t” option from PORTFWD_OPTS. This option requires transparent proxying to be enabled in your kernel. It doesn’t hurt to remove it since the XBOX doesn’t care who is connecting to it. If your kernel doesn’t have this option portfwd will silently fail.
3) Create a portfwd.cfg file in the /etc directory that contains the following line:

tcp { 10629 { => xbox:10629 } }

So now my home server just forwards all connections on port 10629 to my XBOX. That way when my public Asterisk server connects to what it thinks is my home server’s OpenVPN IP address it’s really just getting sent along to the XBOX. If the XBMC and the caller ID script isn’t running the connection just times out.

In reality my configuration is slightly different so that it only allows connections over the VPN to connect to the XBOX but for the sake of clarity I’ve left that out of the configuration. Here’s video of me getting a spoofed call from the Bell’s Mind number while watching a movie. That will give you an idea of what all this work can actually get you. :)