Debian Lenny + LUKS encrypted root + hidden USB keyfile (part 2)

Posted: November 23rd, 2010 | Author: | Filed under: computing | 2 Comments »

Please see the original post on this topic if you’re looking for a full setup. This post is an optional update.

Two recent hard drive failures have sharply reminded me about the need for comprehensive backups. When I built the current home server I included two eSATA-SATAII connectors so that I could later add my two 1TB WD MyBook external HDDs as local backup drives. Upon rebooting the server the first thing I found out was that the MyBooks do not support SMART monitoring through their internal eSATA bridge so I had to disable SMART monitoring on these drives in the server bios to keep it from whining about failures. The second thing I found is that plugging in these drives really pissed off my LUKS scripts due to the kernel reordering the drives. Fortunately this was a fairly easy fix by replacing the “/dev/sdaX” references to the drives with the drive UUIDs. I believe the UUID=”U-U-I-D” method is also now supported by the cryptsetup scripts but I chose to play it safe using the “/dev/disk/by-uuid/U-U-I-D” method instead.

I’ll assume that if you already have a working setup from the first post that I don’t need to explain how much of a pain in the ass it will be to recover your system if you muck any of this up.

The important changes are:

1) /etc/crypttab

sda2_crypt /dev/sda2 none luks,keyscript=/usr/local/sbin/unlock-usb-key.sh

now becomes:

sda2_crypt /dev/disk/by-uuid/uuid-goes-here none luks,keyscript=/usr/local/sbin/unlock-usb-key.sh

2) /etc/initramfs-tools/conf.d/cryptroot

CRYPTROOT=target=sda2_crypt,source=/dev/sda2

now becomes:

CRYPTROOT=target=sda2_crypt,source=/dev/disk/by-uuid/uuid-goes-here

3) Edit the cryptopts parameters of the kopts line in /boot/grub/menu.lst

# kopt=root=/dev/mapper/vg0-root ro cryptopts=target=sda2_crypt,source=/dev/sda2,lvm=vg0-root,keyscript=/keyscripts/unlock-usb-key.sh

now becomes:

# kopt=root=/dev/mapper/vg0-root ro cryptopts=target=sda2_crypt,source=/dev/disk/by-uuid/uuid-goes-here,lvm=vg0-root,keyscript=/keyscripts/unlock-usb-key.sh

4) Run “update-grub” and check that the new UUID was added to kernel selections.

5) Update your initramfs:

# update-initramfs -u -k 2.6.XX-X-amd64

Reboot.

I’m fairly certain that the original post could be re-written to use the usb key’s UUID for the keyscript and skip having to configure udev to create the /dev/usbkey device entry. If anyone has time to do so I’d be interested in seeing it.

Part 1: http://www.oxygenimpaired.com/debian-lenny-luks-encrypted-root-hidden-usb-keyfile

Updated version for Ubuntu/Grub2: http://www.oxygenimpaired.com/ubuntu-with-grub2-luks-encrypted-lvm-root-hidden-usb-keyfile


Network Shakeup – Cisco & Vonage VoIP

Posted: November 18th, 2010 | Author: | Filed under: computing | Tags: , | No Comments »

As a Vonage user of many years we’ve always had issues with call quality and heavy network usage. I’ve tried various QoS solutions including several linux firmwares for the WRT54G, a Hawking “auto qos” device and a Netgear managed switch. Last year I got fed up with hack solutions and invested in a Cisco 871-SEC-K9. At about $500 with the Advanced IP Services feature set it was the most cost effective router I found in the Cisco lineup with a solid set of QoS capabilities.

Unfortunately after it arrived I realized just how rusty I am with the Cisco CLI and the SDM gui available at the time was horrible so after getting the thing configured for routing duties it has sat neglected. Now some issues in the past week with our DSL line (Qwest has oversold capacity for our CO -- surprise) caused the voip quality to go to crap during some business calls so it’s become time to put this to bed.

First thing I need to mention is that getting up to speed on Cisco’s various approaches to QoS is a pain in the ass and I hope to purge this useless knowledge from my head with a few beers this weekend. I started by trying the easy route of setting “auto qos voip” on the external interface but it didn’t do a thing for call quality. Next I installed the updated CCP 2.3 gui tool, which is a vast improvement over SDM, but it still pains me to fire up Windows XP (under Virtualbox) to administer my router (really Cisco?? It’s already written in Java and you can’t make a *nix version? Sad). Unfortunately trying various configs with the CCP QoS wizard didn’t get me any closer.

My setup includes 3 Vonage voip lines running on two Moto VT1000v ATAs. The ATAs are set to static IPs and directly cabled to FE2 & 3 on the Cisco router running IOS C870-ADVIPSERVICESK9-M, Version 12.4(24)T1, RELEASE SOFTWARE (fc3).

Digging deeper into the ATA traffic with Wireshark I found:
a) the VT1000v ATA does not mark any packets with DSCP tags so using the Cisco “trust” options are out unless I want to run the ATA packets through another device for tagging before hitting the router

