IP Security (IPSec) is the encryption of network traffic. You cannot encrypt the header information or trailer (i.e. the IP address/port the packet is from, and going to, the CRC checksums, and so on), but you can encrypt the data payload. This allows you to secure protocols such as POP/WWW without having to change them in any ways, since the encryption occurs at the IP level. It also allows you to securely connects LANs and clients to each other over insecure networks (like the Internet). Currently IPSec for Linux is in testing, however there have been several stable releases, and I myself have deployed Linux based IPSec servers successfully. IPSec is a standard, and a part of the IPv6 protocol, you can already purchase IPSec software for Windows 95/98/NT, Solaris, and other unices that will interoperate with Linux IPSec.
To use IPSec you need IPSec support in the kernel. Unfortunately no American Linux distribution can ship strong crypto outside of North America so generally speaking they choose not to include it at all, of the foreign Linux distributions, currently, none ship with IPSec support built into the kernel. You will need to get the kernel source (I recommend 2.2.10, the most current at the time of writing), and the Linux IPSec source code, available from: http://www.xs4all.nl/~freeswan/.
Install the kernel source (usually to /usr/src/linux) and then compile a new kernel, install it, boot to it, and test it. Make sure your networks work properly, if they don't work, getting IPSec to work will be impossible. Now you need to download the latest IPSec snapshot (version 1.0 will NOT work with 2.2.x kernels). Then go to /usr/local/src (or wherever you put your source code for programs), unpack the source and run the install program (make menugo typically for the ncurses based configuration). This will patch the kernel files, then run the kernel configuration, and then build the IPSec tools, and the kernel.
cd /usr/local/src/ tar -zvvxf /path/to/tarball/snapshot.tar.gz chown -R root:root freeswan-snap1999Jun14b cd freeswan-snap1999Jun14b make menugo
make sure you save the kernel configuration, even though the options are chosen they have not been saved. You will also have to rebuild the kernel as the "make menugo" command runs a "make zImage" which usually fails due to the large kernel sizes with 2.2.x. Once the compile is done it should have an error message or two, simply:
cd /usr/src/linux make bzImage cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-2.2.10-ipsec
Now we need to edit lilo.conf, rerun lilo, and reboot to make use of the new kernel. lilo.conf should look like:
boot=/dev/hda map=/boot/map install=/boot/boot.b prompt timeout=100 image=/boot/vmlinuz-2.2.10-ipsec label=linux-ipsec root=/dev/hda1 read-only image=/boot/vmlinuz-2.2.10 label=linux root=/dev/hda1 read-only
rerun lilo and you should see:
linux-ipsec * linux
then reboot and you should be running kernel 2.2.10 with IPSec support. As the machine reboots and starts the IPSec stuff you will see several errors, by default IPSec is set to use the eth999 interface, which of course does not exist. You should also add /usr/local/lib/ipsec to your path statement or else you will have to type the full path in a lot.
You will need to enable TCP-IP forwarding on the gateway server, in Red Hat Linux this is accomplished by changing the line in /etc/sysconfig/network from:
or you can enable it via the /proc filesystem:
cat 1 > /proc/sys/net/ipv4/ip_forward
Since most people have default deny policies for forwarding packets you will need to allow packets to traverse from the remote network / machine to your network / machine and vice versa. In addition to this, any masquerading rules for internal networks that are also using IPSec must come after the rules allowing IPSec related traffic, or the machine will try to masquerade the packets, instead of them being passed over to IPSec.
The following example is for two protected networks (using non routable IP addresses, hidden behind Linux machines doing IP masquerading) connected via the Internet:
First we'll set up a link using manual keying (for simplicity), you will need to edit ipsec.conf, and your firewall rules. Most of the defaults in the ipsec.conf file are fine but you will need to change the following:
conn sample type=tunnel left= leftnexthop= leftsubnet= right= rightnexthop= rightsubnet= spibase=0x200 esp=3des-md5-96 espenckey= espauthkey=
replace the espenckey and espauthkey with new keys (using ranbits to generate a number, remember to leave the leading 0x that specifies it is a hex number) so that it looks like:
conn my-tunnel type=tunnel left=18.104.22.168 leftnexthop=22.214.171.124 leftsubnet=10.0.0.0/24 right=126.96.36.199 rightnexthop=188.8.131.52 rightsubnet=192.168.0.0/24 spibase=0x200 esp=3des-md5-96 espenckey=some_auth_key_here (ranbits 192) espauthkey=some_other_key_here (ranbits 128)
Once you have done this copy the files ipsec.conf and ipsec.secrets from the machine you edited them on to the other server in a secure manner. Now all that remains to be done is the addition of some firewall rules so that packets do not get masqueraded (instead we simply want them forwarded).
On Server 184.108.40.206 you should add the following rules:
ipchains -A forward -p all -j ACCEPT -s 10.0.0.0/24 -d 192.168.0.0/24 ipchains -A forward -p all -j ACCEPT -s 192.168.0.0/24 -d 10.0.0.0/24
make sure these rules appear before the masquerading rule, it should look like this:
# # FORWARD RULES # ipchains -P forward DENY # ipchains -A forward -p all -j ACCEPT -s 10.0.0.0/24 -d 192.168.0.0/24 ipchains -A forward -p all -j ACCEPT -s 192.168.0.0/24 -d 10.0.0.0/24 ipchains -A forward -p all -j MASQ -s 10.0.0.0/24 -d 0.0.0.0/0
And on server 220.127.116.11 you basically repeat the process:
ipchains -A forward -p all -j ACCEPT -s 192.168.0.0/24 -d 10.0.0.0/24 ipchains -A forward -p all -j ACCEPT -s 10.0.0.0/24 -d 192.168.0.0/24
make sure these rules appear before the masquerading rule, it should look like this:
# # FORWARD RULES # ipchains -P forward DENY # ipchains -A forward -p all -j ACCEPT -s 192.168.0.0/24 -d 10.0.0.0/24 ipchains -A forward -p all -j ACCEPT -s 10.0.0.0/24 -d 192.168.0.0/24 ipchains -A forward -p all -j MASQ -s 192.168.0.0/24 -d 0.0.0.0/0
Now you should be able to bring up the ipsec tunnel on both machines manually and the machines on Network A should be able to talk to the machines on Network B with no problems.
ipsec manual -up my-tunnel
and it should produce output similar to:
/usr/local/lib/ipsec/spi: message size is 36 /usr/local/lib/ipsec/spi: message size is 132 /usr/local/lib/ipsec/spi: message size is 132
To test it try pinging 192.168.0.2 from the 10.0.0.2 client. If this works then you have set it up correctly. If it does not work check your network to make sure 18.104.22.168 can reach 22.214.171.124, and that TCP-IP forwarding is enabled, and make sure that no firewall rules are blocking the packets, or trying to masquerade them. Once you have established a connection and tested it successfully you should move to automatic keying (especially if it's in a production environment).
If you intend to use IPSec in a production environment, manual keying is a bad idea generally speaking. With automatic keying you have a 256 bit shared secret you copy to both ends of the tunnel, which is then used during the key exchanges to make sure a man in the middle attack does not occur. With automatic keying the default lifetime of a key is 8 hours, which you can set to anything you like, and if someone manages to brute force the key, it is only good for that 8 hour chunk of traffic. The following example builds on the previous one:
ipsec.secrets contains the shared secret. This file must be kept secure at all costs. For a connection between the 126.96.36.199 and 188.8.131.52 servers you would need a line like:
184.108.40.206 220.127.116.11 "0xa3afb7e6_20f10d66_03760ef1_9019c643_a73c7ce0_91e46e84_ef6281b9_812392bf"
This line needs to be in the ipsec.secrets file of both computers. You would then need to edit the tunnel configuration in ipsec.conf to the following:
conn my-tunnel type=tunnel left=18.104.22.168 leftnexthop=22.214.171.124 leftsubnet=10.0.0.0/24 right=126.96.36.199 rightnexthop=188.8.131.52 rightsubnet=192.168.0.0/24 keyexchange=ike keylife=8h keyingtries=0
The pluto daemon will then startup, try to connect to the Pluto daemon at the other end of the tunnel, and establish a connection. One caveat, Pluto runs on port 500, UDP, so chances are you will have to poke a hole in your firewall to allow it through:
ipchains -A input -p udp -j ACCEPT -s 0.0.0.0/0 -i eth0 -d 0.0.0.0/0 500
I find it convenient to use the "%search" keyword instead of listing the tunnel to bring up, by adding:
to each tunnel configuration and editing ipsec.secrets:
This will make your life generally easier in the long run. If all goes well you should see something like this in /var/log/messages:
Jun 26 02:10:41 server ipsec_setup: Starting FreeS/WAN IPSEC... Jun 26 02:10:41 server ipsec_setup: /usr/local/lib/ipsec/spi: message size is 28. Jun 26 02:10:41 server ipsec_setup: KLIPS debug `none' Jun 26 02:10:41 server ipsec_setup: KLIPS ipsec0 on eth0 184.108.40.206/255.255.255.0 broadcast 220.127.116.11 Jun 26 02:10:42 server ipsec_setup: Disabling core dumps: Jun 26 02:10:42 server ipsec_setup: Starting Pluto (debug `none'): Jun 26 02:10:43 server ipsec_setup: Loading Pluto database `my-tunnel': Jun 26 02:10:44 server ipsec_setup: Enabling Pluto negotiation: Jun 26 02:10:44 server ipsec_setup: Routing for Pluto conns `my-tunnel': Jun 26 02:10:45 server ipsec_setup: Initiating Pluto tunnel `my-tunnel': Jun 26 02:10:45 server ipsec_setup: 102 "my-tunnel" #1: STATE_MAIN_I1: initiate Jun 26 02:10:45 server ipsec_setup: 104 "my-tunnel" #1: STATE_MAIN_I2: from STATE_MAIN_I1; sent MI2, expecting MR2 Jun 26 02:10:45 server ipsec_setup: 106 "my-tunnel" #1: STATE_MAIN_I3: from STATE_MAIN_I2; sent MI3, expecting MR3 Jun 26 02:10:45 server ipsec_setup: 003 "my-tunnel" #1: STATE_MAIN_I4: SA established Jun 26 02:10:45 server ipsec_setup: 110 "my-tunnel" #2: STATE_QUICK_I1: initiate Jun 26 02:10:45 server ipsec_setup: 003 "my-tunnel" #2: STATE_QUICK_I2: SA established Jun 26 02:10:46 server ipsec_setup: ...FreeS/WAN IPSEC started
And in the /var/log/secure file you should see something like:
Jun 26 02:10:42 server Pluto: Starting Pluto (FreeS/WAN Version snap1999Jun14b) Jun 26 02:10:44 server Pluto: added connection description "my-tunnel" Jun 26 02:10:44 server Pluto: listening for IKE messages Jun 26 02:10:44 server Pluto: adding interface ipsec0/eth0 18.104.22.168Jun 26 02:10:44 server Pluto: loading secrets from "/etc/ipsec.secrets" Jun 26 02:10:45 server Pluto: "my-tunnel" #1: initiating Main Mode Jun 26 02:10:45 server Pluto: "my-tunnel" #1: ISAKMP SA established Jun 26 02:10:45 server Pluto: "grumpy-seifried" #2: initiating Quick Mode POLICY_ENCRYPT+POLICY_TUNNEL+POLICY_PFS Jun 26 02:10:45 server Pluto: "my-tunnel" #2: sent QI2, IPsec SA established Jun 26 02:11:12 server Pluto: "my-tunnel" #3: responding to Main Mode Jun 26 02:11:12 server Pluto: "my-tunnel" #3: sent MR3, ISAKMP SA established Jun 26 02:11:12 server Pluto: "my-tunnel" #4: responding to Quick Mode Jun 26 02:11:12 server Pluto: "my-tunnel" #4: IPsec SA established Jun 26 02:31:31 server Pluto: "my-tunnel" #5: responding to Main Mode Jun 26 02:31:32 server Pluto: "my-tunnel" #5: sent MR3, ISAKMP SA established Jun 26 02:31:32 server Pluto: "my-tunnel" #6: responding to Quick Mode Jun 26 02:31:32 server Pluto: "my-tunnel" #6: IPsec SA established
In addition to this you can view the "eroute" output to make sure the tunnels are correctly configured:
10.0.0.0/24 -> 192.168.0.0/24 => firstname.lastname@example.org
And if you view your routes ("route") you should see:
Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 22.214.171.124 0.0.0.0 255.255.255.255 UH 0 0 0 eth0 10.0.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth 126.96.36.199 0.0.0.0 255.255.255.0 U 0 0 0 eth0 188.8.131.52 0.0.0.0 255.255.255.0 U 0 0 0 ipsec0 192.168.0.0 184.108.40.206 255.255.255.0 UG 0 0 0 ipsec0 10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo0.0.0.0 220.127.116.11 0.0.0.0 UG 0 0 0 eth0
I thought it would also be appropriate to list commercial IPSec products briefly, with an emphasis of course on those based on Linux and FreeS/WAN.
i-data makes a line of products including a VPN server, based on Linux and FreeS/WAN. They are located in Denmark, making their product available world-wide. Their website is at: http://www.i-data.com/networks/.
There are also a number of software packages to give Windows IPSec capability, one of which is even free.
The makers of PGP (Network Associates) have now created a "PGP VPN" software package (which has very little to do with PGP). It supports IPSec and has been reported as inter-operable with Linux FreeS/WAN. You can get it from: http://www.nai.com/asp_set/products/tns/pgp_vpn.asp. The free version of PGP from NAI also supports IPSec VPN's and is available from: http://www.pgpi.com/.
Written by Kurt Seifried