Chapter 24. IPsec

Table of Contents
24.1. Theory
24.2. Kernel configuration
24.3. Installing IPsec-Tools
24.4. Setting up IPsec with manual keying
24.5. Setting up IPsec with automatic key exchanging

24.1. Theory

IPsec is a standard for securing IP communication through authentication, and encryption. Besides that it can compress packets, reducing traffic. The following protocols are part of the IPsec standard:

There are actually two modes of operation: transport mode is used to encrypt normal connections between two hosts, tunnel mode encapsulates the original package in a new header. In this chapter we are going to look at the transport mode, because the primary goal of this chapter is to show how to set up a secure connection between two hosts.

There are also two major methods of authentication. You can use manual keys, or an Internet Key Exchange (IKE) daemon, like racoon, that automatically exchanges keys securely betwoon two hosts. In both cases you need to set up a policy in the Security Policy Database (SPD). This database is used by the kernel to decide what kind of security policy is needed to communicate with another host. If you use manual keying you also have to set up Security Association Database (SAD) entries, which specifies what encryption algorithmn and key should be used for secure communication with another host. If you use an IKE daemon the security associations are automatically established.

24.2. Kernel configuration

Native IPsec support is only available in Linux 2.6.x kernels. Earlier kernels have no native IPsec support. So, make sure that you have a 2.6.x kernel. The 2.6 kernel is available in Slackware Linux 10.0, 10.1, and 10.2 from the testing directory on CD2 of the Slackware Linux CD sets, or any of the official Slackware Linux mirrors. The default Slackware Linux 2.6 kernel has support for AH, ESP and IPcomp in for both IPv4 and IPv6. If you are compiling a custom kernel enable use at least the following options in your kernel configuration:


CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
    

Or you can compile support for IPsec protocols as a module:


CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
    

In this chapter we are only going to use AH and ESP transformations, but it is not a bad idea to enable IPComp transformation for further configuration of IPsec.

When you choose to compile IPsec support as a module, make sure that the required modules are loaded. For example, if you are going to use ESP for IPv4 connections, load the esp4 module.

Compile the kernel as usual and boot it.

24.3. Installing IPsec-Tools

The next step is to install the IPsec-Tools. These tools are ports of the KAME IPsec utilities. Download the latest sources and unpack, configure and install them:


# tar jxf ipsec-tools-x.y.z.tar.bz2
# cd ipsec-tools-x.y.z
# CFLAGS="-O2 -march=i486 -mcpu=i686" \
  ./configure --prefix=/usr \
              --sysconfdir=/etc \
              --localstatedir=/var \
              --enable-hybrid \
              --enable-natt \
              --enable-dpd \
              --enable-frag \
              i486-slackware-linux
# make
# make install
    

Replace x.y.z with the version of the downloaded sources. The most notable flags that we specify during the configuration of the sources are:

24.4. Setting up IPsec with manual keying

24.4.1. Introduction

We will use an example as the guideline for setting up an encrypted connection between to hosts. The hosts have the IP addresses 192.168.1.1 and 192.168.1.169. The "transport mode" of operation will be used with AH and ESP transformations and manual keys.

24.4.2. Writing the configuration file

The first step is to write a configuration file we will name /etc/setkey.conf. On the first host (192.168.1.1) the following /etc/setkey.conf configuration will be used:


#!/usr/sbin/setkey -f

# Flush the SAD and SPD
flush;
spdflush;

add 192.168.1.1 192.168.1.169 ah 0x200 -A hmac-md5 
0xa731649644c5dee92cbd9c2e7e188ee6;
add 192.168.1.169 192.168.1.1 ah 0x300 -A hmac-md5 
0x27f6d123d7077b361662fc6e451f65d8;

add 192.168.1.1 192.168.1.169 esp 0x201 -E 3des-cbc 
0x656c8523255ccc23a66c1917aa0cf30991fce83532a4b224;
add 192.168.1.169 192.168.1.1 esp 0x301 -E 3des-cbc
0xc966199f24d095f3990a320d749056401e82b26570320292

spdadd 192.168.1.1 192.168.1.169 any -P out ipsec
           esp/transport//require
           ah/transport//require;

spdadd 192.168.1.169 192.168.1.1 any -P in ipsec
           esp/transport//require
           ah/transport//require;
      

The first line (a line ends with a ";") adds a key for the header checksumming for packets coming from 192.168.1.1 going to 192.168.1.169. The second line does the same for packets coming from 192.168.1.169 to 192.168.1.1. The third and the fourth line define the keys for the data encryption the same way as the first two lines. Finally the "spadd" lines define two policies, namely packets going out from 192.168.1.1 to 192.168.1.169 should be (require) encoded (esp) and "signed" with the authorization header. The second policy is for incoming packets and it is the same as outgoing packages.

Please be aware that you should not use these keys, but your own secretly kept unique keys. You can generate keys using the /dev/random device:


# dd if=/dev/random count=16 bs=1 | xxd -ps
      

