GRASE Hotspot

3 years in the making, and finally I am releasing the code for the GRASE Hotspot. I’ve always planned on releasing the code, but had a lot things I wanted done before the code was released, in particular making it easy to install, and modular, as well as more secure than it previously was (in particular the remote access).

For those that don’t know much about the hotspot system I’ve been working on, it’s a simple captive portal system, that allows an organisation/company to provide controlled internet access to users. When a user tries to use a computer on the network (wireless or wired), the first time they attempt to access a website, it redirects them to a login screen. After a sucessful login they can then use the internet until their time or data allowance is exhausted. The main part of the GRASE Hotspot is the admin interface I have written. This provides a simple interface for adding and managing users, as well as monitoring usage and websites visited.

The rest of the Hotspot system is what we call glue layers. This is the process of connecting individual components together, in this case, CoovaChilli, FreeRadius, MySQL, Squid and a few other components. Most of the Hotspot solutions I researched required a lot of manual work gluing the components together. All this hard work is taken care of using the GRASE Hotspot.

Currently the best way to get started using the system, is to download the grase-repo deb package from http://hotspot.purewhite.id.au/apt/pool/main/g/grase-repo/ which will setup the apt repository. Then head over to http://hotspot.purewhite.id.au/wiki/Documentation/Packages to get an idea of some of the other packages that can be installed to get started. More information will appear over time at the main wiki page.

Some old screenshots (will be updated soon) and support forums are over at SourceForge.

Asterisk Voip to Voip “Bridge” (Webcallback)

Call it what you like. Sip to Sip, VoIP to VoIP, VoIP Bridge, Callback, Webcallback. The idea is to have a server somewhere call two SIP(VoIP) devices and connect the 2 calls together.

What’s the point of it? Maybe you are stuck somewhere with a phone that only accepts incoming calls, and you want to make cheap voip calls. Or you are overseas, and it’s cheaper to call from Australia to your location that from your location to Australia. For example you may have a payphone that accepts incoming calls but outgoing calls are expensive. Or you just want to enjoy nice cheap VoIP rates but don’t have any VoIP hardware at your location, or poor dodgy internet, but have a mobile phone or landline.

What ever the reason, being able to have a VoIP call that connects to your location, then calls another party is a great thing!

Now before I go much further, if all you want is this ability to be called, and then have your remote party called, PennyTel has this Webcallback feature built in. Mynetfone doesn’t, but if you can make outgoing calls you can use their ANI callback feature (you call a special number, your caller ID needs to not be blocked, and then you hangup after it rings, then it calls you back and lets you make your VoIP call). So, if you aren’t going to be using this much, and don’t need lots of customisation or special features, just signup for PennyTel and start using their Webcallback feature. Remember, you pay the cost of 2 calls using this feature, not 1. First, the cost to your number, then the cost to whom you are calling. So if both parties are mobile phones, then it certainly might not be cheap anymore. How ever, if your number is a landline in australia, and so is the party you are calling, then it’ll cost a total of $0.16 to make your call (on their Freedom Untimed plan). This is pretty cheap compared to most normal telco’s.

Read on however, if you want the ability to use just about any VoIP provider, and want to maybe use multiple VoIP providers and have heaps of control over it all.

Asterisk, the VoIP/PBX mega funky software, will turn a normal server into a PBX/VoIP Gateway etc etc. When I first looked to a solution to this issue a few years ago, I looked at the task of setting up Asterisk and found it daunting, so gave up. PennyTel Webcallback essentially delivered what I needed so I left it alone until now. I now have Asterisk setup as a simple VoIP system that allows me to make 2 calls (using multiple VoIP providers if I want) and join them together.