b) Vonage offers 3 call quality settings through their “Bandwidth Saver” feature. Each of these setting uses the following payload codec:
30kbps = G.729
50kbps = G.721
90kbps = G.711

c) the Vonage voip call Signaling (unit registration, call setup/teardown) happens between the ATA’s UDP port 5061 (sip-tls) and remote UDP port 10000 (ndmp)

d) the Vonage voip RTP call data happens between the ATA’s UDP ports 10050-10061 and various remote UDP ports (14K, 16K, etc)

After much trial and error it became clear that the CCP wizard’s configs weren’t working because they either rely on trusted DSCP markings (see item “a” above) or on NBAR, and the built-in NBAR protocol maps for the 871 don’t recognize any of the ports the ATAs are using as RTP or SIP traffic. I then setup shaping (not policing) using the CCP wizard and modified the CCP-Voice-1 class it created to add a custom port-map for UDP ports 10050-10061. This helped considerably. After more tinkering I found the most bulletproof solution has been to add an extended Access Rule under the CCP-Voice-1 class that matches all ip traffic originating from the IPs of my ATAs:

ip access-list extended VONAGE-ATAs
remark All IP Traffic from 192.168.0.5/192.168.0.6
remark CCP_ACL Category=256
remark Src Host 192.168.0.5
permit ip host 192.168.0.5 any
remark Src Host 192.168.0.6
permit ip host 192.168.0.6 any

This ACL approach is a little bit of a hack as it classifies ALL traffic coming out of the ATA as voice payload (including the sip-tls which is technically signaling) and puts it all into the Low Latency Queue for priority processing, but.. IT WORKS so I’m not going to be picky. So far I’ve stress tested this config by running 2 voip calls concurrently with youtube, ssh sessions, multiple bittorrent downloads and refreshing a dozen firefox tabs all at once while maintaining nearly perfect call quality. Note -- this isn’t scalable or foolproof for larger networks with untrusted users, and I’m sure some IOS gurus will have many better ways to do this, but I’m hoping this will save some other poor schmuck the hours of googling, cisco whitepapers and failed attempts that I enjoyed just to make sure I can be heard clearly when I order a pizza.

REFERENCES/CREDIT:
Another blog that made for some interesting reading on the Cisco/Vonage subject: http://blog.lemieuxnc.net/

CISCO QOS (in case you’re reallllly bored):
http://docwiki.cisco.com/wiki/Quality_of_Service_Networking
http://www.cisco.com/en/US/products/ps6558/products_ios_technology_home.html

Enjoy.


Tangling with Untangle

Posted: October 18th, 2010 | Author: | Filed under: computing | Tags: , | 8 Comments »

This is a work in progress as I build up an Untangle box for personal use. Using the Lite (open source) version 7.4 (EDIT 11.15.2010 -- now running 8.0.0) on a Xeon server with 4 physical interfaces.

DO NOT follow any of this verbatim. This is a jumble of notes for my personal use that I hope may help a few other folks trying for a similar setup.


Install from USB disk: http://wiki.untangle.com/index.php/Installing_Untangle_from_a_USB_Flash_Disk
Use manual partitioning to setup full disk encryption (sda2_crypt) with LVM for separate / and /home. ext2 /boot, xfs for root & home


Enable & lockdown ssh:
* edit /etc/ssh/sshd.conf with my preferred config
* mv /etc/ssh/sshd_not_to_be_run /etc/ssh/sshd_not_to_be_run.bak
* restart ssh

—-
Use the terminal from the gui to create root password and a non-root user
Lockdown ssh from root login and setup key login for non-root user (disable direct root login and restrict to specific user account using AllowUsers, also enable MaxStartups 10:30:60).

—-
Add USB key for LUKS
http://www.oxygenimpaired.com/debian-lenny-luks-encrypted-root-hidden-usb-keyfile

—-
Install GRUB password and backup menu.lst against future Untangle updates
Add grub boot option for verbose, non-splash boot and make default selection
# altoptions=(text boot) vga=791
update-grub
Add /boot/grub/menu.lst as a file override in the gui.

—-
/etc/default/bootlogd change BOOTLOGD_ENABLE=Yes

—-
Edit /etc/apt/sources.list to uncomment debian main. (re-comment and apt-get update when done installing)

Install xfsprogs
Install/configure smartmontools
Install mlocate
Install memtest86+
Install/configure lm-sensors & i2c-tools
http://www.oxygenimpaired.com/new-hardware-is-good-asus-xeon-server


Secure the Untangle kiosk (X does not belong on servers but Untangle depends on it.. oh well.)
Instructions for locking down physical access to the Untangle kiosk:

First, follow jdelagarza’s excellent post on setting up xscreensaver and test that it’s working:
http://forums.untangle.com/feedback/10146-screensaver-lock.html

Unfortunately this can still be easily defeated using ctrl+alt key combos to restart X.
Answer:
1) build a good xorg.conf (see example below) so Xserver uses /etc/X11/xorg.conf instead of falling back to /etc/X11/xorg-untangle-vesa.conf (which is useless to modify directly as it automatically overwritten by /home/kiosk/.bashrc)

