Debian IPsec Micro‐Howto

This information is now out of date due to the release of Debian 4.0!

Updated for Debian 3.1 (sarge) on 2006‑05‑29. The old text using Debian 3.0 (woody) is still available.

So in a moment of weakness I promised I’d write a simple how‐to for setting up IPsec in Debian. That ought to be easy; I’ve set up two separate computer systems (that’s systems, with many computers in each system) each using IPsec extensively, I’ve used both FreeS/WAN and IPsec‐tools, by themselves and interoperating, and I’ve used both PSKs and X.509 certificates. Well, we’ll see.

Why Another Howto?

So what’s wrong with other howtos about how to setup IPsec? Well, they usually don’t cover Debian specifically, but that’s not my chief problem. The main thing which makes other IPsec texts unsuitable for me is that they all assume I’m using IPsec to do a VPN. Well, I’m not, I’m using it to get IP security for otherwise completely insecure thing like NIS and NFS. And once you’ve got it running you can enable things like FTP and even telnet, and you can then run X over the network like it was meant to be run and not inside some ugly SSH tunnel.

Well, enough ranting.

Authentication Methods

Another thing which put me off other texts about IPsec was that they all used PSKs in their examples and then, maybe, covered X.509 certificates at the end, and only as a list of things to do differently. This annoyed me because of course I was using real X.509 certificates signed by a CA (home‐made, but anyway), and didn’t want to be forced to learn how to set up IPsec into a configuration I wasn’t going to use in order to only then learn how to do what I really wanted to do. So here I’m going to assume that you have your certificates ready, all signed by specific CA which you will trust. How to do all that CA signing and stuff have, thankfully, been covered elsewhere, so I’m not going to. If you don’t want to deal with that, there’s always PSKs.

What Implementation?

Debian contains three main implementations of IPsec: Openswan, ISAKMPd, and IPsec‐tools (not counting FreeS/WAN, which is dead upstream.) For reasons outlined here I’ve decided to go with IPsec‐tools for the future. Basically, Openswan only supports tunnel mode and IPsec‐tools feels safer since it is originally multi‐platform in contrast to ISAKMPd which comes directly from OpenBSD. The IPsec‐tools packages are called “racoon” and “ipsec-tools”.

The kernel-image-2.6.8 packages (and older, up to and including 2.6.12, I believe) in Debian 3.1 (sarge) has a bug where it ignores PMTU discovery on IPsec links. This affects those who will run IPsec over a link with a lower MTU than at the network end points. To fix this, either lower the MTU of all hosts involved (ugly and inefficient) or use a newer version of Linux, preferably the linux-image-2.6 packages from backports.org. Their linux-image-2.6.16 package fixed the problem for me.

Anyway, on to the installation.

Installation

Simply install the racoon and ipsec-tools packages. When the question “Please select the configuration mode for racoon IKE daemon.” appears, answer “racoon-tool”.

The startup init scripts

The default for the racoon package is to be started rather late in the boot process, like it was some kind of VPN daemon and not an essential network component. I use IPsec to the NIS server, to the NFS server, and other things, so I need to change the startup order:

# update-rc.d -f racoon remove
update-rc.d: /etc/init.d/racoon exists during rc.d purge (continuing)
 Removing any system startup links for /etc/init.d/racoon ...
   /etc/rc0.d/K20racoon
   /etc/rc1.d/K20racoon
   /etc/rc2.d/S20racoon
   /etc/rc3.d/S20racoon
   /etc/rc4.d/S20racoon
   /etc/rc5.d/S20racoon
   /etc/rc6.d/K20racoon
# update-rc.d racoon start 43 S . start 34 0 6 .
 Adding system startup for /etc/init.d/racoon ...
   /etc/rc0.d/S34racoon -> ../init.d/racoon
   /etc/rc6.d/S34racoon -> ../init.d/racoon
   /etc/rcS.d/S43racoon -> ../init.d/racoon
# 

I have noticed that when using this setup, mounting network filesystems from an NFS server over an IPsec connection immediately after starting Racoon will fail (rather than simply be deferred until the IPsec SA is established as was the case with FreeS/WAN). I therefore recommend using the bg flag in /etc/fstab for NFS mounts, but this may also be a problem with other types of services than NFS. I’m not sure why this is, but we can fix it by pinging the NFS (and other) servers just after starting IPsec.

We do this with a new script, /etc/init.d/ipsecfix, which is inserted after racoon and before mountnfs.sh:

# cat > /etc/init.d/ipsecfix <<EOF
#!/bin/bash
echo -n "Pausing..."
sleep 3
echo -n "done.  "

required="sort awk"

if type fping >/dev/null; then
  xfping(){
    sort -u | fping -A -r1
  }
else
  xfping(){
    sort -u | xargs --no-run-if-empty --max-args=1 ping -q -c1 -n
  }
  required="$required xargs"
fi

for command in $required; do
  if type "$command" >/dev/null; then
    :
  else
    echo "$0: Could not find required command \"$command\"" >&2
    exit 1
  fi
done

