Thursday, 23 January 2014

Getting a Prolific PL-2501 based USB-to-USB link cable working with Debian and a Raspberry Pi

A while ago I had an idea to use a Raspberry Pi as a recovery interface to my bigger home server.  My home server acts as my fileserver, network router, dns server and provides the web interface for my home automation and is always on.  I wanted a way of being able to access it over the network even if it's own network interface is down for some reason (usually because I've been experimenting with something and made a mistake).

I looked into the options and decided the simplest way of making this work would be to get a USB-to-USB link cable.  These aren't simple USB cables, there is some electronics in the middle that makes it work.  They are fairly common though and there are quite a few different manufacturers, most of which seem to be based on a few chipsets.

The one I got was made by "Sandberg" and came from ebay for about £5.  Unfortunately, I was unlucky and it turned out to be based on a chipset that's not currently supported by the plusb kernel module for Prolific USB network interfaces.

The module description says:

"Prolific PL-2301/2302/25A1 USB Host to Host Link Driver"

The cable I got has a PL-2501 chipset.  It was being recognised by the USB system OK but the module simply doesn't know about this chipset:
Bus 001 Device 004: ID 067b:2501 Prolific Technology, Inc. PL2501 USB-USB Bridge (USB 2.0)
There is a patch you can find on the Internet to make this work.  It involves installing the kernel source, patching the module, compiling the module and then copying it over the original module in the kernel driver folder.

In hindsight I'd have been much better off either:
  • using the Raspberry Pi UART and a spare internal serial port in my home server along with a 3.3v-5v level converter to create a serial link
  • installing a 2nd network card into my home server, linking this to the Raspberry Pi's NIC and then using a USB-to-Ethernet dongle in the Raspberry Pi so it has 2 interfaces.
Since I already had my USB link cable I was determined to make it work.

Here is what I did to get it to work.  You will need to compile the module twice, once on the Linux server and once on the Raspberry Pi since they are different architectures.  A module compiled on x86 wont work on the ARM based Pi.

---

Standard Debian system howto

This was what I did to get the cable working on my Linux server, it's x86 architecture but this will work OK for anything using a standard Debian system (i.e. no custom kernel).