2) add a ServerFlags section with the following options:
“DontZap” to disable ctrl+alt+bksp and ctrl+alt+del
“DontVTSwitch” to disable ctrl+alt+F[1-12] (especially want to disable F10 which also kills X)
“DontZoom” to disable using ctrl+alt+[+/-] to crash X

3) reboot/restart X
My current /etc/X11/xorg.conf

# xorg.conf (X.Org X Window System server configuration file)
#
# If you have edited this file but would like it to be automatically updated
# again, run the following command:
# sudo dpkg-reconfigure -phigh xserver-xorg
#

Section "ServerFlags"
Option "DontZap" "true"
Option "DontVTSwitch" "true"
Option "DontZoom" "true"
EndSection

Section "InputDevice"
Identifier "Generic Keyboard"
Driver "kbd"
Option "XkbRules" "xorg"
Option "XkbModel" "pc104"
Option "XkbLayout" "us"
EndSection

Section "InputDevice"
Identifier "Configured Mouse"
Driver "mouse"
EndSection

Section "Device"
Identifier "Configured Video Device"
Driver "vesa"
EndSection

Section "Monitor"
Identifier "Configured Monitor"
VertRefresh 60
EndSection

Section "Screen"
Identifier "Default Screen"
Monitor "Configured Monitor"
Device "Configured Video Device"
DefaultDepth 24
SubSection "Display"
Depth 24
Virtual 1024 768
Modes "1024x768"
EndSubSection
EndSection

You can verify which xorg.conf file the Xserver is using with this command:
# cat /var/log/Xorg.0.log | grep “Using config file”

See this forum post for comments: http://forums.untangle.com/hacks/19035-secure-kiosk-locking-down-xscreensaver.html


Reconfiguring packet filter to allow DHCP on other interfaces

Hmmm.. trying to research how to serve DHCP on interfaces other than the Internal and DMZ but still be able to use packet filter to block unwanted interfaces. The following post explains how we can config dnsmasq to serve on multiple interfaces but the only suggestion for configuring the packet filter is to turn off DHCP filtering for all interfaces, which leaves the External interface exposed:
http://forums.untangle.com/tip-day/7206-dhcp-multiple-networks.html

I didn’t like this, and after a bit of searching it appears I’m not alone:
http://forums.untangle.com/networking/16176-dummies-guide-enabling-dhcp-eth3-eth4-eth5-eth6.html
http://forums.untangle.com/networking/17766-network-config-assist-4-untangle-interfaces.html
http://forums.untangle.com/networking/15115-dhcp-only-eth4.html

So.. as a long time linux user it seemed only proper to crack open my Untagle box and do a bit of digging.

It appears that the following ruby script is responsible for doing most the work of translating the packet filter gui into actual iptables rules:

/var/lib/rails/untangle-net-alpaca/lib/os_library/debian/packet_filter_manager.rb

When you apply changes in the gui the script then rebuilds the iptables rules in this file:

/etc/untangle-net-alpaca/iptables-rules.d/400-firewall

By studying this file you can see that when you apply the built-in “Allow DHCP Requests from the internal interface.” rule it creates the following iptables rule:

iptables -t filter -I INPUT 1 -p udp -m mark --mark 2/2 -m multiport --destination-ports 67 -j RETURN

The “Allow DMZ..” rule does the same except that the “--mark 2/2” portion changes for each interface.

I then tried making an “Allow DHCP” rule of my own for my eth3 using the gui which creates this actual iptable rule:

iptables -t mangle -A firewall-rules -p udp -m multiport --destination-ports 67 -m mark --mark 8/8 -j RETURN

Now we’re onto something… I then checked the “Block all DHCP Requests to the local DHCP Server.” rule and found it creates:

iptables -t filter -A INPUT -p udp -m multiport --destination-port 67 -j DROP

Bingo! The difference is that all the user rules are created by appending rules to the end of “firewall-rules” rule set of the “mangle” table whereas the built-in set of Allow rules are inserting rules into the top of the input chain (INPUT 1) in the default “filter” table. In short this means that when creating custom user rules they’re getting added after the the built-in “Block all DHCP..” rule so the DHCP packets are being dropped before they ever get to the user created Allow rules (vs the built-in Allow rules that get inserted before the built-in “Block all DHCP..” rule).

I was able to test this by manually adding an iptable rule for my eth3 interface that uses the insert vs the append method and it was successful in allowing DHCP (but this would get overwritten by untangle in the next rule refresh):

iptables -t filter -I INPUT 1 -p udp -m mark --mark 8/8 -m multiport --destination-ports 67 -j RETURN

So.. now understanding the issue. The simplest solution I found was to just abandon the built-in rules and do it all through a couple user rules.

Steps:
1) Uncheck: “Block all DHCP Requests to the local DHCP Server.”, “Allow DHCP Requests from the DMZ interface.”, “Allow DHCP Requests from the internal interface.”