Why is it better than PennyTel Webcallback?
For me it’s better because it can work out cheaper for me. PennyTel callback is $0.16 total ($0.08 per each call to landline). However, if I’m calling someone who is a MyNetFone customer, if  I was to call their VoIP number from a MyNetFone VoIP account, the call would be free. And if I’m on a MyNetFone monthly plan, then I could have a good number of free landline calls each month. My optimal solution is currently combining both MyNetFone and PennyTel. PennyTel to the normal landline, $0.08, and MyNetFone to the MyNetFone VoIP numbers, $0.00. So it’s a total of $0.08 for the whole call! So depending on your location, and your destination number, and your VoIP provider plans, you can get your calls cheaper than using PennyTel webcallback. And just the fact that you can use this Callback method with just about any VoIP provider, priceless!

So lets get onto the easy part, setting it all up. While at first this can look daunting, in reality, it’s very simple. This is all based on an Ubuntu 10.04 box, using the CLI. Quick note before we start, what ever machine you set this up on, needs to have enough bandwidth for 2 calls at the same time. So if you are putting it on a home ADSL connection, check you have enough up and down bandwidth for this. My server is hosted out on the internet and has enough bandwidth. A big reason for me setting this up is lack of a decent internet connection from my home to be able to do normal VoIP.

sudo apt-get install asterisk

Yes,this does pull in a far few bits of software, some of which isn’t needed and I’ve not even poked at yet, but this is what we do to get Asterisk installed. Easy.

Now the setup. You need to edit /etc/asterisk/sip.conf to add your VoIP providers. Some providers give you the Asterisk details on their site, many others are just a google away, generally on http://www.voip-info.org/

So drop down to the bottom of the [general] section in /etc/asterisk/sip.conf and add in a register line for each VoIP provider. Mine is in the following format. You can see that the username is repeated a few times on the mynetfone one. It can be different for other providers.

register => username@sip01.mynetfone.com.au:password:username@sip01.mynetfone.com.au/username
 
register => 888xxxxxxx:secret@sip.pennytel.com/888xxxxxxx

Now drop to the bottom of the /etc/asterisk/sip.conf file, and add in your “trunks” for the VoIP providers. In my situation, I don’t want incoming calls (as then they need to be routed), so I just have the outgoing trunks.

[mynetfone-out]
disallow=all
allow=alaw
allow=ulaw
allow=ilbc
allow=g729
allow=gsm
allow=g723
authname=09xxxxxx
canreinvite=no
dtmfmode=rfc2833
fromuser=09xxxxxx
host=sip01.mynetfone.com.au
insecure=very
nat=no
pedantic=no
qualify=yes
secret=password
type=friend
defaultuser=09xxxxxx
 
[pennytel-out]
type=friend
host=sip.pennytel.com
fromuser=888xxxxxxx
defaultuser=888xxxxxxx
secret=password
canreinvite=no
insecure=invite

Again, these can look different. A bit of googling around should help, or if you work from the above you should be able to work out the settings for your own provider. Note, username is no more in newer Asterisk versions, it’s now defaultuser, so you may need to change what you find on the net.

Have a look in /etc/asterisk/manager.conf, you’ll see you need to create a file in /etc/asterisk/manager.d/ to add a user. You may wish to do this so you can use the astman tool later, which helps with disconnecting calls and monitoring things. (You can do this through the asterisk cli, how ever it may be a bit harder).

The format of the file you create is as follows. /etc/asterisk/manager.d/somename.conf

[username]
secret = password
read = system,call,log,verbose,command,agent,user,config
write = system,call.log,verbose,command,agent,user,config

This username and password isn’t related to your VPS at all, it’s what you’ll use when logging in with Astman or other tools.

Now we get to the bit we’ve been waiting for, setting it up to connect 2 calls.
Edit /etc/asterisk/extensions.conf. Comment out the include => demo line from the [default] section. There is a section in the [default] that should sort out Hangup/Busy detection and the likes, so the extensions we are adding can be very simple, however, you can customise these very easily to do more than just connect the 2 calls.

 
[DialOutMyNetFone]
exten => _0X.,1,Dial(SIP/mynetfone-out/${EXTEN})
 
