#!/bin/blog

January 18, 2009

Managing encrypted logical volumes

Filed under: Security, UNIX & Linux — Tags: , , — martin @ 1:32 pm

Worked on this with G. the other day.

Create the underlying logical volume:
lvcreate -n datalv_crypted -L 1G vg00

Initialize a LUKS crypto device on the logical volume:
cryptsetup luksFormat /dev/vg00/datalv_crypted

If you have lost your mind and want to keep the passphrase in a file (which is what G.’s weirdo client had asked for):
dd if=/dev/urandom of=/etc/i_am_dumb count=256
cryptsetup luksFormat /dev/vg00/datalv_crypted /etc/i_am_dumb

Bring up the crypto device from the encrypted logical volume:
cryptsetup luksOpen /dev/vg00/datalv_crypted data # optionally -d /etc/i_am_dumb

Create a file system on the crypto device, /dev/mapper/data, which has now sprung to life:
mkfs.ext3 /dev/mapper/data

Enter the crypto device in /etc/fstab:
/dev/mapper/data /data ext3 defaults 0 0

Don’t forget to create the mount point:
mkdir /data

Enter the encrypted logical volume in /etc/crypttab. Substitute “none” with /etc/i_am_dumb if you are keeping the passphrase on the system.
data /dev/vg00/datalv_crypted none luks

Reboot. You will be prompted for the passphrase on bootup, unless you’re keeping it in a file. The new file system will be mounted on /data.

The usual process for resizing file systems now has to be extended by an additional step:

lvresize -L +1G /dev/vg00/datalv_crypted
cryptsetup resize /dev/mapper/data
resize2fs /dev/mapper/data

That’s all there is to it. In another installment, I will hopefully write about encrypted physical volumes, allowing live migration of an entire volume group to encrypted storage during full operation. 🙂

With the technical details out of the way, some additional words about keeping the passphrase on-disk:

If you work for someone who wants this, he’s not neccessarily an idiot, but maybe just a bit naive. It is your duty as the expert to explain why keeping the passphrase in-band with the encrypted data is nothing more than just a waste of CPU cycles. Seriously. This, G., means you. 😉

Advertisements

December 31, 2008

Using the SSH agent from daemon processes

Filed under: UNIX & Linux — Tags: , , , — martin @ 1:04 am

One of my more recent installations, the BackupPC server I wrote about earlier, needs full access as the user root to his clients in order to retrieve the backups. Here’s how I implemented authentication on this machine.

BackupPC runs as its own designated user, backuppc. All authentication procedures therefore happen in the context of this user.

The key component in ssh-agent operation is a Unix domain socket that the ssh client uses to communicate with the agent. The default naming scheme for this socket is /tmp/ssh-XXXXXXXXXX/agent.<ppid>. The name of the socket is stored in the environment variable SSH_AUTH_SOCK. The windowing environments on our local workstations usually run as child processes of ssh-agent. They inherit this environment variable from their parent process (the agent) and therefore the shells running inside our Xterms know how to communicate with it.

In the case of a background server using the agent, however, things are happening in parallel: On one hand, we have the daemon which is being started on bootup. On the other hand, we have the user which the daemon is running as, who needs to interactively add his SSH identity to the agent. Therefore, the concept of an automatically generated socket path is not applicable and it would be preferable to harmonize everything to a common path, such as ~/.ssh/agent.socket.

Fortunately, all components in the SSH authentication system allow for this kind of harmonization.

The option -a to the SSH agent allows us to set the path for the UNIX domain socket. This is what this small script, /usr/local/bin/ssh-agent-wrapper.sh does on my backup server:

#!/bin/bash
SOCKET=~/.ssh/agent.socket
ENV=~/.ssh/agent.env
ssh-agent -a $SOCKET > $ENV

When being started in stand-alone mode (without a child process that it should control), ssh-agent outputs some information that can be sourced from other scripts:

