An IPsec tunnel implementation for Linux ======================================== Quickstart Instructions ----------------------- The IPsec tunnel implementation is divided into two parts, one kernel module called ipsec.o, and a tool to administrate security associations and tunnels, called ipsecadm. Both the kernel module and the ipsecadm tool are installed by running make install. Start by loading the kernel module into the Linux kernel by running modprobe ipsec. You now have a new inactive network device called ipsec0 which can be seen if you run ifconfig -a. The ipsecadm tool has a built-in brief help which is displayed if you execute it without paramters, or with unknown or invalid parameters. You can also look at the manual page by running man ipsecadm. The tool has two main modes. One is for adding and removing security associations (SAs), and one for adding and removing tunnels. Before we start, we need an example scenario. Let's say that we are going to create a tunnel between two hosts A and B. The public IP number of host A is 1.2.3.4 and it's private IP address is is 10.0.1.0/24. Host A B ------------------------------------------------ Public IP address 1.2.3.4 5.6.7.8 Private IP address 10.0.1.1 10.0.2.1 Private network 10.0.0.0/24 10.0.2.0/24 IPsec uses Security Associations (SA), which is another name for a security agreement between two hosts. The SA is uniquely described by two IP addresses and a 32-bit number number called a SPI. The SPI allows more than one SA between a pair of hosts. When the SA was agreed upon, the two parties agreed upon the type of the SA which can basically be encryption or athorization, and also the algorithm, key size and key to be used. It's time for an example. This is an SA in (more or less) plain English: SPI: 0x1000 Destination IP: 1.2.3.4 Source IP: 5.6.7.8 Type: Encryption Algorithm: Tripple DES Key Size: 192 bits Key: Before we can create an SA, we need a key. One way to create a key is to use /dev/random. To create a 192-bit key (which corresponds to 24 bytes) and put it in the file /etc/ipsec/ipsec.key run the following: mkdir /etc/ipsec chmod 500 /etc/ipsec dd if=/dev/random of=/etc/ipsec/example.key bs=24 count=1 Now we can use ipsecadm to create the SA above. The name of the cipher is specified using its cryptoapi name, which can be a little strange. The name for tripple DES is des_ede3-cbc. You can see which ciphers you have installed by looking in the directory /proc/crypto/cipher/. ipsecadm sa add --spi=0x1000 --dst=5.6.7.8 --src=1.2.3.4 \ --cipher=des_ede3-cbc \ --cipher-keyfile=/etc/ipsec/example.key \ --duplex Simple, isn't it? Wondering about the --duplex parameter? To create tunnel you need two SAs, one in each direction. Since it is common to use the same security settings for both directions you can create a pair of SAs in one go by using --duplex. In the example above, the key is given on the command line which is bad since it is easy for To look at the two SAs you just created, run the following: ipsecadm sa show Note that the SAs can be used for all IPsec traffic, and not only for tunnels, but right now only tunnels are implemented. Also make sure you add the SAs on both hosts. The next step is to create the tunnels. I will show the commands needed for host A, and leave the commands for host B as a simple excercise. Run the following: ipsecadm tunnel add ipsec1 --local=1.2.3.4 --remote=5.6.7.8 As you can see there is no need to specify the SPI. You can do that if you want to using the --spi option, but if unspecified, the local and remote addresses will be used to find a suitable SA. Now we need to set an IP number on the newly created tunnel device, but what should it be? When a packet is created on a machine, the destination address is used by the routing table to find the outgoing device for the connection, and the source address is set to the address of the device. (This is a bit simplified, but enough for us now.) If you initiate a connection from host A to an address on the private network at host B, you probably want the source address of your packets to be the private address of host A, which is 10.0.1.1: ifconfig ipsec1 10.0.1.1 up The last step is to create an entry in the routing table that makes the packets to the private network at host B go out via the ipsec1 device: route add -net 10.0.2.0/24 dev ipsec1 That's it! Do the equivalent thing on host B and you should be all set! Nothe that you should not generate a new key on host B, but copy the one you made for host A to host B. Make sure that you copy the key in a secure manner, e.g. using ssh/scp.