[DialOutPennyTel]
exten => _0X.,1,Dial(SIP/pennytel-out/${EXTEN})

And we are done. Everything should be setup now. The default install of Asterisk has autoloading on in /etc/asterisk/modules.conf so the rest should just work.

After all those edits, restart asterisk.

sudo /etc/init.d/asterisk restart

Now we create our call file.

Channel: SIP/pennytel-out/YOURNUMBER
Context: DialOutMyNetFone
Extension: WHOTOCALLNUMBER
Priority: 1
Archive: Yes

Very simple file. The Channel line is what calls you, so replace pennytel-out with the trunk you wish to use to call you. (It can be the same as the trunk used later on, or different. In this example, it’s different as I want the cheap call to my landline, and the free call to a mynetfone number). The Context is the extension name that we defined in /etc/asterisk/extensions.conf, and the Extension is the number that you wish to call. Both for YOURNUMBER and WHOTOCALLNUMBER you need to know the format your VoIP provider uses. Some will allow just a localised version, for example in australia I can just dial 075xxxxxx or 040 123 4567, and MyNetFone understands them. Some other VoIP providers might need 6175xxxxxx instead. Dialing internation, some just need the country code, others need a prefix like 0011, etc etc.

Now to actually place the call. There are a number of methods of doing this, the end result needs to be a call file placed in the /var/spool/asterisk/outgoing directory, owned by the asterisk user, and placed in a way that asterisk can’t start reading it before the file is all there. For this reason, the mv command is recommended and I’ll demonstrate. (I first copy the file so I can keep a number of pre setup files stored).

cp preset1.call call123.call
sudo chown asterisk call123.call
sudo mv call123.call /var/spool/asterisk/outgoing/

As soon as the file hits that directory, asterisk reads it and executes it. If everything goes right, within 10 seconds your phone should start ringing. Pick it up, it’ll then start ringing the other party, finally, when they pickup you can start talking! Done.

Sometimes the hangup detection doesn’t work properly. I’ve not yet worked out why or how to fix it, I believe there are a number of things to tweak regarding this. What I currently do is run ‘astman localhost’ (from the machine running asterisk), login with the details we setup earlier, and I can think select the call and press hangup if it doesn’t hangup correctly.

For more details about Call files, check out http://www.voip-info.org/wiki/view/Asterisk+auto-dial+out

Of course, it’s not always practical to ssh into your server just to make a phone call. I’ll leave the task of setting up other methods of creating and moving the call files to the reader. Please though, don’t give your web server user full sudo access without a password! I’d recommend ether a database with a cron runner script (running as the asterisk user), or something similar.

Last things. Check your firewall. You’ll need to open some RTP ports and some SIP ports. A google will reveal more. Try to limit what you open though, I’ve not given any instructions for securing asterisk in this post, that also is for your further reading.

Internet Reception

So we finally got our modem a few weeks back. A 3G9WB, also known as a 3G9WT (Telstra Branding) or a 7.2 Home Gateway. Really, it’s just a Netcomm router with a Sierra mobile module inside.

It’s unlocked, but we still can only get Telstra NextG, although with a Yagi we might be able to get Optus 3G. However, even Telstra NextG is dodgy, showing as “Low” signal strength, or 2 bars out of 5. Often it’ll just stop because the signal is too low. And 2G (EDGE) isn’t any better.

So today we needed to download some video editing software, thought we give OpenShot a try instead of Cinelerra. Hoping for something a little simpler for basic editing. The download started off with an ETA of 30mins, and then the speed just kept dropping. Soon our ETA was 4 hours. I’d had enough, so I opened the window, removed the flyscreen and climbed onto the window sill. I then carefully wedged the modem into the louvers. Still only a low signal, but success! The download was finished in 3minutes! I might actually be able to upload my assignment quickly with the modem here (when the submission link is fixed up).

So, until we get an external antenna, we’ll just have to use an external modem! :-P

