Debian IPsec Micro‐Howto

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

Updated for Debian 4.0 (etch) on 2008‑05‑17. The old text using Debian 3.1 (sarge) 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.

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’re always PSKs.

Well, enough ranting.

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 was and is multi‐platform in contrast to ISAKMPd which comes directly from OpenBSD. The IPsec‐Tools packages are called “racoon” and “ipsec-tools”.

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, choose “direct”.

The startup init scripts

The default racoon package is not configured to nicely shut down on system reboot or shutdown, so we need to add some links:

# 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/rc1.d/K89racoon
   /etc/rcS.d/S40racoon
# update-rc.d racoon start 40 S . stop 89 1 . start 34 0 6 .
 Adding system startup for /etc/init.d/racoon ...
   /etc/rc1.d/K89racoon -> ../init.d/racoon
   /etc/rc0.d/S34racoon -> ../init.d/racoon
   /etc/rc6.d/S34racoon -> ../init.d/racoon
   /etc/rcS.d/S40racoon -> ../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/sh -e
### BEGIN INIT INFO
# Provides:          ipsecfix
# Required-Start:    networking
# Should-Start:      racoon isakmpd vpn ipsec ike
# Default-Start:     S
# Description:       Force IPsec SAs to exist in advance
# Short-Description: Initialize IPsec networking
### END INIT INFO
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/xorg.conf ]; then
  echo "Now pinging all X font servers:"
  awk '/^[^#]/&&$1=="FontPath"&&$2~/"tcp\//{
      sub(/.*\//, "", $2);
      sub(/:.*/, "", $2);
      print $2 }' /etc/X11/xorg.conf \
    | xfping
fi

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

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

Configuration files

The configuration is split into two separate files, with some duplicated information across them. This is due to the design of IPsec; it is separated into a kernel part and a daemon part, each of which is configured separately.

First, the X.509 certificate and key files. 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, these commands (you will need the openssl package installed during this):

# cd /etc/racoon/certs
# ln -s ca-cert.pem `openssl x509 -noout -subject_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.

Now, the first of the two actual configuration files, the /etc/ipsec-tools.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.

#!/usr/sbin/setkey -f

# These lines are for IPv6 Neighbor solicitation and advertisement,
# the IPv6 equivalent of the older non-IP ARP protocol.  This should
# never be encrypted.
# I am unsure if this is really needed, but it can't really hurt.
spdadd ::/0 ::/0 icmp6 135,0 -P out none;
spdadd ::/0 ::/0 icmp6 135,0 -P in none;
spdadd ::/0 ::/0 icmp6 136,0 -P out none;
spdadd ::/0 ::/0 icmp6 136,0 -P in none;

##
# guest.example.org
spdadd 333.333.333.333 444.444.444.444 any -P out ipsec esp/transport//require;
spdadd 444.444.444.444 333.333.333.333 any -P in ipsec esp/transport//require;
##

I’ve put it off long enough, so here it is, the /etc/racoon/racoon.conf file. The file will have some default settings at the top and a commented‐out example. Keep those and add the following at the end.

##
# Guest
remote 444.444.444.444 {
        exchange_mode main;
        certificate_type x509 "host-cert.pem" "host-key.pem";
        my_identifier fqdn "host.example.org";
        verify_identifier on;
        peers_identifier fqdn "guest.example.org";
        proposal {
                encryption_algorithm 3des;
                hash_algorithm sha1;
                authentication_method rsasig;
                dh_group modp1024;
        }
}
sainfo address 333.333.333.333 any address 444.444.444.444 any {
        pfs_group modp1024;
        encryption_algorithm aes,3des;
        authentication_algorithm hmac_sha1,hmac_md5;
        compression_algorithm deflate;
}
# Extra sainfo for port 500 needed, taken from
# <http://bugs.debian.org/341398#msg69>
sainfo address 333.333.333.333[500] any address 444.444.444.444[500] any {
        pfs_group modp1024;
        encryption_algorithm aes,3des;
        authentication_algorithm hmac_sha1,hmac_md5;
        compression_algorithm deflate;
}
# See also:
#<http://lists.freebsd.org/pipermail/freebsd-net/2004-March/003514.html>
##

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 those section (the ones enclosed by ##’es) in both files for all hosts you want to communicate securely with.

Pre‐Shared Keys

Delete “certificate_type”, “my_identifier”, and “verify_identifier” to use the default values which use PSKs. Change “peers_identifier” to be set to “address” (and only the string “address”) on each remote section. Change “authentication_method” to be set to “pre_shared_key”. Edit /etc/racoon/psk.txt to contain the keys for each hosts (which obviously must be different, for security). The format is similar to 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.