Having to manage several servers on the Internet, I needed a way to create a secure internal network. Our servers are somewhere in the cloud and the solution that was adopted was to setup the GNU/Linux IPsec stack and an IP-IP tunnel between each server.
The following article describes how to setup the IPSec network and IP-IP tunnel. These steps were executed on 9 servers running Ubuntu 8.0.4 and one server running Ubuntu 10.0.4.
IPSec Configuration
We must install the following packages. The ipsec-tools
package provides the utilities to setup and configure the IPSec stack and the racoon
package provides the IKE server to manage the security associations.
$ sudo apt-get install ipsec-tools racoon tcpdump
Configure /etc/ipsec-tools.conf
The /etc/ipsec-tools.conf
configuration file must define the policy entries (SPD) that describe which traffic has to be encrypted. We must define one SPD for each direction (two SPDs for each tunnel).
On the 90.1.1.1
server and to setup the IPSec tunnel to 201.10.10.10
, the configuration looks like:
spdadd 90.1.1.1 201.10.10.10 any -P out ipsec
esp/transport//require
ah/transport//require;
spdadd 201.10.10.10 90.1.1.1 any -P in ipsec
esp/transport//require
ah/transport//require;
Configure Racoon
The Racoon configuration is defined in /etc/racoon/racoon.conf
. Racoon can use several authentication mechanisms to verify that an IPSec association can be created with a given peer. To make the configuration simple and identical on every server, I have used RSA certificate. RSA certificates are very easy to manage and they provide a really good authentication.
remote anonymous {
exchange_mode main,base;
lifetime time 12 hour ;
certificate_type plain_rsa "/etc/racoon/ipsec.key";
peers_certfile plain_rsa "/etc/racoon/ipsec.pub";
proposal {
encryption_algorithm 3des;
hash_algorithm sha256;
authentication_method rsasig;
dh_group modp1024;
}
generate_policy off;
}
sainfo anonymous {
pfs_group modp1024;
encryption_algorithm 3des;
authentication_algorithm hmac_sha256;
compression_algorithm deflate;
}
RSA Key Generation
The RSA public and private keys have to be generated using the plainrsa-gen
tool.
plainrsa-gen -b 4096 -f /etc/racoon/ipsec.key
The public key part must be extracted from the generate key file and is identified by : PUB
. You must extract that line and, remove the #
start character and put the line in the ipsec.pub
file.
# : PUB 0sXXXXXXX
Test
To verify the configuration, connect to one server and run a ping
command to the second server. Connect to the second server and run a tcpdump
to observe the packets coming from the other server:
$ sudo tcpdump -n host
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
17:34:47.377153 IP 90.1.1.1 > 201.10.10.10: AH(spi=0x0c57e022,seq=0xab9): ESP(spi=0x093415ec,seq=0xab9), length 100
17:34:47.377316 IP 201.10.10.10 >90.1.1.1: AH(spi=0x02ff6158,seq=0x9e3): ESP(spi=0x01375aa7,seq=0x9e3), length 100
17:34:48.379033 IP 90.1.1.1 > 201.10.10.10: AH(spi=0x0c57e022,seq=0xaba): ESP(spi=0x093415ec,seq=0xaba), length 100
17:34:48.379186 IP 201.10.10.10 > 90.1.1.1: AH(spi=0x02ff6158,seq=0x9e4): ESP(spi=0x01375aa7,seq=0x9e4), length 100
IP-IP Tunnels
Now that the servers can connect with each other using IPSec, we create a local network with private addresses that our internal services are going to use. Each server will have its public IP address and an internal address.
In other words, the IP-IP tunnel simulates a local network.
Setup the endpoint (90.1.1.1)
Create the tunnel interface. The Linux kernel must have the tun module installed. The following command creates a tunnel on the host 90.1.1.1 to the remote host 201.10.10.10.
ip tunnel add tun0 mode ipip \
remote 201.10.10.10 local 90.1.1.1
Bind the tunnel interface to an IP address and configure the target IP (10.0.0.1 is our local address, 10.0.0.2 is the remote endpoint):
ifconfig tun0 10.0.0.1 netmask 255.255.255.0 \
pointopoint 10.0.0.2
Setup the client (201.10.10.10)
Create the tunnel interface. The Linux kernel must have the tun module installed. The following command creates a tunnel on the host 201.10.10.10 to the remote host 90.1.1.1.
ip tunnel add tun0 mode ipip \
remote 90.1.1.1 local 201.10.10.10
Bind the tunnel interface to an IP address and configure the target IP (10.0.0.2 is our local address, 10.0.0.1 is the remote endpoint):
ifconfig tun0 10.0.0.2 netmask 255.255.255.0 \
pointopoint 10.0.0.1
Test
Once the tunnel is created, you should get the tun0
interface and be able to ping the remote peers in the 10.0 network.
$ ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.707 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.541 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.630 ms
Firewall Configuration
With the IPsec stack and tunnels in place, it is still necessary to get a good firewall configuration to allow the IPsec traffic, block the non-IPsec traffic (in case of miss-configuration) and protect the server.
The IPSec traffic needs the IKE protocol (UDP port 500) to establish the security associations. The ah
protocol will be used to authenticate the peers and the esp
protocol to encrypt the payload. The IPsec traffic is controlled by the following rules (for the 201.10.10.10 server):
ip=90.1.1.1
iptables -A INPUT -p ah -i eth0 -s $ip -j ACCEPT
iptables -A INPUT -p esp -i eth0 -s $ip -j ACCEPT
iptables -A INPUT -p udp --sport 500 --dport 500 \
-s $ip -j ACCEPT
iptables -A OUTPUT -p ah -o eth0 -d $ip -j ACCEPT
iptables -A OUTPUT -p esp -o eth0 -d $ip -j ACCEPT
iptables -A OUTPUT -p udp --sport 500 --dport 500 \
-d $ip -j ACCEPT
The IP-IP tunnel brings another problem to the firewall configuration. Once extracted, the packets have to match the firewall rules. The iptables
ipsec policy is used to accept the packets that are associated with an IPSec policy.
iptables -A INPUT -m policy --pol ipsec --dir in \
-p 4 -j ACCEPT
iptables -A OUTPUT -m policy --pol ipsec --dir out \
-p 4 -j ACCEPT
Troubles
Setting up the IPsec stack is not easy and does not work immediately. The Linux kernel does not bring any clue to spot the issue.
- Make sure there is no firewall that block the AH/ESP/IKE packets (disable any firewall if necessary)
- Make sure the SPD associations correspond to the peers (Check
/etc/ipsec-tools.conf
on both servers) - Make sure Racoon daemon is running and that it does not report any error (Check
/var/log/daemon.log
)