IPsec site-to-site tunnel

From SaruWiki
Jump to navigation Jump to search

IPsec tunneling theory

IPsec is very powerful, but also quite complicated and intricate. When starting on tunneling, you might want to start exploring the site ipsec-howto. It explains both the theory of IPsec, and describes how to create IPsec tunnels. However, after reviewing the theory, you might want to continue here for a more elaborate, Debian-specific, site-to-site only, howto on tunneling.

IPsec site-to-site tunneling

IPsec general preparations

First off, you'll have to inventory your prospective tunnel setup. We suggest you fill in the following table (filled here for the purpose of example):

Debian Server Data Example
Name(*) dworkin
Internet IP
Private IP
Default key exchange encryption 3DES
Default tunnel encryption 3DES

(*) This data is not mandatory, but it makes it easier to reference the machine in question.

Next, you'll need to decide if you are going to use the debian-specific tool racoon-tool, or if you're going to configure racoon directly. If you don't know what the difference is, choosing will be quite hard. So here follows a little description of the tools, and what we see as the consequences of your choice.

  • racoon is a daemon that can exchange keys with the other end of a prospective IPsec connection in a secure and automated way; it is part of the IPsec-tools package. You are supposed to configure it by means of entering exactly the right data in /etc/racoon/racoon.conf. Using racoon directly is the "standard" way of setting up an IPsec tunnel
  • racoon-tool is a Debian-specific Perl script, that can perform your racoon configuration for you. Using this means that you're less likely to make typo's etcetera: it's plain easier. On the other hand, since this is Debian-specific, a lot of information on the Internet might get less usable for you, since that assumes you're using plain racoon. This shortcoming is mitigated somewhat by the realization that racoon-tool generates a racoon.conf file just as you'd expect, but only in a different location (/var/lib/racoon/racoon.conf instead of /etc/racoon/racoon.conf). But then again, you might want to learn how to make IPsec tunnels in a way that can be used on non-Debian servers as well...

We feel there is no compelling general reason to choose one way over the other, so we'll outline both ways here. You'll have to choose, though. Mind you, if you ever change your mind, you can easily switch from direct to racoon-tool or back by running dpkg-reconfigure racoon...

Next, you'll have to verify if your kernel has been compiled with the necessary options. What you need at minimum are the following kernel options, that can be found under Networking support > Networking options:

  • Transformation user configuration interface: this enables support for the Transformation (XFRM) user configuration interface; IPsec needs this.
  • PF_KEY Sockets: This option makes your kernel compatible with the KAME IPsec tools that we're going to use.
  • IP: ESP transformation: This option ensures we can create IPsec networking packets in ESP mode.
  • IP: IPsec tunnel mode: This option enables the IPsec tunnel mode.
  • IP: IPComp transformation: Not required, but you'll want this: it enables compression over your IPsec tunnels

For IPsec you need several cryptographic algorithms; the mandatory ones are already selected because you set the options above. But if you need or want additional ones (AES, Blowfish etc), then go to Cryptographic API, and select the algorithms you want. We would suggest the following algorithms:

  • Null algorithms: useful for testing
  • SHA224 and SHA256 digest algorithm: pretty secure and pretty well supported
  • Blowfish cipher algorithm: fast and efficient
  • AES cipher algorithms: AES is a well-known standard, that is still considered pretty secure

If you have any other cryptographic need, then most likely you'll have to satisfy it here as well. Then, after the usual compiling and installing of your new or updated kernel, you'll of course have to reboot to be able to use these features.

Verify that your Linux server is not sitting behind a NATting device, like an ADSL modem/router. If it is, you'll need an extra feature (NAT-T, or Nat Traversal), not described in this procedure.

IPsec installation

The amount of software we need to realize an IPsec tunnel is limited, because most of the IPsec capabilities are now integrated in the Linux kernel. The packages we need are:

  • ipsec-tools, the package that contains the KAME IPsec tools with which we can control the IPsec implementation that's in the Linux kernel;
  • racoon, the Internet Key Exchange daemon;
  • vim(*), an improved version of the vi editor.

(*)Well we don't really need vim, but if we install it, not only will we have a very powerful editor, but also will we be able to use the xxd command when generating strong encryption keys.

When using aptitude or apt-get install to install racoon, we'll be asked for the desired "Configuration mode for racoon IKE daemon": direct or racoon-tool. Choose according to your preference.

That's it! No additional software is required. Your system is now ready to set up IPsec tunnels - all it requires is the right configuration (and a correctly configured endpoint for the other end of the tunnel).

IPsec site-to-site tunnel configuration

IPsec tunnel-specific preparations