1) Install the kernel headers and kernel source packages for your current kernel:
apt-get install linux-headers-`uname -r` linux-source
Note the use of backticks - ` these are not apostrophes, on a UK keyboard the key is next to the number one key.

Then extract the source:
cd /usr/src
tar xjf linux-source-3.2.tar.gz
Note - at the time of writing the source was for kernel 3.2, might have changed when you read this!

2) Copy your running kernel config into the source folder so any compiled modules are use the correct settings:
cd /usr/src/linux-source-3.2
cp /boot/config-`uname -r` .config
cp /usr/src/linux-headers-`uname -r`/Module.symvers ./
3) Patch the plusb module to work with our PL-2501.  I found a patch someone had made and downloaded it.  However it failed to patch against my source code.   The patch was very simple though so I manually patched my file and created a new patch file that can be downloaded here:
plusb.patch
Then apply the patch:
cd /usr/src/linux-source-3.2/drivers/net/usb/
patch < plusb.patch 
4) build your module:
cd /usr/src/linux-source-3.2
 make prepare
 make scripts
 make SUBDIRS=drivers/net/usb modules
 Note - this actually builds all the modules in the net/usb folder but there's not many and it doesn't take long.

5) Replace the old module with your new one:
rmmod -f plusb
mv drivers/net/usb/plusb.ko /lib/modules/`uname -r`/kernel/drivers/net/usb/
6) Load the module and make sure it's worked:
modprobe plusb
ifconfig -a
And you should see the usb0 interface listed that you can now use like any other network interface.

Raspberry Pi howto 

The process is very similar on the R-Pi.  To keep things as simple as possible I used the kernel maintained by the Raspbian people.  If you are using a non-standard kernel or the latest kernel from the Raspberry Pi foundation it'll be a lot more involved as they don't provide header packages.

You will need quite a lot of free space on your Pi's filesystem for this, I'd estimate at least 1GB.  It depends what you already have installed.

1) Install the latest Raspbian kernel and the source package:
apt-get install linux-image-rpi-rpfv
Note - I'm not sure if this is normal (I had been messing about with kernels a fair bit) but after installing this I had to copy the new kernel over the old one before rebooting would get it to load:
cp /boot/vmlinuz-3.10-3-rpi /boot/kernel.img
Or you could add a "kernel=vmlinuz-3.10-3-rpi" line to the config.txt file.

3) Get the kernel headers and source:
apt-get install linux-headers-rpi-rpfv linux-source-3.10
Note - make sure you have the deb-src repo in your sources.list.  http://www.raspbian.org/RaspbianRepository

4) Extract the source:
cd /usr/src
tar xJf linux-source-3.10.tar.xz
Everything else is the same as the instructions for standard Debian, step 2 onwards.  Just replace "linux-source-3.2" with "linux-source-3.10" anywhere.

After that, you'll have a usb0 interface on the Raspberry Pi too.  Once you've assigned IP addresses to this interface on both systems you can access one via the other simply using ssh.

You'll definitely want the device to come up at boot time.  So create a udev rule (create a file called something like /etc/udev/rules.d/99-plusb.rules) and put this in it:
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="067b", ATTR{idProduct}=="2501", RUN+="/sbin/modprobe plusb"
Do this on both systems.

In case these are of any use, here are my finished working modules for both the Raspberry Pi and x86 (Intel Atom) server:

plusb-3.2.0.4-686-pae.tar

plusb-3.10-3-rpi.tar

Tuesday, 14 January 2014

Misunderstood SIP - Registration Expiry

How Registration expiry and Re-Registering works seems to be one of the most mis-understood concepts in SIP.

Registration Expiry

A SIP UAC (such as your SIP telephone) sends a Registration request to a SIP UAS (such as your PBX or hosted platform).
This Registration request has an Expires header in it (which can be an individual header or a tag in the Contact header). The value used is nearly always a configurable setting in the UAC itself.

The UAS responds to the Registration request accordingly (usually there is a process of Authentication that goes on which I wont go into here). At the end, if the Registration is accepted, the UAS will send an OK message to the UAC which contains the actual Registration expiry time (again, either an individual Expires header or as a tag in the Contact header). 

The important thing to note is that it is the UAS which decides what the expiry will be, not the UAC which is where most people go wrong. The assumption is often that if you set an expiry of 600 seconds in the UAC settings then that's what gets used. Not necessarily the case, the UAS has the final say.

Often a SIP PBX will have settings to control minimum & maximum permissible values for the Registration Expiry. Then a UAC is allowed to use any value inside this range. Outside the range, the UAS decides what gets used. Sometimes there is a default expiry to use when a UAC selects something outside of the permissible range.

Re-Registering

Once a UAC is Registered, it has to decide when to re-Register. The Expiry is not a timer to start re-Registering, it's the time when the UAS will assume the UAC isn't there any more. Think of it as a Re-Registration deadline.

So, a UAC must have completed it's re-Registration before this Expiry time or calls will stop working. There is no definitive strategy for doing this in SIP, it seems to be up to the UAC manufacturers to decide what they think is best. 

Some halve the Expiry and then start to Re-Register from that point onwards, so with an Expiry of 180 seconds, you'll start to see more Register messages after 90 seconds. This gives more than enough time for the Re-Registration to complete before the previous Registration expires. 

Other UACs choose different times either based on some percentage of the Expiry, a set number of seconds before Expiry etc...etc... 

Due to this second misunderstanding, many people think that they can alleviate Registration problems by setting a very low Expiry. In reality this nearly always makes it much worse as the UAC now has less time to actually get Re-Registered. 

Generally, I wouldn't set Registration Expiry to less than 600 seconds. There can be some circumstances when it makes sense to use a lower setting (e.g. a mobile roaming handset moving from network to network regularly might need a shorter Expiry) but in general it should be avoided.

Trying to use a very short Re-Registration timer for overcome NAT mapping issues (where a NAT router is destroying NAT mappings too quickly), isn't the correct way of doing it. Any decent UAC will have a NAT keep-alive setting somewhere (or often this happens automatically). Then the UAC will send out a SIP Options message or sometimes just a blank packet on port 5060 to keep a NAT mapping open. Use this as very short Expiry will often cause others problems as described above.

Wednesday, 4 December 2013

Blocking Asterisk SIP Invite attacks with fail2ban

There's a lot of fuss about people putting too much trust into a program called fail2ban when using it with Asterisk to block SIP attacks.

Such as:

http://forums.digium.com/viewtopic.php?t=78988

Whilst I fully agree that simply installing fail2ban and relying on that as your only protection against SIP hacks is foolish, I do think it is still a useful tool.

The biggest current problem with it is that while it's quite good at stopping Register attacks, it doesn't do anything out of the box to protect against Invite floods.  This is where attackers send in SIP Invite messages to attempt calls and to brute-force passwords.

The good news is that simply adding an extra regex line to the fail2ban config can help in some cases.

This works with Asterisk 1.8 (possibly newer versions, I've not tested yet).  There is a big change you must make first.  Asterisk comes with a setting in sip.conf called "allowguest" which controls whether you allow un-authenticated SIP calls in or respond with a 401 Authentication Required message.  It is normally recommended to set this to "no" to stop unsolicited calls.  This addition to fail2ban will NOT work with this set, you must set it to "yes" or Asterisk will not log anything for fail2ban to act on.

Lots of people will say that this is a bad idea (and I don't necessarily disagree with them).  For my own use, I need this set anyway.  There is a possible argument saying that you're safer setting it to "yes" and allowing fail2ban to catch call attempts than leaving it to "no" and not knowing about these calls coming in.
Be aware that your default context (i.e. the context that external calls fall in to) must be carefully set up so as to only include extensions that you really want exposing to the outside world.  This would normally be your inbound phone numbers only.
If someone manages to guess one of your inbound numbers (or intentionally sends in calls to your numbers because they already know them) then you could get unsolicited "spit" (SIP spam) calls.

If you decide you want to do this or you already need allowguest=yes for some other reason like me, then here is what to do...

Find the list of regular expressions in the file /etc/fail2ban/filter.d/asterisk.conf (on Debian Wheezy, may be elsewhere on other systems) and add this line:

NOTICE.* .*: Call from '.?' \(<HOST>:.*\) to extension '.*' rejected

Reload fail2ban and it should stop multiple Invites from the same source IPs.

I have to admit, I have only just done this and I have so far only done a small amount of testing using SIPp.  So there could be cases it doesn't catch Invites and it may block valid Invites sometimes.  I will continue to test and update this post as I find more things out.

In general you should always be keeping an eye out on what is happening to your Asterisk installations (or any SIP system for that matter, this isn't limited to Asterisk).  My next plan is to write a monitoring tool in Python that'll keep an eye on logs and activity for unusual things going on.

Tuesday, 29 October 2013

Quickly install Asterisk and Dahdi on Debian Wheezy

Most how-to guides I've seen on setting up Asterisk with Dahdi on Debian start off by telling you to download source from Digium and compile it yourself.

That's fine sometimes but I prefer to stick to the Debian maintained packages on a production system.

The main problem with this is that you don't get the Dahdi kernel modules in the Dahdi package, you need to build them on your system.  Fortunately, the Debian Module-Assistant makes this easy.

It's worth noting that even if you don't have an ISDN or analogue card in your system, if you are using Asterisk 1.8 or lower, you'll need Dahdi for certain things such meetme conferences as they need it for a timing source.

Getting Asterisk installed is just a case of installing the right packages.  Libpri is needed if you are going to be using a PRI (E1/T1/J1) card or a BRI card (yes, really, because for BRI to work Dahdi emulates PRI):

apt-get install asterisk libpri1.4 asterisk-dahdi
You'll get Asterisk 1.8 with Debian Wheezy.  During the install you'll be asked for your countries ITU telephony code.  This is the country code needed to dial you from other countries, for the UK it is 44.

At this stage you have a working Asterisk installation but Dahdi will fail to start due to missing kernel modules.  You must build these modules from source using module-assistant.  Install the things you need to build:

apt-get install linux-headers-`uname -r` dahdi-source
m-a a-i dahdi
'm-a' is short for module-assistant!

Now you can configure and start Dahdi:

dadhi_genconf
service dahdi restart
asterisk -rvvvvv
dahdi show status
That's it, it's actually a very quick and easy process. 
 

 
 
 

Wednesday, 2 October 2013

LXC Linux Containers on Debian Wheezy

Linux Containers (LXC) is a fairly new operating-system level virtualisation technology.  

Getting it working in Debian Wheezy isn't as straight forward as it could be right now.  There are a couple of fixes needed (which I'm sure are in the pipeline).  Here are my notes on getting it going.  This may not be the best way of doing it and certainly wont be the only way but it works!

Also be aware that LXC is considered by many to not be production ready yet.  There are potential security issues.  This isn't an issue when you are using it yourself just to play with or as I do, to set up virtual systems on a server or desktop where I'm the only user!


How To Install LXC on Debian Wheezy and configuring the host


Install required packages:
  apt-get install lxc bridge-utils libvirt-bin debootstrap
Add this line to fstab:
  cgroup    /sys/fs/cgroup    cgroup  defaults    0  0

Mount it and make sure it is mounted OK

Set up a network bridge on the host in /etc/network/interface along the lines of:
  auto br0
  iface br0 inet static
        address 192.168.0.100
        netmask 255.255.255.0
        gateway 192.168.0.1
        bridge_ports eth0
        bridge_fd 0
        bridge_maxwait 0

Bring it up:
  ifup br0

and check it's OK.


Creating a virtual system (container)

Generate the container and it's root file system using the supplied script:
  lxc-create -n myvps -t debian
where 'myvps' is the host name you want to give the container and also the folder it's file system will be in.  You'll be asked various questions, they're self explanatory.

Note - I'll be using 'myvps' throughout the example, the commands will fail if you don't replace this with the real host name.  Copying&pasting directly from online how-to guides is never a great idea :)

If you don't know what a pre-seed file is then you can just skip that question that comes up at first!

Edit the config file /var/lib/lxc/myvps/config to add network device config such as:
  ## Network
  lxc.network.type                        = veth
  lxc.network.flags                       = up
  lxc.network.hwaddr                      = 00:FF:00:00:00:01
  lxc.network.link                        = br0
  lxc.network.name                        = lxceth1
  lxc.network.ipv4  = 192.168.0.1/24

Each container needs a unique MAC and device name (and IP, obviously).  Omit the last line if you want DHCP.

Edit the network config for the container /var/lib/lxc/myvps/rootfs/etc/network/interfaces to add the network devices such as:
  auto lxceth1
  iface lxceth1 inet static
  address 192.168.0.1
  netmask 255.255.255.0
  gateway 192.168.0.1
  dns-nameservers 192.168.0.1
Or as DHCP if no IP was put in the config file above.

At this point, you should be ready but there are a couple of fixes needed which the lxc scripts for Debian don't currently cover.

Fixing LXC Debian set up

At the time of writing, there are a couple of problems with the way the lxc-create script works in Debian.  One of these is that it doesn't create the necessary tty1, so manually add it:
  mknod -m 660 /var/lib/lxc/myvps/rootfs/dev/tty1 c 5 1
At this stage the container will actually start up so do that:
  lxc-start -n myvps -d
Note - the -d option detaches from the container's console.  You need to do this or you'll be permanently attached to it unless you completely stop the container!

Then console to the container:
  lxc-console -n myvps
This is safe because you can disconnect at any point using the "ctrl+a q" combination and the container stays running for you to connect to later on.

Log in using the root password you set during the container configuration process.

sshd will be running but broken, keys need regenerating:
  dpkg-reconfigure openssh-server
Two last things to fix are to add a default route and put a working dns server into /etc/resolv.conf (which is easiest from the host machine rather than the container due to lack of a text editor!).

Now you have a very basic Debian install.

To fix locale warnings with apt-get:
  dpkg-reconfigure locales 
To make containers start on boot of host (do this on the host, not the container):
ln -s /var/lib/lxc/myvps/config /etc/lxc/myvps
And make sure LXC_AUTO is set to "true" in /etc/default/lxc on the host so it starts on boot (if you want that).

Once you are familiar with this, setting up containers is very easy.  It will be even easier once the lxc-create debian script is improved.  I have used LXC in Ubuntu too and it is stupidly easy to get it going (although as a result you are given less options and less flexibility unless you re-configure it).

Wednesday, 7 August 2013

Nexus 4 red light of death

OK just a quick note this one but it might help some people out.

The other day it seemed that my beloved Nexus 4 suffered from the red light of death.  The battery had died overnight.  I plugged the phone in at work, it normally leave it connected to my PC there during the day and it does charge.  However in this case, it just wouldn't turn on and I kept getting the red light of death.  It was showing the charging animation still.

I plugged it into a supposed 1 amp power supply (which I normally use with a Raspberry Pi) but it still wouldn't turn on which had me worried.

Long story short, when I got home I connected the proper charger up (well actually my nexus 7 charger) and it came back to life! 

So if you seem to have the red light of death problem make sure you are using a decent charger - ideally the original nexus 4 one or better.  The 1 amp PSU I had at work clearly isn't really capable of supplying 1 amp. 

Thursday, 2 May 2013

Hacking the Xenta IP-11IR-H264-PT IP camera from Ebuyer part three - network access

Just a quick update.  I was going to try to get sshd working but decided to try to get telnetd working first as it is already on there (but disabled).

Firstly, to get to a command line through serial without having to use the ctrl+z method described previously.  Get to the command once once using that method, then use vi to edit the file /etc/boottab, this controls the programs that start on boot.

Find a line near the end:

/bin/vs/vs_auto.sh
and add an ampersand at the end like this:

/bin/vs/vs_auto.sh &
Then save the file.  This will background the vs_server program so you can get to the command line with it running.

The device has a watchdog running on it, this looks for various events and makes sure various processes are running.  If they are not then the camera reboots.  It is this that reboots the device if you stop vs_server by doing ctrl+c or ctrl+z once it's finished booting before editing the boottab file.

There's not much you can do with the watchdog as it is controlled by the program /bin/vs/vs_server which is a compiled ELF executable and not editable.

You can run telnetd now but you will find that it attempts to start a 2nd copy of vs_server, which then crashes and causes another reboot almost as soon as you telnet in!

To get telnet starting at boot, find a comment in the /etc/boottab file that reads:

#start Telnetd
And add:

/bin/telnetd &
On the next line.  Save and close the file.

Now your problem is stopping vs_server running a second time when you telnet in.  Edit the file /etc/profile file (which is executed whenever a user logs in) and find the line:

/etc/boottab ipcamera
Remove this line and replace it with the following section of code:

if [ -z "$(pidof vs_server)" ]
  then                    
  /etc/boottab ipcamera
fi
Save and close the file.  This code means the vs_server is only started if the vs_server process does not already exist.  So vs_server still starts when the camera boots (as well as the watchdog it has the web server, rtsp server etc... built into it).  But, it wont attempt to run again when you telnet in, or log in via any other method for that matter.

That's it.  Now you can put away your serial cable and telnet to your camera whenever you want!