This command uses dd to output 16 bytes from /dev/random. Don't forget to add "0x" at the beginning of the line in the configuration files. You can use the 16 byte (128 bits) for the hmac-md5 algorithm that is used for AH. The 3des-cbc algorithm that is used for ESP in the example should be fed with a 24 byte (192 bits) key. These keys can be generated with:


# dd if=/dev/random count=24 bs=1 | xxd -ps
      

Make sure that the /etc/setkey.conf file can only be read by the root user. If normal users can read the keys IPsec provides no security at all. You can do this with:


# chmod 600 /etc/setkey.conf
      

The same /etc/setkey.conf can be created on the 192.168.1.169 host, with inverted -P in and -P out options. So, the /etc/setkey.conf will look like this:


#!/usr/sbin/setkey -f

# Flush the SAD and SPD
flush;
spdflush;

add 192.168.1.1 192.168.1.169 ah 0x200 -A hmac-md5
0xa731649644c5dee92cbd9c2e7e188ee6;
add 192.168.1.169 192.168.1.1 ah 0x300 -A hmac-md5
0x27f6d123d7077b361662fc6e451f65d8;

add 192.168.1.1 192.168.1.169 esp 0x201 -E 3des-cbc
0x656c8523255ccc23a66c1917aa0cf30991fce83532a4b224;
add 192.168.1.169 192.168.1.1 esp 0x301 -E 3des-cbc
0xc966199f24d095f3990a320d749056401e82b26570320292

spdadd 192.168.1.1 192.168.1.169 any -P in ipsec
           esp/transport//require
           ah/transport//require;

spdadd 192.168.1.169 192.168.1.1 any -P out ipsec
           esp/transport//require
           ah/transport//require;
      

24.4.3. Activating the IPsec configuration

The IPsec configuration can be activated with the setkey command:


# setkey -f /etc/setkey.conf
      

If you want to enable IPsec permanently you can add the following line to /etc/rc.d/rc.local on both hosts:


/usr/sbin/setkey -f /etc/setkey.conf
      

After configuring IPsec you can test the connection by running tcpdump and simultaneously pinging the other host. You can see if AH and ESP are actually used in the tcpdump output:


# tcpdump -i eth0
tcpdump: listening on eth0
11:29:58.869988 terrapin.taickim.net > 192.168.1.169: AH(spi=0x00000200,seq=0x40f): ESP(spi=0x00000201,seq=0x40f) (DF)
11:29:58.870786 192.168.1.169 > terrapin.taickim.net: AH(spi=0x00000300,seq=0x33d7): ESP(spi=0x00000301,seq=0x33d7)
      

24.5. Setting up IPsec with automatic key exchanging

24.5.1. Introduction

The subject of automatical key exchange is already touched shortly in the introduction of this chapter. Put simply, IPsec with IKE works in the following steps.

  1. Some process on the host wants to connect to another host. The kernel checks whether there is a security policy set up for the other host. If there already is a security association corresponding with the policy the connection can be made, and will be authenticated, encrypted and/or compressed as defined in the security association. If there is no security association, the kernel will request a user-land IKE daemon to set up the necessary security association(s).

  2. During the first phase of the key exchange the IKE daemon will try to verify the authenticity of the other host. This is usually done with a preshared key or certificate. If the authentication is successful a secure channel is set up between the two hosts, usually called a IKE security association, to continue the key exchange.

  3. During the second phase of the key exchange the security associations for communication with the other host are set up. This involves choosing the encryption algorithm to be used, and generating keys that are used for encryption of the communication.

  4. At this point the first step is repeated again, but since there are now security associations the communication can proceed.

The racoon IKE daemon is included with the KAME IPsec tools, the sections that follow explain how to set up racoon.

24.5.2. Using racoon with a preshared key

As usual the first step to set up IPsec is to define security policies. In contrast to the manual keying example you should not set up security associations, because racoon will make them for you. We will use the same host IPs as in the example above. The security policy rules look like this:


#!/usr/sbin/setkey -f

# Flush the SAD and SPD
flush;
spdflush;

spdadd 192.168.1.1 192.168.1.169 any -P out ipsec
        esp/transport//require;

spdadd 192.168.1.169 192.168.1.1 any -P in ipsec
        esp/transport//require;
      

Cautious souls have probably noticed that AH policies are missing in this example. In most situations this is no problem, ESP can provide authentication. But you should be aware that the authentication is more narrow; it does not protect information outside the ESP headers. But it is more efficient than encapsulating ESP packets in AH.

With the security policies set up you can configure racoon. Since the connection-specific information, like the authentication method is specified in the phase one configuration. We can use a general phase two configuration. It is also possible to make specific phase two settings for certain hosts. But generally speaking a general configuration will often suffice in simple setups. We will also add paths for the preshared key file, and certification directory. This is an example of /etc/racoon/racoon.conf with the paths and a general phase two policy set up:


path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/etc/racoon/certs";