When we start creating a tunnel, we need the relevant data for the far side of each tunnel we'll be creating, similar to what we've already gathered for our own side of the tunnel. Note that it is not necessary that the other endpoint is also a Linux server; it could just as well be an IPsec capable appliance like a Checkpoint FW1 firewall or a Microsoft Windows server. The main difference between different endpoints is the set of encryption algorithms they'll be able to support. Therefor, the preferred encryption algorithm must be negotiated between you and your counterpart on the other side of the tunnel. In this example, the other side is a Debian server as well, and we've agreed to use SHA1 as algorithm for both the IKE phase and the actual tunnel. Furthermore, we've agreed on a secret key, needed for the initial IKE phase.

Debian Server Data Example
Name(*) darktower
Internet IP
Private IP
Preferred key exchange encryption SHA1
PreShared Key 0x383a94619b3d6a8f33a39f68b4d16594
Preferred tunnel encryption SHA1

So how do we generate a strong PSK? A quick way would be to execute this command:

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

This will output a strong key, like 383a94619b3d6a8f33a39f68b4d16594; you'll only have to prepend 0x to signify that it's a hexadecimal key. Note that if you do not prepend 0x, it will mean that the key will be interpreted as a passphrase instead of a key. No harm there, as long as you do this on both sides of the tunnel.

We must put this key in a key file. To this end, we append the file /etc/racoon/psk.txt with the following information:

# key for tunnel to darktower    0x383a94619b3d6a8f33a39f68b4d16594

Note: there is already sample information in this file; it is good practice to comment this out. Furthermore, make sure this file is ONLY readable for root (sudo chmod 600). Finally, remember that the other side of the tunnel needs the EXACT same key - transport it there using a very secure method (like going there in person). If your key gets compromised on the way there, your tunnel is not secure!