2) Create a user rule to accept on any of the interfaces you do want DCHP:
Action: Pass, Protocol: UDP, Destination Port: 67, Source Interface: Internal, eth3

3) Create a rule to Drop on all the interfaces:
Action: Drop, Protocol: UDP, Destination Port: 67, Source Interface: all (even the ones you checked in the previous Pass rule)

Make sure the Pass rule is ordered above the Drop rule. Assuming your DHCP is configured correctly you should now have DHCP access on any interfaces you have checked within the Pass rule.

——-
Mapping the Untangle Packet Filter rules.

The interfaces on this box are identified by Untangle as follows ( the “--mark #/#” is basically another identifier for the different interfaces within iptables):
eth0 = External (--mark 1/1)
eth1 = Internal (--mark 2/2 and --mark 258/258)
eth2 = DMZ (--mark 4/4)
eth3 = eth3 (--mark 8/8)
VPN (--mark 128/128)
All Interfaces (--mark 256/256)

First line = the built-in rule description listed in the Untangle gui.
Second/third lines = actual rule(s) created in /etc/untangle-net-alpaca/iptables-rules.d/400-firewall by checking the gui description.

MAPPING:

Allow DHCP Requests from the internal interface.
${IPTABLES} -t filter -I INPUT 1 -p udp -m mark --mark 2/2 -m multiport --destination-ports 67 -j RETURN

Allow DHCP Requests from the DMZ interface.
${IPTABLES} -t filter -I INPUT 1 -p udp -m mark --mark 4/4 -m multiport --destination-ports 67 -j RETURN

Block all DHCP Requests to the local DHCP Server.
${IPTABLES} -t filter -A INPUT -p udp -m multiport --destination-port 67 -j DROP

Prefer Local DHCP Traffic from non-internal interfaces.
${IPTABLES} -t mangle -A FORWARD -p udp -m multiport --destination-ports 67,68 -m physdev --physdev-is-bridged --physdev-out eth1 -j DROP
${IPTABLES} -t mangle -A FORWARD -p udp -m multiport --destination-ports 67,68 -m physdev --physdev-is-bridged --physdev-in eth1 -j DROP

Accept DHCP traffic to the local DHCP client.
${IPTABLES} -t filter -I INPUT 1 -p udp -m multiport --destination-ports 68 -j RETURN

Accept DNS traffic from the Internal and VPN interfaces to the local DNS Server.
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 53 -m mark --mark 258/258 -j RETURN
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 53 -m mark --mark 384/384 -j RETURN

Accept DNS traffic to the local DNS Server from all interfaces.
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 53 -m mark --mark 256/256 -j RETURN

Accept SNMP traffic from the Internal interface.
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 161 -m mark --mark 258/258 -j RETURN

Accept SNMP traffic from all interfaces.
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 161 -m mark --mark 256/256 -j RETURN

Block OpenVPN traffic from the internal interface.
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 1194 -m mark --mark 258/258 -j alpaca-pfi-drop

Accept OpenVPN traffic from all interfaces.
${IPTABLES} -t mangle -A firewall-rules -p udp -m multiport --destination-ports 1194 -m mark --mark 256/256 -j RETURN

Accept SSH traffic from all interfaces.
${IPTABLES} -t mangle -A firewall-rules -p tcp -m multiport --destination-ports 22 -m mark --mark 256/256 -j RETURN

Allow Ping on all interfaces.
${IPTABLES} -t mangle -A firewall-rules -p icmp -m mark --mark 256/256 -j RETURN

Block all local traffic.
(added to 700-nat-firewall)
${IPTABLES} -t mangle -A firewall-rules -j alpaca-pfi-drop

Accept incoming VPN traffic when running as a VPN client.
???

Route VPN traffic that would go through the Bridge.
???

—--
Samba + SWAT + GOsa setup:
# apt-get install samba=2:3.2.5-4lenny11 samba-common=2:3.2.5-4lenny11
# apt-get install swat smbfs samba-docs
Create separate Packet Filter rules to allow 135,139,445 TCP and 137,138 UDP from select interfaces
Setup via SWAT (localhost 901)

uncomment apt deb sources and add deb unstable
# apt-get install gosa (to install dependent packages)
# apt-get install -t unstable (to install newest gosa with fcgi bug fix)
# apt-get install gosa-schema gosa-plugin-ldapmanager gosa-plugin-samba smbldap-tools libnss-ldap libpam-ldap
# apt-get remove lighttpd (conflicts with apache2)

Use /usr/share/doc/gosa/slapd.conf-example/slapd.conf.gz for /etc/ldap/slapd.conf and customize
https://oss.gonicus.de/labs/gosa/wiki/DocumentationInstallingGOsa

pulling gosa off and using webmin instead.
# add webmin repo
deb http://download.webmin.com/download/repository sarge contrib

———
Other good references:
http://forums.untangle.com/hacks/16687-how-install-all-ut-7-3-ntop-phpsysinfo-imspector-squid-monit-rsyslog-sqstat.html

Untangle -- useful files:
/var/log/uvm/
/var/log/untangle-net-alpaca/
/etc/untangle-net-alpaca/

TODOs:
* Configure untangle modules
* Add LUKS disk encryption for second SATA drive and for external eSATA backup drives
* Setup filesharing via Samba
* OpenVPN
* Bootp
* Enable sadc in /etc/default/sysstat ?

*** This post is still under construction ***


Dendroctonus Ponderosae Suck

Posted: June 4th, 2010 | Author: | Filed under: altitute | Tags: | No Comments »

The Colorado high country.. great mountainbiking, legendary skiing and epic views of mountains covered with dead trees.

If you haven’t seen the devastation of the Mountain Pine Beetle then you can find plenty of examples here.

This first wave hit about a dozen trees on our property late last fall. Now that the snow has finally melted it’s time to get the infested trees over to the county sort/burn yard before the larva hatch and spread to new victims.

Note the “pitch tubes” that result from the beetle boring into the tree. If the tubes are long and clear/yellow colored then there’s a chance the tree may have repelled them with enough sap, but the only way to know for sure is to look under the bark. If you wait for the tree to “brown out” and look dead before taking it then the larva will already have hatched and spread to other trees.
pine beetle pitch tubes

Example of a pine beetle larva after skinning off some bark.
pine beetle larve 1

A more mature larva, nearly ready to bore out.
pine beetle larva 2

Cut, stripped and loaded. The beetle don’t live in the branches so it’s only necessary to burn the trunks.
pine beetle logs 1

Notice the blue staining in the wood due to a fungus that the beetles carry. It infects the tree and clogs up the ability for the tree to transport water. A one-two punch for the tree.
pine beetle logs with blue stain

We’ll see how this summer goes. I’m hopeful with enough watering and some treatments that we can hang on to our “high value” trees and big ponderosas.

More pine beetle resources:
http://en.wikipedia.org/wiki/Mountain_pine_beetle
http://www.ext.colostate.edu/pubs/insect/05528.html
http://csfs.colostate.edu/forest-management/common-forest-insects-diseases/mountain-pine-beetle/
http://www.biocontrols.com/secure/shop/item.asp?itemid=141


Debian Lenny + LUKS encrypted root + hidden USB keyfile

Posted: May 22nd, 2010 | Author: | Filed under: computing | Tags: , , | 16 Comments »

The setup:

* Recently built up a new 1U Xeon quad core to take over home server duties.

* Installed a fresh copy of Debian Lenny using a USB stick install and the debian-504-amd64-netinst.iso image.

* Setup and partitioned disks manually with the Debian installer:

/dev/sda1 as /boot
/dev/sda2 as encrypted LUKS partition sda2_crypt
sda2_crypt as an LVM physical volume (technically /dev/dm-0)
/dev/mapper/vg0-swap as swap
/dev/mapper/vg0-root as root

* Finished standard install, configured system basics and tested working LUKS setup using normal console password entry during boot.

* Converted system to Proxmox VE running proxmox-ve-2.6.24 kernel. (Shouldn’t be relevant to this how-to).

The Challenge:

All is working well, but since this will be a headless server sitting down in the utility room it’s going to be a PITA to have to physically enter the LUKS password at each reboot. I could setup a remote LUKS passphrase over ssh, but really I want the machine to be able to survive a reboot without my intervention to get it running. So, for my needs a USB key sounds like the ticket.

I found a few nice how-to’s via the Google, but I wanted a few tweaks so I ended up using a blend of the following:
* The passwordless disk encryption in Debian Etch how-to is an excellent guide and provided much of what I needed.
* The Unlocking a luks volume with a USB key how-to doesn’t work for encrypting root, but I liked the idea of hiding the key between the MBR and first partition of the USB stick (yes, I know, security through obscurity is bad.. blah, blah).
* I found a nice udev config in section 2.1 of this post.
* Found the solution of adding kopts parameters to grub from somewhere else I can’t seem to find again.

Getting it done:

This assumes you already have a working LUKS setup using console password entry.

Creating the key

1) Insert your usb stick and use dmesg to identify the device file. We’ll assume /dev/sdx.