SSH_AUTH_SOCK=/var/lib/backuppc/.ssh/agent.socket; export SSH_AUTH_SOCK;
SSH_AGENT_PID=1234; export SSH_AGENT_PID;
echo Agent pid 1234;

This file may sourced from the daemon user’s ~/.bash_profile:

test -s .ssh/agent.env && . .ssh/agent.env

However, this creates a condition where we can’t bootstrap the whole process for the first time. So it might be somewhat cleaner to just set SSH_AUTH_SOCK to a fixed value:

export SSH_AUTH_SOCK=~/.ssh/agent.socket

Here’s the workflow for initializing the SSH agent for my backuppc user after bootup:

root@foo:~ # su - backuppc
backuppc@foo:~ $ ssh-agent-wrapper.sh
backuppc@foo:~ $ ssh-add

In the meantime, what is happening to the backuppc daemon?

In /etc/init.d/backuppc, I have added the following line somewhere near the top of the script:

export SSH_AUTH_SOCK=~backuppc/.ssh/agent.socket

This means that immediately after boot-up, the daemon will be unable to log on to other systems, as long as ssh-agent has not been initialized using ssh-agent-wrapper.sh. After starting ssh-agent and adding the identity, the daemon will be able to authenticate. This also means that tasks in the daemon that do not rely on SSH access (in the case of BackupPC, things like housekeeping and smbclient backups of “Windows” systems) will already be in full operation.

December 16, 2008

More BackupPC sizing considerations

Filed under: UNIX & Linux — Tags: , — martin @ 7:12 am

After the ALIX had failed, I moved my BackupPC instance to a leftover Dell workstation with 1.7 GHZ Pentium 4 and 768 GB MB of RAM.

While this is somewhat usable, the machine is badly overloaded. When multiple backup tasks are running, all RAM plus 1 GB of swap space are fully used. And the USB 2.0 disk used for storage causes the system to be waiting for I/O 70-90% of the time. On the other hand, I should probably stop the manual scheduling of backup jobs and let BackupPC do it on its own.

Nevertheless, it can be said that retrieving, compressing and indexing files surely appears to be a lot more work than just serving them. 🙂

December 14, 2008

ALIX sizing lesson and WPA configuration note

Filed under: UNIX & Linux — Tags: , , , — martin @ 1:17 pm

Okay, there we have it. The ALIX, despite its generally good performance, can’t handle the workload of BackupPC and starts to swap really badly when backing up a fairly large system via rsync.

At least I’ve learned from this test how to configure the Wistron CM9 card for WPA on Debian:

iface ath0 inet static
        madwifi-base wifi0
        madwifi-mode sta
        wpa-driver wext
        wpa-ssid blah
        wpa-psk blubb
        address 192.168.1.100
        netmask 255.255.255.0
        network 192.168.1.0
        broadcast 192.168.1.255
        gateway 192.168.1.1

December 4, 2008

Using a USB key for the LUKS passphrase

Filed under: Paranoia, UNIX & Linux — Tags: , , — martin @ 10:43 pm

When I had installed my notebook with Ubuntu 8.04 “Horny Hard-on”, I had opted to put the /home filesystem onto an encrypted partition on /dev/sda4. However, after a few months, entering the passphrase after turning on the computer doesn’t seem to be that attractive anymore. I have therefore decided to try to store the passphrase on a spare USB key.

This is how I migrated my LUKS container to a passphrase stored on USB media.

First, I filled the USB key with random data:
# dd if=/dev/urandom of=/dev/sdc

Then, I siphoned off 256 bytes from the USB key, to be used as the passphrase:
# dd if=/dev/sdc of=/home/martin/foo.key bs=1 count=256

foo.key is required temporarily. You may keep a copy of it stored in a safe place, or you may leave the interactive password in place as a fall-back measure. Which is what I’m doing.

The new passphrase can be added to the LUKS container like this:
# cryptsetup luksAddKey /dev/sda4 /home/martin/foo.key

Cryptsetup asks for “any passphrase”. That is one of the numerous possible passphrases that may be assigned to a LUKS device at once. Such as the interactive passphrase that is already in place.