Handbrake Encoding Cluster

Recently I’ve been given the task of putting a DVD collection on to the computer (for backup purposes, so that the originals can be locked away and not damaged by little hands). Having used Handbrake before to convert DVD’s to H.264 videos, I figured I’d be able to use it again. But for such a large task, it makes sense to have many computers doing the encoding. Unlike dvd::rip, Handbrake doesn’t have a distributed cluster feature.

I found a possible solution in the Handbrake Forums, using ppss and some scripts. http://forum.handbrake.fr/viewtopic.php?f=6&t=17504

Unfortunately, I wasn’t able to get PPSS working how I wanted (or at all). However, it did provide me with a transcode bash script that assisted with getting the HandbrakeCLI options right, in particular splitting TV episodes into individual episodes.

I continued looking for ways to do this, knowing I’d previously used some clustering script many years ago, and finally found gearman.
At first glace, gearman seems to be perfect, except digging deeper you discover it’s designed to be called from within applications and not so much as a command line “queue”. Thankfully I discovered a post explaining how to make gearman more command line friendly using xargs. (Which also helped me finally understand how xargs work!) So with a bit of scripting I had myself a number of small shell scripts, a gearmand server, and a working cluster.

Firstly, I setup some NFS mounts on all the computers involved.

$ mkdir /mnt/DVD_rip
$ mkdir /mnt/DVD_encode

For me, I had 2 mounts as I wanted the DVD_rip folder to be on a local computer, and the DVD_encode folder to be on a server that all the finished files needed to be on.

I then created a simple bash script for ripping the disks (with error handling). I can run this script in the /mnt/DVD_rip folder, give it one argument (the DVD name) and it’ll rip the disk and attempt to retry any sectors that have errors. The ‘lsdvd’ is so that css keys are loaded so you can read encrypted DVD’s. You can also stop and restart the ripping process at any time without loosing what has been ripped successfully. NB: It doesn’t remove the CSS encryption so you will need libdvdcss on all computers doing encoding.

lsdvd /dev/sr0 > /dev/null & ddrescue -r 1 /dev/sr0 "$1.iso" "$1.log"

My next script (submitjob.sh) is another 1 liner, it submits the job to gearmand. It simply takes the name of the file to encode (iso or a video file) and optionally an attribute that ether tells our transcoding script to encode all the titles (split episodes) or which title to encode. Without this attribute it will scan for the longest title and only encode that.

My next script (startworker.sh) starts the gearman worker processes. I run it on each machine in the cluster that I want processing videos. I usually run it in a screen session as when it’s encoding it outputs some information through this script, the rest goes into log files. NB: The script has the hostname of the gearmand server in it as does the submitjob.sh script.

Our last script (transcode2mkv.sh) is the actually transcoding script. This is what the gearman worker calls to do the encoding. I got this script from the method that uses PPSS at http://forum.handbrake.fr/viewtopic.php?f=6&t=17504. I then modified it to encode to mkv files instead of mp4, and I changed some of the default encoding options, as well as how it handled the titles (i.e. selecting all, or individual ones), and how it handled selection of audio and subtitle tracks (it selected them all, I wanted it to just select the English audio, and all the subtitles). I also added logging so that it would update a cluster log when it started and stopped encoding (with timestamps), and to log the progress output to one logfile, and the verbose information to another logfile (so I could easily tail the logfile to get the current progress).
Initially for doing TV episodes, this script would select all the titles and encode each one to it’s own file. I changed it to just select the 4 I wanted, and then later changed it so I could select individual titles. The reason I changed to selecting individual titles was that some of my encoding machines are faster than others, this way I didn’t have 3 machines sitting idle while one machine was still on the first title of the disk, instead they each took a title and the disk was processed a lot quicker.

All the files can be found at http://tim.purewhite.id.au/code/handbrake-cluster or checked out with bzr.

bzr branch http://tim.purewhite.id.au/code/handbrake-cluster/