Now with the data for the tunnel available and the key set up, we can get going on the configuration of the tunnel itself. If you've selected using racoon-tool, read on. If you've chosen direct (or if you're not on a Debian server but another Linux distribution), skip to the next section.

Method 1: using racoon-tool

Method 2: direct racoon configuration

To configure racoon directly, we're going to edit /etc/racoon/racoon.conf. If this is the first tunnel you're going to create: good practice is to rename the original racoon.conf to racoon.conf.org, and create a fresh one. The basic file then looks like this:

# Racoon configuration file

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

# logging level: notify or debug
log notify; 

listen {
        isakmp [500];
        isakmp_natt [4500];

This sets some default options for our Racoon daemon. The lines speak almost for themselves: the path plus filename for the PreShared Keys, the path to the certificates directory, the loglevel (error, warning, notify, info, debug or debug2), and on which IP addresses and ports should the daemon listen - an in which mode. Normally, you'd only have an isakmp entry, followed by the public IP address, and the default IKE port (TCP 500). If you want to accomodate other servers behind NAT routers as tunnel endpoints, then you'd need that second entry - it'll make Racoon smart enough to negotiate the IKE phase even though there's a NAT router in between.

Now the tunnel-specific stanza's. There are two, and they could look something like this:

# Connection odeonlan
remote 500 {
        proposal {
                encryption_algorithm 3des;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group modp1024;

        verify_identifier on;
        peers_identifier address;
        exchange_mode main;

sainfo address[any] any address[any] any {
        pfs_group modp1024;
        encryption_algorithm aes,3des;
        authentication_algorithm hmac_sha1,hmac_md5;
        compression_algorithm deflate;

The first stanza describes the parameters with which the IKE phase 1 communication will take place. It says in this example: for the endpoint, negotiate IKE over port 500 (since that is the default port number, you could omit the 500). Start the IKE phase 1 negotiations with the following parameters: encrypt communication during IKE with 3des, use sha1 as hashing method, use the PSK file to verify that the other side is really who they claim to be, and use a 1024-bits Diffie-Hellman group. To find out what these parameters mean, we kindly refer you to execute command man racoon.conf, and of course to Internet.
The last three statements in the first stanza have the following meaning:

  • if we want to, we can try to verify if the other side is who we believe it to be. This statement verify_identifier on turns on this identity check.
  • to now find out who the other side claims to be, we can look at several identifiers. Here we claim that we want to verify the IP address of the other side of the tunnel. This ensures the tunnel is not set up between our end and some unknown other server.
  • the keys must be exchanged between the endpoints in main mode, which requires multiple messages going back and forth, but which ensures that the other side is indeed who they claim to be. This only works if the IP number of the other side is known in advance, as is the case with a server with a fixed internet IP address. This will NOT work if the other side of the tunnel is a roaming client - but since we're using the IP address already as identifier, this is not the case in this example.

The second stanza defines the parameters of the IKE phase 2 (IPsec-SA establishment). It decribes a "security association": the encryption policy or policies for traffic passing through the tunnel. The first line of the stanza gives a description of the traffic that this policy is valid for. Here the traffic description reads "If you see packets entering the tunnel, coming from any port on in any protocol, and going to any port on in any protocol, then that traffic must be encrypted using the parameters specified between the curly brackets. You could use multiple sainfo stanza's to tunnel multiple types of traffic through the same tunnel.

After specifying the tunnel in racoon.conf we need to restart the Racoon daemon so that it knows about our tunnel:

sudo invoke-rc.d racoon restart

Furthermore, we want to ensure that Racoon starts when we reboot our server, so we create a symlink in our runlevel directory:

ln -s /etc/init.d/racoon /etc/rc2.d/S98racoon

Now we've told the kernel how to encrypt traffic going through the tunnel; however, we haven't yet told the kernel what traffic to put through which tunnel. For this, we need a Security Policy (SP), which is stored in the Security Policy Database (SPD). So how do we create and such an SP? We use the utility setkey.
Under Debian, we can simply edit /etc/ipsec-tools.conf, and call upon /etc/init.d/setkey to execute it, e.g. at startup. To this end, we create ipsec-tools.conf like this:

#!/usr/sbin/setkey -f

## Flush the SAD and SPD

# Tunnel to Darktower
spdadd any -P out ipsec

spdadd any -P in ipsec

In this, we make sure that any call on setkey results in flushing the SA and SP databases. Then we add the two policies that encrypt and decrypt traffic entering and leaving the tunnel. The first line adds to the SPD a policy for outgoing traffic (-P out) to be encrypted (ipsec) if that traffic comes from, goes to, and is made up of any protocol (any). You could limit the use of the tunnel to any protocol that is in the /etc/protocol file, and/or between different address ranges, and/or particular ports. For example:

spdadd[9080] http -P out ipsec

This policy encrypts all HTTP traffic going to port 9080 on the web server

OK, now that we've created the setkey information, we can have our Debian server create our SPD for us:

invoke-rc.d setkey

Furthermore, if we want our SPD to be created automatically on startup, we can create the appropriate symlink:

ln -s /etc/init.d/setkey /etc/rc2.d/S98setkey

Extra configuration issues

Maybe after all that complicated configuration work on setkey and racoon you thought you had a working tunnel? Well you have indeed, but that does not necessarily mean you can also use it. Two issues might need to be tackled, before your tunnel actually works.

setting the right routes

We might have told the kernel how to encapsulate and encrypt traffic from our network to the other one, and vice versa, but probably no traffic will by itself go that way. That is because we haven't added the route from our network to the other side to the routing table. So this is something we now have to do. When we want to reach the remote network (here:, we need to send it to our public IP interface, and make sure that our routing engine uses our server's private IP as the router source address. This way, we can reach the remote network not only from our local network, but also from our router itself. A means to enter this route would be to execute this command:

ip route add via src

To make sure that this route is available on startup of your server, make it persistent.

adapting your firewall configuration

It's nice to have a tunnel that carries traffic; it's nice to have a firewall filtering your network traffic; it's not so nice if your firewall is blocking the traffic that is supposed to go over your tunnel.

It depends on which firewall you use, but you should make sure there are rules in place that allow the outgoing traffic that you want to enter, and incoming traffic that you want to allow to leave the tunnel. A piece of IPtables firewall scripting could look like this:

# define all necessary variables
LocalLAN[1]=''    # the LAN segment we're prepared to open
PublicIP[1]=''   # Our own external IP for this connection
RemoteLAN[1]=''   # the remote LAN segment we wanna reach
RemoteIP[1]=''      # the public IP of the remote gateway

# open IKE port between us and them, in and out
iptables -A INPUT -p udp -s ${RemoteIP[1]} --sport 500 --dport 500 -j ACCEPT
iptables -A OUTPUT -p udp -d ${RemoteIP[1]} --sport 500 --dport 500 -j ACCEPT

# Pass network traffic through the NAT tables
iptables -t nat -A PREROUTING -s ${RemoteLAN[1]} -d ${LocalLAN[1]} -j ACCEPT
iptables -t nat -A POSTROUTING -s ${LocalLAN[1]} -d ${RemoteLAN[1]} -j ACCEPT

# Pass network traffic over the tunnel through the filter tables
iptables -A FORWARD -s ${RemoteLAN[1]} -d ${LocalLAN[1]} -j ACCEPT
iptables -A FORWARD -s ${LocalLAN[1]} -d ${RemoteLAN[1]} -j ACCEPT

And of course, if you want to use Netfilter to filter out additional traffic inside of the tunnel, you can make rules for that as well, instead of those last two lines.

A note of caution: if you use your Linux server as a NAT router itself, and/or if you have other reasons to have DNAT and SNAT rules in your firewall, make sure that the PREROUTING and POSTROUTING lines shown above appear BEFORE those DNAT and SNAT lines. If not, then your tunnel packages get NATted before the IPsec policy kicks in, and your kernel will not recognise them as packages that need to be tunneled.

IPsec diagnostics

When creating tunnels, everything has to be just perfect, or the tunnel won't work at all. However, rarely ever does one get everything perfect at the first go. Thus, when creating tunnels, you heavily depend on the right diagnostic skills and tools. We've described these in a separate page: the IPsec tunneling diagnostics page.