2) Fill the entire usb stick with random data (this will erase all data on the usb stick). If you’re extra paranoid and have lots of spare time use /dev/random instead.

# dd if=/dev/urandom of=/dev/sdx bs=1

3) If you still want the usb stick to be usable for storing data you’ll need to recreate the partition table and filesystem. Use fdisk to create a new single partition and mark the partition as type “W95 FAT32” then use mkfs.vfat to format the new partition.

4) Extract 4096 bits of random data off the usb stick that will become the new keyfile from in between the MBR and the first partition.

# dd if=/dev/sdx of=/root/luks-secret.key bs=512 skip=4 count=8

5) Add the key to your LUKS encrypted partition in key slot 1 (your current LUKS password should already be in slot 0). You’ll be prompted for you current password when running this.

# cryptsetup luksAddKey /dev/sda2 /root/luks-secret.key --key-slot 1

Your usb stick is now ready to go.

6) If you don’t want to keep a backup copy of this key on your filesystem then use shred.

# shred --remove --zero /root/luks-secret.key

Creating a udev rule

This will make your specific usb stick available at /dev/usbkey when inserted. Other usb sticks will be ignored even if they contained the same keyfile.

1) Run the following command to get the necessary information about the usb stick.

# udevadm info -a -p $(udevadm info -q path -n /dev/sdx)