sainfo anonymous {
{
        pfs_group 2;
        lifetime time 1 hour;
        encryption_algorithm 3des, blowfish 448, rijndael;
        authentication_algorithm hmac_sha1, hmac_md5;
        compression_algorithm deflate;
}
      

The sainfo identifier is used to make a block that specifies the settings for security associations. Instead of setting this for a specific host, the anonymous parameter is used to specify that these settings should be used for all hosts that do not have a specific configuration. The pfs_group specifies which group of Diffie-Hellman exponentiations should be used. The different groups provide different lengths of base prime numbers that are used for the authentication process. Group 2 provides a 1024 bit length if you would like to use a greater length, for increased security, you can use another group (like 14 for a 2048 bit length). The encryption_algorithm specifies which encryption algorithms this host is willing to use for ESP encryption. The authentication_algorithm specifies the algorithm to be used for ESP Authentication or AH. Finally, the compression_algorithm is used to specify which compression algorithm should be used when IPcomp is specified in an association.

The next step is to add a phase one configuration for the key exchange with the other host to the racoon configuration. For example:


remote 192.168.1.169 
{
        exchange_mode aggressive, main;
        my_identifier address;
        proposal {
                encryption_algorithm 3des;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group 2;
        }
}
      

The remote block specifies a phase one configuration. The exchange_mode is used to configure what exchange mode should be used for phase. You can specify more than one exchange mode, but the first method is used if this host is the initiator of the key exchange. The my_identifier option specifies what identifier should be sent to the remote host. If this option committed address is used, which sends the IP address as the identifier. The proposal block specifies parameter that will be proposed to the other host during phase one authentication. The encryption_algorithm, and dh_group are explained above. The hash_algorithm option is mandatory, and configures the hash algorithm that should be used. This can be md5, or sha1. The authentication_method is crucial for this configuration, as this parameter is used to specify that a preshared key should be used, with pre_shared_key.

With racoon set up there is one thing left to do, the preshared key has to be added to /etc/racoon/psk.txt. The syntax is very simple, each line contains a host IP address and a key. These parameters are separated with a tab. For example:


192.168.1.169     somekey
      

24.5.3. Activating the IPsec configuration

At this point the configuration of the security policies and racoon is complete, and you can start to test the configuration. It is a good idea to start racoon with the -F parameter. This will run racoon in the foreground, making it easier to catch error messages. To wrap it up:


# setkey -f /etc/setkey.conf
# racoon -F
      

Now that you have added the security policies to the security policy database, and started Racoon, you can test your IPsec configuration. For instance, you could ping the other host to start with. The first time you ping the other host, this will fail:


$ ping 192.168.1.169
connect: Resource temporarily unavailable
      

The reason for this is that the security associations still have to be set up. But the ICMP packet will trigger the key exchange. ping will trigger the key exchange. You can see whether the exchange was succesful or not by looking at the Racoon log messages in /var/log/messages, or the racoon output if you started racoon in the foreground. A succesful key exhange looks like this:


 Apr  4 17:14:58 terrapin racoon: INFO: IPsec-SA request for 192.168.1.169 queued due to no phase1 found.
 Apr  4 17:14:58 terrapin racoon: INFO: initiate new phase 1 negotiation: 192.168.1.1[500]<=>192.168.1.169[500] 
 Apr  4 17:14:58 terrapin racoon: INFO: begin Aggressive mode. 
 Apr  4 17:14:58 terrapin racoon: INFO: received Vendor ID: DPD 
 Apr  4 17:14:58 terrapin racoon: NOTIFY: couldn't find the proper pskey, try to get one by the peer's address.
 Apr  4 17:14:58 terrapin racoon: INFO: ISAKMP-SA established 192.168.1.1[500]-192.168.1.169[500] spi:58c4669f762abf10:60593eb9e3dd7406
 Apr  4 17:14:59 terrapin racoon: INFO: initiate new phase 2 negotiation: 192.168.1.1[0]<=>192.168.1.169[0] 
 Apr  4 17:14:59 terrapin racoon: INFO: IPsec-SA established: ESP/Transport 192.168.1.169->host1ip; spi=232781799(0xddff7e7) 
 Apr  4 17:14:59 terrapin racoon: INFO: IPsec-SA established: ESP/Transport 192.168.1.1->192.168.1.169 spi=93933800(0x59950e8) 
      

After the key exchange, you can verify that IPsec is set up correctly by analyzing the packets that go in and out with tcpdump. tcpdump is available in the n diskset. Suppose that the outgoing connection to the other host goes through the eth0 interface, you can analyze the packats that go though the eth0 interface with tcpdump -i eth0. If the outgoing packets are encrypted with ESP, you can see this in the tcpdump output. For example:


# tcpdump -i eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:27:50.241067 IP terrapin.taickim.net > 192.168.1.169: ESP(spi=0x059950e8,seq=0x9)
17:27:50.241221 IP 192.168.1.169 > terrapin.taickim.net: ESP(spi=0x0ddff7e7,seq=0x9)