When the new passphrase has been added, foo.key can be deleted.

Next, I determined the USB id of my USB key:
# ls -l /dev/disk/by-id/ | grep sdc
lrwxrwxrwx 1 root root 9 2008-12-04 21:31 usb-LG_XTICK_AAAAAAAAAAAAAAAAA-0:0 -> ../../sdc

I found that I needed a little helper script that extracts 256 bytes from the USB key and pipes them to stdout:

#!/bin/bash
# Script: /usr/local/sbin/dd-luks-key.sh
if [ -e $1 ]
then
dd if=$1 bs=1 count=256
fi

And now the change to /etc/crypttab:

# Old entry; ask for password:
#sda4_crypt /dev/disk/by-uuid/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee none luks
# New entry; execute the keyscript with the USB id as the argument:
sda4_crypt /dev/disk/by-uuid/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee /dev/disk/by-id/usb-LG_XTICK_AAAAAAAAAAAAAAAAA-0\:0 luks,keyscript=/usr/local/sbin/dd-luks-key.sh

That’s it. I can now reboot with the USB key plugged in and observe how the system automatically mounts the LUKS container. The USB key is not partitioned, so Gnome will not automatically mount it. It can just be pulled anytime after bootup.

If I had chosen to delete the interactive passphrase, which is stored in key slot 0:
# cryptsetup luksDelKey /dev/sda4 0

Be advised that this is no real-deal tough-minded security, but something that will protect the machine only against the type of attackers (e.g. thieves) who are out for your hardware but not for your data. Don’t leave the USB key close to the laptop. Use this responsibly. Thanks!

I’m not conviced that I will stick with this, as it’s far below my usual standard of paranoia. Nevertheless, I have gained a few nice insights into the LUKS system.

October 31, 2008

Bring on the goodies!

Filed under: UNIX & Linux — Tags: , , , — martin @ 8:49 pm

Ubuntu 8.10 – At last. 😉
OpenBSD 4.4 – Early. 🙂

OpenBSD 4.4 finally has support for my Huawei E220 UMTS/G3 modem (a.k.a. “T-Mobile Web & Walk Box Micro”) in the default installation. Granted, that’s at least one year late. Nevertheless, I have already used the E220 with an OpenBSD snapshot release, several months ago. The really good thing is that the OpenBSD implementation of the Huawei E220 serial interface runs circles around the shady E220 hack that is still required to get the thing up and running on Linux. 🙂

October 20, 2008

OpenSSH: Going flexible with forced commands

Filed under: Security, UNIX & Linux — Tags: , — martin @ 9:32 am

As we all know, it is possible to use SSH not only for obtaining an interactive login session on a remote machine, but also for executing commands remotely. For instance, the following command will log on to myserver.example.com, execute “uname -a” and return to the local shell:

ssh myserver.example.com uname -a

(The local SSH client returns the exit code from the remote command, if you’re into this kind of detail.)

You might have some users (or scheduled automatisms) that you don’t want to be able to log on to that machine at all, but who should be permitted to execute only a given command. In order to achieve this, you can configure key-based authentication. Once this has been done, the key can be prefixed with a number of configuration options. Using one of these options, it is possible to enforce execution of a given command when this key is used for authentication.

In this example from ~/.ssh/authorized_keys, the user wants to look at the process list, so we set the command to “ps -ef”.

command="/bin/ps -ef"

Using this, when the user tries to log in, or tries to execute an arbitrary command, “/bin/ps -ef” is executed instead and the SSH session terminates.

In addition to enforcing a command, it is advisable to disable a number of advanced SSH features, such as TCP and X11 forwarding. Assignment of a pseudo terminal to the user’s SSH session may also be suppressed, by adding a number of additional configuration options next to the forced command:

no-port-forwarding,no-X11-forwarding,no-pty

Here’s what a full entry from ~/.ssh/authorized_keys might look like:

command="/bin/ps -ef",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAp0KMipajKK468mfihpZHqmrMk8w+PmzTnJrZUFYZZNmLkRk+icn+m71DdEHmza2cSf9WdiK7TGibGjZTE/Ez0IEhYRj5RM3dKkfYqitKTKlxVhXNda7az6VqAJ/jtaBXAMTjHeD82xlFoghLZOMkScTdWmu47FyVkv/IM1GjgX/I8s4307ds1M+sICyDUmgxUQyNF3UnAduPn1m8ux3V8/xAqPF+bRuFlB0fbiAEsSu4+AkvfX7ggriBONBR6eFexOvRTBWtriHsCybvd6tOpJHN8JYZLxCRYHOGX+sY+YGE4iIePKVf2H54kS5UlpC/fnWgaHbmu/XsGYjYrAFnVw== Test key

This is quite nice: We have successfully limited this user to requesting a process list.

This is called an SSH forced command.

So much for the introduction. 😀

Here’s what I’m really getting at today – What, if we want the user to not only execute a single command, but a number of commands, such as:

– Show process list (ps)
– Show virtual memory statistics (vmstat)
– Stop and start the print server (/etc/init.d/cupsys stop/start)

Following the approach described above, this would give us four key pairs, four entries in ~/.ssh/authorized_keys, and four entirely different invocations of SSH on the client side, each of them using a dedicated private key. In other words: An administrative nightmare.

This is where the environment variable $SSH_ORIGINAL_COMMAND comes in. (This nice facility was pointed out to me last week by G., who had read about it somewhere but wondered what it might be useful for.)

Until now, all we know is that with a forced command in place, the SSH server ignores the command requested by the user. This is not entirely true, though. The SSH server does in fact remember the command that was requested, stores it in $SSH_ORIGINAL_COMMAND and thus makes it available within the environment of the forced command.

With this in mind, it is possible to allow more flexibility inside forced commands, without the need to go crazy with countless key pairs. Instead, it is possible to just create a wrapper script that is called as the forced command from within ~/.ssh/authorized_keys and decides what to do, based on the content of $SSH_ORIGINAL_COMMAND:

#!/bin/sh
# Script: /usr/local/bin/wrapper.sh 

case "$SSH_ORIGINAL_COMMAND" in
	"ps")
		ps -ef
		;;
	"vmstat")
		vmstat 1 100
		;;
	"cups stop")
		/etc/init.d/cupsys stop
		;;
	"cups start")
		/etc/init.d/cupsys start
		;;
	*)
		echo "Sorry. Only these commands are available to you:"
		echo "ps, vmstat, cupsys stop, cupsys start"
		exit 1
		;;
esac

It is important to be aware of potential security issues here, such as the user escaping to a shell prompt from within one of the listed commands. Setting the “no-pty” option already makes this kind of attack somewhat difficult. In addition, some programs, such as “top”, for example, have special options to run them in a “secure” read-only mode. It is advisable to closely examine all programs that are called as SSH forced commands for well-meant “backdoors” and to find out about securing them.

It’s up to you to decide based on your own situation, whether you want to run this wrapper as the root user or if you prefer to use password-less “sudo” commands to raise privileges where needed.

If you encounter problems while debugging $SSH_ORIGINAL_COMMAND, please make absolutely sure that you are authenticating with the correct key. I found it helpful to unset SSH_AUTH_SOCK in the window where I do my testing, in order to prevent intervention from identies stored in the SSH agent.

October 10, 2008

Untote Exploits

Filed under: Security, UNIX & Linux — Tags: , , , — martin @ 5:55 am

Jahrelang habe ich auf dem K. herumgehackt, weil “sein” IPS immer Verbindungen unterbrochen hat, nachdem es Bytefolgen auf der Leitung gesehen hatte, mit denen man vor etlichen Jahren mal irgendwelche archaischen Exploits (konkret erlebtes Beispiel: Sendmail decode vulnerability) triggern konnte. Denn mal ehrlich: Wie obskur kann’s noch werden?

