RouterBoard as a Home Router – 4 1/2 years on

A while back I mentioned a follow up to an old blog post about the RouterBoard that i’d recently purchased and setup for home use. This is a very belated update on that board.

My requirements have since changed from the original post, but not dramatically so. The requirement for LACP has disapeared, IPSec is no longer used, but a requirement for Dynamic Routing has appeared.

All in all, I have to say that I still cannot recommend RouterOS enough. I’ve been using it the past 4 1/2 years, and have recommended a large number of folks to use it.

The main reason behind this is that it just works, there’s not really any faffing about that needs to be done, and if you’re running the stable release, everything does just work.

Feature wise, this is right up there with some of the big brands (Cisco, Juniper et all), however its fair to say not with the same price tag.

Continue reading RouterBoard as a Home Router – 4 1/2 years on

iSCSI Target re scanning on VMWare

If you’re using iSCSI on VMWare but have a requirement to rescan the luns after a machine has booted (For example a VM which has DirectPath to a Storage card enabled, which is hosting your iSCSI luns) you can simply do so with the following command

F5 LoadBalancing on a per app mountpoint

With some customers solutions I’ve seen a common requirement to do loadbalancing decision based on the actual application server serving the content, this obviosuly introduces a few issues if you’re using a single base URL for this

If we take the example below

With this in mind, its not possible to use traditional Layer 3 / Layer 4 load balancers, and would require a L7 Load balancer, such as a F5 LTM or Riverbed Stingray (ZTM/ZXTM). I’m going to concentrate on the F5 in this example.

On the F5 you have the abbility to use a iRule to preform load balacning actions. On a Virtal Server that has the “http” profile enabled, you would be able to add a iRule similar to below.

There are multiple events that this will trigger.

  1. CLIENT_ACCEPTED
  2. This event is triggered whenever a new connection is made to the Load balancer. In our case the code will check to see if the virtual servers name contains “testing”, which if it does sets the serverpool variable to contain “testing”, otherwise it will set it to “liveserver”

  3. HTTP_REQUEST
  4. This event is triggered on any new HTTP Request. In our case this preforms a ‘switch’ (a multiple if/else statement) on the URL. We do however preform two “transformations” on the URL, the first is we convert it to lower case. the second is that we only take the URL between the first two /’s. So for the URL http://www.example.com/app1/test we would use app1 for teh switch statement.
    Based on the path, we will then set the NEWPOOL variable, and then set the pool to NEWPOOL

  5. HTTP_RESPONSE
  6. This event is triggered when the server send a response to a HTTP Request. We add the “X-AP” header to the response, and set this to the NEWPOOL variable.

‘Instant’ Upload to Rackspace CloudFiles

Using inotify and the ‘swift’ client tools it is possible to automatically upload files to cloudfiles as they are written to disk.

This code is untested and might cause planes to drop from the sky, use it at your own risk!

Google Authenticator F5 IRule

Two Factor authentication is rather hit and miss in terms of support from web apps.

A quick look around the web turns up an article on DevCentral for a solution to implement google authentication with ldap. As I don’t run a LDAP server at home I needed to hack up the script a bit. This iRule implements the two factor side of things from the above article, but skips the LDAP side of things, as it’s not needed!

Yubikey and server authentication

After starting to use the Yubikey for LastPass and various other online servers I’ve started also using my yubikey for SSH access to my server(s).

I’ve touched on google_authenticator and pam_yubico for authentication in a previous post however I will be going into this in a bit more detail.