# DNS
echo "Now pinging all DNS resolvers:"
awk '$1=="nameserver"{ print $2 }' /etc/resolv.conf \
    | xfping

# NFS
echo "Now pinging all NFS servers:"
awk '/^[^#]/&&$3=="nfs"{ sub(/:.*/, "", $1); print $1 }' /etc/fstab \
    | xfping

# NIS
echo "Now pinging all NIS servers:"
awk '/^[^#]/&&$1=="ypserver"{ print $2 }' /etc/yp.conf \
    | xfping

# X font
if [ -r /etc/X11/XF86Config-4 ]; then
  echo "Now pinging all X font servers:"
  awk '/^[^#]/&&$1=="FontPath"&&$2~/"tcp\//{
      sub(/.*\//, "", $2);
      sub(/:.*/, "", $2);
      print $2 }' /etc/X11/XF86Config-4 \
    | xfping
fi

echo -n "Pausing..."
sleep 3
echo "done.  "
EOF
# chmod 755 /etc/init.d/ipsecfix
# update-rc.d ipsecfix start 44 S .
 Adding system startup for /etc/init.d/ipsecfix ...
   /etc/rcS.d/S44ipsecfix -> ../init.d/ipsecfix
# 

Now we can safely start and stop racoon. But it won’t do anything without configuration.

Configuration files

I have used FreeS/WAN in the past, and its configuration was really flexible and powerful (if incomprehensible). So when I saw the racoon.conf file, I was disappointed. Well, in Debian our good friend the package maintainer has implemented a macro preprocessor for us in the form of “racoon-tool“, which reads its own configuration file “/etc/racoon/racoon-tool.conf”. It purports to imitate FreeS/WAN’s configuration features, and does so after a fashion even if some features are still missing. In any case it’s better than using racoon.conf directly.

Anyway, the configuration files. First, put your CA public cert, CRL, host key and certificate (all unencrypted and in PEM format) in /etc/racoon/certs/ as ca-cert.pem, crl.pem, host-key.pem, and host-cert.pem, respectively. Then run, as root:

# cd /etc/racoon/certs
# ln -s ca-cert.pem `openssl x509 -noout -hash -in ca-cert.pem`.0
# ln -s crl.pem `openssl crl -noout -hash -in crl.pem`.r0
# chmod go-rwx host-key.pem

That last command is just to make sure we didn’t do something stupid.

I’ve put it off long enough, so here it is, the racoon-tool.conf file. I’m assuming a host name of “host.example.org” with IP address 333.333.333.333 and an IPsec connection to another host named “guest.example.org” with IP address 444.444.444.444. The file will have some default settings at the top and lots of commented‐out examples. Keep those and add the following at the end.

peer(%default):
	certificate_type: x509 host-cert.pem host-key.pem
	my_identifier: fqdn host.example.org
	verify_identifier: on
	authentication_method[0]: rsasig
connection(%default):
	src_ip: 333.333.333.333

# Guest
peer(444.444.444.444):
	peers_identifier: fqdn guest.example.org
connection(guest):
	dst_ip: 444.444.444.444
	admin_status: enabled
#

With this configuration, we will no longer accept any non‐IPsec packets from guest.example.org, and will also send only IPsec packets to that host. Now that’s what I call real network security.

You then repeat that last section (the one enclosed by #’es) for all hosts you want to communicate securely with.

Please note that if you want to use asn1dn identifiers instead of fqdn you need to patch a bug in racoon-tool:

# patch --strip=0 <<EOF
--- /usr/sbin/racoon-tool.~1~	2005-05-04 10:33:32.000000000 +0200
+++ /usr/sbin/racoon-tool	2005-06-11 06:33:00.000000000 +0200
@@ -1328,7 +1328,7 @@

                 chomp;
 
-                if (! m/^[-\"{}()\[\]_;\%\@\w\s.:\/]+$/) {
+                if (! m/^[-\"{}()\[\]_;\%\@\w\s.:\/=]+$/) {
                         prog_warn 0, "bad data in $conffile, line $line:";
                         prog_warn 0, $_;
                         # $barf = 1;
@@ -1464,7 +1464,6 @@
 				$peer_list{$peer}{'syntax_error'} = 1;
 				next LINE;
 			}
-			$value = value_lc($section, $property, $value);
 		 	$peer_list{$peer}{$property} = $value; 
 		} elsif ( $section eq 'peer' ) {
                         prog_warn 0, "$peer - unrecognised tag in $conffile, line $line:";
EOF
patching file /usr/sbin/racoon-tool
# 

Pre‐Shared Keys

Delete “authentication_method[0]”, “certificate_type”, and “my_identifier” to use the default values which use PSKs. Change “peers_identifier” to be set to “address” (and only the string “address”) on each host section. Edit /etc/racoon/psk.txt to contain the keys for each hosts (which obviously must be different, for security). The format is like the /etc/hosts file, but the second field is the key, not a host name. Keys can be either a free‐form string or hexadecimal, starting with “0x”. Beware, there seems to be a limit of about 1022 characters or so per line.

This work is dedicated to the Public Domain.