2) In the output, look for the section that contains SUBSYSTEMS==”usb”, DRIVERS==”usb”, ATTR{manufacturer}, ATTR{product} and ATTR{serial}. Use this information for creating the rule in the next step.

3) Create a file in “/etc/udev/rules.d/99-unlock-luks.rules” that contains the following (all on one line):

SUBSYSTEMS=="usb", DRIVERS=="usb", ATTRS{manufacturer}=="XYZ Corporation", ATTRS{product}=="Flash Thingy", ATTRS{serial}=="0123456789abc", SYMLINK+="usbkey%n"

4) Reload udev rules with:

# udevadm control --reload-rules

5 ) Test that /dev/usbkey is created when the usb stick is inserted.

Create the keyscript

This will be the shell script responsible for reading the keyfile from the usb stick and passing it via cat to cryptsetup when called upon during boot. If the keyfile is not available or valid then it will revert to asking for your normal LUKS password on the console. The nice part about this keyscript is that by reading the keyfile directly using dd we get to skip worrying about drivers for mounting the usb stick’s filesystem.

1) Create a keyscript containing the following as “/usr/local/sbin/unlock-usb-key.sh”


#!/bin/sh
TRUE=0
FALSE=1

# flag tracking key-file availability
OPENED=$FALSE

# check and modprobe the USB driver if not already loaded
cat /proc/modules | busybox grep usb_storage >/dev/null 2>&1
USBLOAD=0$?
if [ $USBLOAD -gt 0 ]; then
modprobe usb_storage >/dev/null 2>&1
fi

# give the system time to settle and open the USB device
sleep 10

# check for the specifc /dev/usbkey device created by udev using /etc/udev/rules.d/99-unlock-luks.rules
if [ -b /dev/usbkey ]; then
# if device exists then output the keyfile from the usb key (hidden key is 4096 bytes long starting at 2048 bytes)
dd if=/dev/usbkey bs=512 skip=4 count=8 | cat
OPENED=$TRUE
fi

if [ $OPENED -ne $TRUE ]; then
echo "FAILED to get USB key file ..." >&2
/lib/cryptsetup/askpass "Try LUKS password: "
else
echo "Success loading key file. Moving on." >&2
fi

sleep 2

2) Make the script executable:

# chmod a+x /usr/local/sbin/unlock-usb-key.sh

Configure cryptsetup & initramfs-tools

1) Install initramfs-tools package.

2) Add the keyscript parameter to /etc/crypttab

sda2_crypt /dev/sda2 none luks,keyscript=/usr/local/sbin/unlock-usb-key.sh

3) Add the following modules to /etc/initramfs-tools/modules

sha256
aes-x86_64 (or aes-i586 if running 32-bit)
aes_generic
crypto_api
dm-crypt
dm-mod
scsi_dh
usbcore
usbhid
usb_storage

4) Add the following to /etc/initramfs-tools/conf.d/cryptroot

CRYPTROOT=target=sda2_crypt,source=/dev/sda2

5) Ensure “MODULES=most” and “BUSYBOX=y” are set in /etc/initramfs-tools/initramfs.conf

Update grub config & initrd images

Now we need to build a new boot initrd.img that contains the scripts and modules we configured above.
1) First, create a “safe” backup copy of your current initrd image.


# cd /boot

Copy your current initrd version.
# cp initrd.img-2.6.XX-X-amd64 initrd.img-2.6.XX-X-amd64-safe

2) Edit /boot/grub/menu.lst and create a duplicate of your current boot option that utilizes the “safe” initrd.img.


title Debian GNU/Linux, kernel 2.6.XX-X-amd64
root (hd0,0)
kernel /vmlinuz-2.6.XX-X-amd64 root=/dev/mapper/vg0-root ro
initrd /initrd.img-2.6.XX-X-amd64

title Debian GNU/Linux, kernel 2.6.XX-X-amd64-safe
root (hd0,0)
kernel /vmlinuz-2.6.XX-X-amd64 root=/dev/mapper/vg0-root ro
initrd /initrd.img-2.6.XX-X-amd64-safe

3) For some reason I still haven’t figured out (and haven’t spent much time further researching), I needed to add the “cryptopts” to my kernel boot options to make everything work. Otherwise, instead of the init scripts mounting root, I would get errors similar to “LVM driver is detected but LVM is not configured” during boot.
Again, edit /boot/grub/menu.lst and add the “cryptopts” parameters to your current kopts line.

# kopt=root=/dev/mapper/vg0-root ro cryptopts=target=sda2_crypt,source=/dev/sda2,lvm=vg0-root,keyscript=/keyscripts/unlock-usb-key.sh

4) Run “update-grub”. This will update all your boot kernels and the kopts line from the previous step will ensure it’s added to new kernels as well.