Heute bin ich in gewisser Weise einen Schritt weiter, denn bei einem Kunden wurde ein SLES9 aus dem Internet gecrackt, weil der Angreifer sich über einen PHP-Exploit die /etc/passwd herunterladen konnte und darin Passwort-Hashes vorgefunden hat, die ein Administrator beim Anlegen von Usern per Copy&Paste dort eingebaut hat. Die hat er dann auf dem üblichen Weg mit etwas Geduld per Brute-Force geknackt. Ein Szenario aus den 1980ern. Ekelhaft.

October 6, 2008

New ALIX 2d3

Filed under: Hardware, UNIX & Linux — Tags: , , , — martin @ 6:44 pm

I received my first new ALIX of the type 2d3 today. Apparently, this is the successor to the 2c3 and brings no major changes but just minor modifications. According to PC Engines:

• Increase USB current limit.
• USB headers as build option.
• USB ports 3 and 4 on header (not tested).
• Change optional serial header J12 to COM2.
• Add LED and switch pins to I2C header.
• Populate buzzer driver circuit, add pins for use as GPIO.
• Add option for power in header J18.
• Some enhancements to reduce EMI.
• Add second POSCAP to ruggedize 3.3V rail for high power radio cards.

I have highlighted the most apparent changes in the photograph (click to enlarge).

Migration of the pre-installed disk from my development ALIX 2c3 went fine, although I had to resolve a problem with some nasty mis-feature where Debian tries to keep persistent ethernet device names by hard-coding the MAC addresses into some obscure udev configuration file. The system complained about the following network issue, although eth0, eth1 and eth2 showed up properly in the output of dmesg:

Configuring network interfaces…SIOCSIFADDR: No such device
eth0: ERROR while getting interface flags: No such device

Deleting the /etc/udev/rules.d/z25_persistent-net.rules file and rebooting resolved the problem immediately.

I never could quite get the hang of devfs or udev anyway. Here’s yet another reason to hate them. 😀

October 4, 2008

Playing with the ALIX LEDs

Filed under: UNIX & Linux — Tags: , , — martin @ 7:24 am

I have started to use an ALIX machine by PC-Engines as my printserver using CUPS. Being the playful kid that I am, I wanted the machine to somehow indicate that it has queued print jobs, using the LEDs.

Controlling the LEDs is fairly simple. I started on OpenBSD, found a very simple method for controlling them through gpioctl right away and quickly rolled it into this very simple shell script that allows for commands such as “led 1 on” or “led 3 off”, you get the idea.

I found that OpenBSD didn’t work too well for me as a CUPS printserver for multiple USB printers. The helpful OpenBSD mailing lists were down on that weekend, so I just decided to install Debian Linux onto the ALIX.

The Linux Kernels currently in circulation don’t however support the ALIX LEDs. Support is available, though. I downloaded the kernel module source from here (leds-alix_0.0.1.orig.tar.gz) and after compiling them and loading the leds_alix module, my shell script was ready to be extended into a “multiplatform” LED control wrapper.

(The LED drivers on Linux allow for a lot more fun, such as a “heartbeat” feature or acting as an “IDE” LED, but that’s not my point here. 🙂 )

On top of my little shell wrapper, I have now implemented a Perl script, the “CUPS LEDs daemon”, cupsledsd, which starts cycling the LEDs when there are pending jobs and uses the wrapper for turning them on and off. Of course, this could easily be used for something more sophisticated, such as displaying the number of queued jobs.

Update, 2008-10-07: I found that the original cupsledsd, as posted above, was a bit too hard on the CPU, using 5-10% for just blinking. Here’s a Linux-only cupsledsd that uses no system() calls. It accesses the CUPS queue directly (searches for data files in /var/spool/cups, probably unsupported), writes directly to the Linux /sys filesystem and blinks more frantically while not using a significant amount of CPU.

« Newer PostsOlder Posts »

Create a free website or blog at WordPress.com.