Taking a machine at home as an example. My requirements are simple

  • NO SSH Key access to be allowed – as there is no way to require a second factor with an SSH Key (Passphrases can be removed or a new key generated)
  • Access from Local machines to be allowed without Two Factor being enabled
  • Yubikey to be the Primary TFA
  • Fall back to google authenticator should either the Yubico servers be down, an issue with my keys or I just don’t have a USB port available (IE I’m on a phone or whatever)
  • In order to meet these requirements I’m going to need the following

  • yubico-pam Yubikey PAM
  • Google Authenticator PAM
  • pam_access
  • The server is running Archlinux, and luckily all of these are within AUR – and as such I’m not going to cover the install of the modules.

    In order to restrict SSHd access as above I need the following auth lines in /etc/pam.d/sshd

    The next step is ensure that the relevant users and IP are listed in /etc/security/access_yubico.conf

    After this is setup we will also need to setup the yubikey file /etc/yubikey

    I’m not going to cover configuration of google authenticator with the google-authenticator command

    The final changes are to the /etc/ssh/sshd_config ensuring that the following are set

    PAM and Two Factor authentication

    As the need for Two factor authentication is a requirement for PCI-DSS (Payment Card Industry standard) and SSH Key with password is not always deemed to be an acceptable form of Two factor authorisation there is now a surge in different forms of two factor auth, all with their own pros and cons.

    For a small business or ‘Prosumer’ (professional consumers) the market incumbent (RSA) is not a viable option due to the price of the tokens and the software / appliance that is required. There are cheaper (or free!) alternatives for which two that I’ve used at Google Authenticator, and Yubikey.

    Google Authenticator is an OATH-TOTP system that much like RSA generates a one time password once every 30 seconds. It’s avaiable as an App for the Big three mobile platforms (iOS, Android and Blackberry).

    Yubikey is a hardware token that emulates a USB keyboard, that when the button is pressed, generates a one time password. This is supported by services such as lastpass.

    Both solutions have the ability to be used with their own PAM modules. Installation of either is simple, but what happens if you want to use both, but only require one of these.

    Luckily PAM makes it quite easy !

    In the above example the user must enter a password and then provide either their yubikey or their google_authenticator.

    Should the password be incorrect the user will still be prompted for their yubikey or google authenticator, but will then fail. Should they provide a password and then their yubikey, they will not be asked for their google authenticator. Should they provide password and not a yubikey, they will be prompted for their google authenticator!

    Auditd logging all commands

    A common requirement for PCI-DSS is for all commands run by a user who has admin privileges to be logged. There are many ways to do this, most of the time people will opt for a change to the bash configuration or to rely on sudo. There are many ways arround this (such as providing the command that you wish to run as a paramater to SSH). As the linux kernel provides a full auditing system. Using a utility such as auditd, we are able to log all commands that are run. The configuration for this is actually quite simple. In /etc/audit/audit.rules we need to ensure that the following exists.

    -a exit,always -F arch=b64 -S execve
    -a exit,always -F arch=b32 -S execve

    This will capture any execve system call (on exit) and will log this to the auditd log. A log entry will look similar to below.

    type=SYSCALL msg=audit(1318930500.123:3020171): arch=c000003e syscall=59 success=yes exit=0 a0=7fff65179def a1=7fff65179ec0 a2=7fff6517d060 a3=7ff54ee36c00 items=3 ppid=9200 pid=9202 auid=0 uid=1000 gid=100 euid=1000 suid=1000 fsuid=1000 egid=100 sgid=100 fsgid=100 tty=(none) ses=4 comm="xscreensaver-ge" exe="/usr/bin/perl" key=(null)
    type=EXECVE msg=audit(1318930500.123:3020171): argc=5 a0="/usr/bin/perl" a1="-w" a2="/usr/bin/xscreensaver-getimage-file" a3="--name" a4="/home/welby/Pictures"
    type=EXECVE msg=audit(1318930500.123:3020171): argc=3 a0="/usr/bin/perl" a1="-w" a2="/usr/bin/xscreensaver-getimage-file"
    type=CWD msg=audit(1318930500.123:3020171): cwd="/home/welby/Downloads"
    type=PATH msg=audit(1318930500.123:3020171): item=0 name="/usr/bin/xscreensaver-getimage-file" inode=208346 dev=fe:02 mode=0100755 ouid=0 ogid=0 rdev=00:00
    type=PATH msg=audit(1318930500.123:3020171): item=1 name=(null) inode=200983 dev=fe:02 mode=0100755 ouid=0 ogid=0 rdev=00:00
    type=PATH msg=audit(1318930500.123:3020171): item=2 name=(null) inode=46 dev=fe:02 mode=0100755 ouid=0 ogid=0 rdev=00:00

    This should keep most auditors happy :)

    Moving part of an lvm vg from one pv to another

    Lets say that you’ve got multiple physical volumes (PV) in a Volume Group (VG) and you want to migrate the extents from one PV to another, this can be acomplished with a quick and easy pvmove command.

    For example

    pvdisplay -m
    --- Physical volume ---
    PV Name /dev/sdb1
    VG Name INTEL_RAID
    PV Size 2.73 TiB / not usable 4.00 MiB
    Allocatable yes (but full)
    PE Size 4.00 MiB
    Total PE 714539
    Free PE 0
    Allocated PE 714539
    PV UUID XWiRzE-Ol3d-38En-ND6b-qo93-4zeF-xv8zDv

    --- Physical Segments ---
    Physical extent 0 to 604876:
    Logical volume /dev/INTEL_RAID/MEDIA
    Logical extents 0 to 604876
    Physical extent 604877 to 617676:
    Logical volume /dev/INTEL_RAID/backups_mimage_0
    Logical extents 25600 to 38399
    Physical extent 617677 to 617701:
    Logical volume /dev/INTEL_RAID/EPG
    Logical extents 0 to 24
    Physical extent 617702 to 643301:
    Logical volume /dev/INTEL_RAID/backups_mimage_0
    Logical extents 0 to 25599
    Physical extent 643302 to 714538:
    Logical volume /dev/INTEL_RAID/MEDIA
    Logical extents 604877 to 676113

    --- Physical volume ---
    PV Name /dev/sdc1
    VG Name INTEL_RAID
    PV Size 2.04 TiB / not usable 2.00 MiB
    Allocatable yes
    PE Size 4.00 MiB
    Total PE 535726
    Free PE 430323
    Allocated PE 105403
    PV UUID laOuKy-5FZa-cJ3h-JffV-qUub-diKC-O0wVqK

    --- Physical Segments ---
    Physical extent 0 to 25599:
    Logical volume /dev/INTEL_RAID/backups_mimage_1
    Logical extents 0 to 25599
    Physical extent 25600 to 54202:
    Logical volume /dev/INTEL_RAID/MEDIA
    Logical extents 676114 to 704716
    Physical extent 54203 to 67002:
    Logical volume /dev/INTEL_RAID/NZB_DOWNLOAD
    Logical extents 0 to 12799
    Physical extent 67003 to 79802:
    Logical volume /dev/INTEL_RAID/backups_mimage_1
    Logical extents 25600 to 38399
    Physical extent 79803 to 105402:
    Logical volume /dev/INTEL_RAID/OLD_VM
    Logical extents 0 to 25599
    Physical extent 105403 to 535725:
    FREE

    From here you can see that /dev/INTEL_RAID/MEDIA is a Logical Volume (LV) on both PVs within the VG. If I was wanting to grow my mirrored LV, which requires space on both PVs, I’d have to migrate some of the extents of another LV. If I wanted to move some of the MEDIA lv, I should be able to do the following

    pvmove /dev/sdb:643302-714538 /dev/sdc

    This will move extents 643302-714538 to the next contiguious block on /dev/sdc

    Dahdi In LXC

    At home we use various VoIP providers to either get free calls to various places (GTalk/GVoice to america for instance) and various other destinations over SIP providers

    I’ve been using Asterisk for years (I remeber the 0.7 release) and have implemented it for companies before, usually with no issues, baring the continuall deadlocks in the 1.2 range. Recently I enabled my VoIP network segment for IPv6 only to find that GTalk stoped working on IPV6 Day. After a bit of digging about, it seems that Asterisk 1.8 does support IPV6! But, gtalk and similar are not supported, SIP is infact the only first class citezen it seems.

    I’ve toyed with using freeswitch before, but unfortuantly have had varied sucsess with FreeTDM to Dahdi with BT caller ID and the likes. I did hack in support for it, but I’m not too sure if I trust my code, as my C is quite rusty to say the least.

    I did however come up with another solution!

    As I’m running a moderatly new Linux Kernel I can use LXC – Linux Containers – which are effectilvy the same idea as a wpar, chroot, openvz, whatever. After setting up asterisk in the LXC I needed to expose my Dahdi card to it. LXC allows you to restrict access on a per device basis. I’ve setup Dahdi on the host machine as normal so the kernel modules can be loaded etc. Once this is done I’ve preformed the following within the LXC

    cd /
    mkdir dev/dahdi
    mknod dev/dahdi/1 c 196 1
    mknod dev/dahdi/2 c 196 2
    mknod dev/dahdi/3 c 196 3
    mknod dev/dahdi/4 c 196 4
    mknod dev/dahdi/channel c 196 254
    mknod dev/dahdi/ctl c 196 0
    mknod dev/dahdi/pseudo c 196 255
    mknod dev/dahdi/timer c 196 253
    mknod dev/dahdi/transcode c 196 250

    This creates the Device nodes within /dev/ for my 4 dahdi channels (3FXS 1FXO if anyone is interested). After this I’ve added the following to the lxc config file, to allow the LXC to have access to these devices


    # If you want to be lazy just add this line
    #lxc.cgroup.devices.allow = c 196:* rwm

    #Otherwise use the following
    lxc.cgroup.devices.allow = c 196:0 rwm
    lxc.cgroup.devices.allow = c 196:1 rwm
    lxc.cgroup.devices.allow = c 196:2 rwm
    lxc.cgroup.devices.allow = c 196:3 rwm
    lxc.cgroup.devices.allow = c 196:4 rwm
    lxc.cgroup.devices.allow = c 196:250 rwm
    lxc.cgroup.devices.allow = c 196:253 rwm
    lxc.cgroup.devices.allow = c 196:254 rwm
    lxc.cgroup.devices.allow = c 196:255 rwm

    This will obviously only work for the first 4 dahdi channels, but if you need more, just continue adding the 196:x lines, replacing x with the channel number, and also ensuring that you create the device nodes in the same way