title Debian GNU/Linux, kernel 2.6.XX-X-amd64
root (hd0,0)
kernel /vmlinuz-2.6.XX-X-amd64 root=/dev/mapper/vg0-root ro cryptopts=target=sda2_crypt,source=/dev/sda2,lvm=vg0-root,keyscript=/keyscripts/unlock-usb-key.sh
initrd /initrd.img-2.6.XX-X-amd64

5) Now that you have a backup “safe” initrd.img, it’s time to update your current one to include the scripts and modules configured in the previous steps so that they are available at boot. Thanks to the initramfs-tools package, this is as simple as:

# update-initramfs -u -k 2.6.XX-X-amd64

6) If you want to verify that everything has copied correctly, you can unpack your current initrd.img to the tmp directory and look through the extracted files. The keyscript should have been copied into the “keyscripts” folder.

# cd /tmp
# zcat /boot/initrd.img-2.6.XX-X-amd64 | cpio -iv
# ls -al keyscripts/

Testing

1) Reboot with the usb stick installed and select the boot option that uses the new initrd.img you created. The system should boot all the way to the login prompt.
2) Reboot without the usb stick and it should stop at the prompt for your LUKS password.
3) If you run into issues you can reboot with your “safe” kernel.

Advantages

In my opinion there are a couple advantages to this setup:
1) The udev script approach makes it a tiny bit more difficult for someone to use an alternate usb stick even if they had the keyfile.
2) The dd method of “hiding” the keyfile in random deadspace means that even if someone got their hands on your usb stick they wouldn’t know they had a keyfile.

Why?

So.. what’s the point to encrypting if you’re just going to leave the key sitting in the machine? For me, the drive encryption isn’t about protecting against the NSA or uber-l33t hackers. I just want to ensure if the hardware gets ripped off during a break-in that the data is secure. My home setup will allow me to physically secure the usb key nearby and run a usb extension cable from the key to the server. I’ll take my chances that the average criminal would just unplug any cables when taking the machine and regardless, it would be extremely difficult to physically get to the secured usb stick even if they knew to look for it. Of course if you value security over the convenience of unattended reboots then just pull usb stick when not in use.

Enjoy.

Update 10/14/2010 -- corrected several typos.
Update 11/24/2010 -- added part 2: http://www.oxygenimpaired.com/debian-lenny-luks-encrypted-root-hidden-usb-keyfile-part-2
Update 01/02/2011 -- Updated version for Ubuntu/Grub2: http://www.oxygenimpaired.com/ubuntu-with-grub2-luks-encrypted-lvm-root-hidden-usb-keyfile


New hardware is good.

Posted: May 20th, 2010 | Author: | Filed under: computing | Tags: , , , | 1 Comment »

The time has come for a new machine to take over duties as the home server. Instead of stuffing together the normal patchwork of old workstations I’ve decided to pick up some proper hardware that can reliably support a few concurrent virtual machines running on Proxmox VE.

A few combo deals on Newegg later…
* 1x ASUS RS100-E5/PI2 1U Barebone Server (P5BV-M/RS100-E5 mobo)
* 1 x Intel Xeon X3220 Kentsfield 2.4GHz LGA 775 Quad-Core (SLACT, G0 stepping)
* 4 x Kingston ValueRAM 2GB 240-Pin DDR2 SDRAM DDR2 800 (PC2 6400) ECC
* 2 x Western Digital Caviar Black WD1001FALS 1TB 7200 RPM SATA 3.0Gb/s 3.5″ Internal HDDs
* 1 x Intel EXPI9402PT 10/100/1000Mbps PCI-Express PRO/1000 PT Dual Port Server Adapter
* 1 x Nippon Labs eSATA Bracket Two SATA II internal cable to 2 port ESATA bracket for SATA I and SATA II Hard Drive Model ESATAB-2P

That leaves me with 4-cores, 8G of ECC memory, 2 TBs of storage and 4 Gigabit NICs for a little over a grand. Hardware commoditization is a Good Thing™.

Assembly begins:
ASUS RS100-E5/PI2 barebones

 

1 beer. Everything fits easily. Note the 90 degree PCI riser will allow you to install a 16x PCI-e card but the riser only provides an 8x connection to the MB.
ASUS RS100-E5/PI2 partial build

 

2 beers. A little mod to remove the Sata2/eSata cables from their stock bracket and install them neatly with a little cutting to the slim-cd cover plate on the front of the server.
ASUS RS100-E5/PI2 built

Hardware is done and initial testing goes smoothly. BIOS was already up to date for me.

Grabbed a fresh copy of Debian Lenny and installed via USB stick with the debian-504-amd64-netinst.iso image.

lm-sensors 3.1.2 shows me running a steady 57-60°C at idle which seems high to me, but checking the Intel specs it appears normal for the G0 stepping version of this chip. On the plus side, the G0 is actually a 95W thermal design instead of the 105W advertised on Newegg. Under load it climbs well into the 60’s but the fans spin up a little and keep it holding steady within range.

