Ultimate Home Server - Configuring the base system

Alright, in this post I’m trying to get the base system set up with a decent GRUB configuration, a very simple firewall, the OpenSSH server, and getting encryption keys to work on an USB stick. I will include some links to further information in each section. You will need to be root for most of this, so log in and do sudo -i to switch to a root console.

But first! If you get the dreaded GRUB error 17 cannot mount selected drive:

On the screen that says “press any key to continue”, umm.. press any key and continue :)

On the GRUB menu screen highlight the default boot line and press ‘e’ to edit, highlight the line that looks like: root (hd3,0) though it may have different numbers in there, change it to look like: root (hd0,0) and hit enter. back on the boot menu press ‘b’ to boot. Hopefully that will get you booted up and ready to go. Once booted you will need to fix the /boot/grub/menu.lst to match the correct boot drive. switch to root with sudo -i and do:

vim /boot/grub/menu.lst

change all of the references in there to match what you used to boot successfully (most likely (hd0,0)). I’m assuming you know how to use vim…

If that doesn’t work for you then this grub page may help. I will be returning to GRUB, for security concerns,  once the OpenSSH server is properly set up.

Before starting on all of this you need to update! Just type:

apt-get update && apt-get dist-upgrade

This is needed to get some updates that effect the security of OpenSSh!

Firewall: Ubuntu Hardy Heron comes with an interface to ipchains that is called ufw (uncomplicated firewall), it looks like it is much simpler than ipchains (I am hoping so…), so I’m going to try it out. There is a page on the Ubuntu help site about it, and other helpful pages at the funestra.org howtos and the Ubuntu wiki.

There are a few things to remember here: this program uses /etc/services as well as other things so you can specify services to allow by service name, meaning protocol:port, or by a packages meta-data (though I’m not sure what that means, I think it means that packages can provide their own data in some form of file???). The gist of that is that you can cat | grep /etc/services to get the protocol:port for the service you need then use that information to allow or deny things in ufw. When it is first enabled ufw will ‘flush the chains’ and connections will be dropped. Rules can be set up before ufw is started. All of that means that if you are doing this remotely, like via SSH then you need to make sure you set a rule to allow SSH connections before you start the firewall.

So, assuming that you’ve used 192.169.1 as your internal addressing, and you haven’t set SSH up to use a different port than its default, you can allow remote SSH connections, which is the first thing I am worried about, by doing:

ufw allow proto tcp from 192.168.1.0/24 to all port 22

That will allow all ip’s in the 192.168.1.0-255 range to connect to any ip on the server on port 22, which is what SSH uses by default. If you want a little more restriction you could do:

ufw allow proto tcp from {the ip of your workstation} to {the LAN side ip of your server} port 22

Which allows only your computer to connect to only the LAN side of your server on the default SSH port. You can see the protocol and port by doing:

cat /etc/services | grep ssh

which returns:

ssh        22/tcp                # SSH Remote Login Protocol
ssh        22/udp

showing port 22 and protocols for tcp and udp.

Now you can do:

ufw enable && ufw default deny

to start the firewall and set the default action to deny connections. Check it out with:

ufw status

After those simple steps you should have a firewall up that is blocking everything but tcp connections on port 22.

OpenSSH: Now we need to configure the SSH server itself. I’m going to take a lame shortcut here, but there is an excellent page about advanced OpenSSH configuration at the Ubuntu help site. That page should be excellent for setting up all of your needs. Just a couple of notes: If you use the banner thing they have there you may have a problem creating the symlink from /etc/issue to /etc/issue.net it seems the file already exists, just add an ‘f’ after the ‘-s’ to force it to overwrite the old file, like this:

ln -sf /etc/issue /etc/issue.net

Also, I did not mess with the public key stuff as I’m planning on setting up kerberos to take care of authentication for such things…

After completing all of the stuff you want to use from that page you should now be able to log into the server from a workstation through OpenSSH. This makes things much easier, at least for me, as now it is possible to copy/paste and stuff like that, but, we still have some more work to do here, so if it’s not convenient for you to get to your server you may not want to move away from it just yet…

GRUB security: If you had the GRUB error 17 mentioned at the beginning of this post then you’ve already had the /boot/grub/menu.lst file open, but now we’re going to open it again. When we set up the keys on the USB stick it will be necessary to rebuild the initrd file which causes your menu.lst file to be updated. It’s best to have it all in order before doing that. This time I’m posting a link to a grub security howto on the ubuntu forums. This step is optional, and argued about a lot, but I feel it can’t hurt anything so why should I leave a security hole open if I don’t have to…

Once you’ve finished with that you need to follow step two of the howto setup passwordless encryption in Debian Etch page. This was a very helpful howto, but I had to figure a few things that were lacking for my particular project. I’ll be covering that stuff here.

After you’re done setting up the ’safe’ boot option you need to create some key files, do that by typing:

dd if=/dev/random of=/media/keys/root.key bs=1 count=256
dd if=/dev/random of=/media/keys/root.key bs=1 count=256

That creates one for the root file system, and one for the data file system.

Now you need to enable the use of those keys to unlock the encrypted partitions, but first you need to know how those partitions are called by the encryption system. This information is in /etc/crypttab, which we need to edit anyway so you may as well do:

vim /etc/crypttab

Mine looks like this, after editing:

sda2_crypt /dev/disk/by-uuid/a172f191-7974-4f82-8d66-5400c47dabd2 root.key luks,keyscript=/usr/local/sbin/root-crypt-script.sh
system--storage-storage--data_crypt /dev/mapper/system--storage-storage--data data.key luks,keyscript=/usr/local/sbin/data-crypt-script.sh

The important thing here is that you need to change the word ‘none’ in your unedited file to the name of the key file, in my case it is root.key for the root file system, and data.key for the other partition. You will also need to add the location of the scripts that are used to load those key files at the end of each line (basically everything after the ‘,’ on both lines. These scripts have not been created yet, but we’ll get to that right after we finish enabling the key files for the partitions.

To enable these files you need to call cryptsetup and add them for the proper drives. The commands I used looked like:

cryptsetup luksAddKey /dev/disk/by-uuid/a172f191-7974-4f82-8d66-5400c47dabd2 keys/root.key
cryptsetup luksAddKey /dev/mapper/system--storage-storage--data keys/data.key

Yours will use lines from your /etc/crypttab file, just remember which partition is which and which key unlocks each one, this is why I used the naming schemes that I did, it made that a lot easier.

After telling the encryption system about our keys we need to set up the scripts that will load them during boot. The modified script at the previously linked site works a charm for the root file system during very early boot up. This can be copy/pasted through a SSH connection into vim and saved as /usr/local/sbin/root-crypt-script.sh or whatever you want to name it and probably wherever you want to put it, just make sure the name and path match what you put in the /etc/crypttab file, and change the “MD=/tmp-usb-mount” line to read “MD=/media/keys“, or wherever you’ve mounted your USB stick and saved the key files. Once it is saved it needs to be made executable. I used the following command, as root through a SSH connection to set this one up:

vim /usr/local/sbin/root-crypt-script.sh

Then copy/paste the script, making sure to change the “MD=/tmp-usb-mount” line to read “MD=/media/keys” and do:

chmod a+x /usr/local/sbin/root-crypt-script.sh

to set the executable bit.

That was the easy part, unfortunately the other partition gets unlocked later in the boot up process, and apparently there are some issues with busybox, or something else… at any rate, that script would not unlock the data partition, and when it failed it would go into a loop saying that I needed to input a password, then that would blow up with an illegal option error and start over. Fortunately that loop would only run so many times and eventually drop me into a repair console. After many different attempts at various things I managed to come up with the following script, which I saved as /usr/local/sbin/data-crypt-script:

#!/bin/sh

# Part of passwordless cryptofs setup in Debian Etch.
# See: http://wejn.org/how-to-make-passwordless-cryptsetup.html
# Author: Wejn <wejn at box dot cz>
#
# Updated by Rodolfo Garcia (kix) <kix at kix dot com>
# For multiple partitions
# http://www.kix.es/
# USB Disk partition type (ext2 or vfat)PARTTYPE=ext2

# Key file in the USB disk
KEYFILE=.key

# # # # # CODE # # # # #
MD=/media/keys

if [ "x$1" = "x" -o "x$1" = "xnone" ]; then
KEYF=$KEYFILE
else
KEYF=$1
fi

echo "Locating $KEYF ..." >&2

USBLOAD=0
FSLOAD=0

cat /proc/modules | grep usb_storage >/dev/null 2>&1
USBLOAD=$?

cat /proc/modules | grep $PARTTYPE >/dev/null 2>&1
FSLOAD=$?

if [ $USBLOAD -gt 0 ] || [ $FSLOAD -gt 0 ]; then
modprobe usb_storage >/dev/null 2>&1
modprobe $PARTTYPE >/dev/null 2>&1
echo "Done loading required modules ..." >&2
sleep 7
else
echo "Required modules already loaded ..." >&2
fi

OPENED=0

echo "Retrieving $KEYF from USB keychain ..." >&2
mount $MD

if [ -f $MD/$KEYF ]; then
cat $MD/$KEYF
OPENED=1
break
fi

if [ $OPENED -eq 0 ]; then
echo "FAILED to retrieve $KEYF from USB keychain ..." >&2
echo -n "Try entering your password: " >&2
read -r A </dev/console
echo -n "$A"
else
echo "Successfully retrieved $KEYF from the keychain!" >&2
fi

umount $MD

This script was heavily modified from the script I got from the other web site, very little of the original remains. The biggest problem I have with this script is that if you do indeed need to input the password it will be echoed onto the screen, for some reason the boot up process chokes if you use the -s option for read and I don’t know how else to hide the typed in text…

I used the following command, as root through a SSH connection to set this one up:

vim /usr/local/sbin/data-crypt-script.sh

Then copy/paste the script and do:

chmod a+x /usr/local/sbin/data-crypt-script.sh

to set the executable bit.

Now, finally, the last thing to make this all come together, you need to rebuild your initrd image. type:

update-initramfs -u

and when it gets all done reboot, hopefully you’ll see your encrypted partitions open up with the keys on the USB stick and all will be right with the world. After the bootup the stick is unmounted and is safe to remove. I would like to point out that I am not going into details about how to remove the passphrase options as I think it may be a good idea to keep that option open in case the stick gets damaged or lost. If it were the only way you could unlock the encryption it would mean a total loss of all data on all of the encrypted drives.

Next I will post about syslogd on the network, the NTP server, and kerberos, and anything else that becomes pertinant between now and then….

Share and Enjoy:
  • StumbleUpon
  • Digg
  • Reddit
  • del.icio.us
  • Facebook
  • Mixx
  • Google

Post a Comment

Your email is never shared.