So far I’m impressed. This thing has some nice features for the price point:
* The MB provides 4 SATAII ports, so using the Nippon Sata/eSata connectors I can toss on an additional 2 external mounted drives as long as they have their own power supply.
* Easily expandable for KVM/IPMI with purchase of a module
* The serial console supports remote management so you can skip IPMI if you choose
* 4 (2 front/2 rear) USB connections and legacy PS/2 ports
* Onboard GPU for VGA display
* Quiet for a 1U rack mount. Not silent, but certainly not distracting. Volume picks up with the fans under heavy load, but nothing unexpected.

A few quirks:
* The slim-cd/dvd connector looks like an old style molex. I haven’t bothered to look for a drive.
* Doesn’t include rails and it’s a bit heavy for mounting just by the ears

Following a short burn-in with Debian I converted the system Proxmox VE running the proxmox-ve-2.6.24 kernel. I started with proxmox-ve-2.6.18 but couldn’t get lm-sensors to work due to the outdated “w83627ehf” module. So far everything is running smooth with a mix of a few KVM VMs and OpenVZ appliances. (Edit 10/15/2010 -- I’ve since reformatted this machine to to a bare metal Untangle box as I was able to accomplish everything I’ve needed by hacking up the Untangle/Debian distribution without the overhead of virtualization).

lspci output for the curious:


00:00.0 Host bridge: Intel Corporation 3200/3210 Chipset DRAM Controller (rev 01)
00:01.0 PCI bridge: Intel Corporation 3200/3210 Chipset Host-Primary PCI Express Bridge (rev 01)
00:1c.0 PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 1 (rev 01)
00:1c.4 PCI bridge: Intel Corporation 82801GR/GH/GHM (ICH7 Family) PCI Express Port 5 (rev 01)
00:1c.5 PCI bridge: Intel Corporation 82801GR/GH/GHM (ICH7 Family) PCI Express Port 6 (rev 01)
00:1d.0 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #1 (rev 01)
00:1d.1 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #2 (rev 01)
00:1d.2 USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #3 (rev 01)
00:1d.7 USB Controller: Intel Corporation 82801G (ICH7 Family) USB2 EHCI Controller (rev 01)
00:1e.0 PCI bridge: Intel Corporation 82801 PCI Bridge (rev e1)
00:1f.0 ISA bridge: Intel Corporation 82801GB/GR (ICH7 Family) LPC Interface Bridge (rev 01)
00:1f.1 IDE interface: Intel Corporation 82801G (ICH7 Family) IDE Controller (rev 01)
00:1f.2 SATA controller: Intel Corporation 82801GR/GH (ICH7 Family) SATA AHCI Controller (rev 01)
00:1f.3 SMBus: Intel Corporation 82801G (ICH7 Family) SMBus Controller (rev 01)
01:03.0 VGA compatible controller: XGI Technology Inc. (eXtreme Graphics Innovation) Volari Z7
02:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5721 Gigabit Ethernet PCI Express (rev 21)
03:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5721 Gigabit Ethernet PCI Express (rev 21)
05:00.0 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet Controller (rev 06)
05:00.1 Ethernet controller: Intel Corporation 82571EB Gigabit Ethernet Controller (rev 06)

My homemade /etc/sensors3.conf file for lm-sensors. Lots of guesswork in here. I welcome suggestions or validation from someone more versed on lm-sensors.

# Winbond W83627EHF configuration
# This is for an Asus P5BV-M mobo.
# w83627dhg-isa-0290

chip "w83627ehf-*" "w83627dhg-*"

label in0 "VCore"
label in1 "+12V"
label in2 "AVCC"
label in3 "3VCC"
label in6 "+5V"
label in7 "VSB"
label in8 "VBAT"

# +12V is in1 and +5V is in6 as recommended by datasheet
compute in1 @*(1+(56/10)), @/(1+(56/10))
compute in6 @*(1+(22/10)), @/(1+(22/10))
set in1_min 12.0*0.9
set in1_max 12.0*1.1
set in6_min 5.0*0.8
set in6_max 5.0*1.2

# Set others
set in4_min 1.75*0.95
set in4_max 1.75*1.05
set in5_min 1.4*0.9
set in5_max 1.4*1.1

# Set the 3.3V
set in2_min 3.3*0.95
set in2_max 3.3*1.05
set in3_min 3.3*0.95
set in3_max 3.3*1.05
set in7_min 3.3*0.95
set in7_max 3.3*1.05
set in8_min 3.1*0.95
set in8_max 3.1*1.05

# Fans
label fan1 "Case Fan"
label fan2 "CPU Fan"
label fan3 "Aux Fan"
set fan2_min 3020
ignore fan1
ignore fan3
ignore fan4
ignore fan5

# Temperatures
label temp1 "Sys Temp"
label temp2 "CPU Temp"
label temp3 "AUX Temp"
set temp1_max 95
set temp1_max_hyst 80
set temp2_max 80
set temp2_max_hyst 75
ignore temp3


post 0

Posted: May 18th, 2010 | Author: | Filed under: other | No Comments »

In the beginning.