THIS IS SEVERAL YEARS OLD AND REFERS TO FREES/WAN. Its probably outdated by now. Google will have better info. If you're looking to learn more about Linux check out the Southern California Linux Expo

VPN Howto: Table of Contents

1.0 - Introduction
   1.1 - License
   1.2 - Goals of this Howto
   1.3 - What is a VPN and why would you want one
   1.4 - Types of VPNs
   1.5 - Why Use FreeS/WAN?
   1.6 - Uses for a VPN:

2.0 - Installing IPSec and FreeS/WAN 1.3
   2.1	- Recompiling Kernel
      2.1.1 - Upgrade to latest version (2.2.14)
      2.1.2 - Downloading, Patching and Compiling the Kernel with FreeS/Wan IPSec
      2.1.3 - Installing the new Kernel
   2.2 - Configuration
      2.2.1 - The ipsec.conf file
      2.2.2 - Firewall Configuration
   2.3 - Testing
      2.3.1 - Bring up Connections Manually
      2.3.2 - IPSec look and barf
      2.3.3 - Pings and TCPDump
      2.3.4 - Misc. but Useful Commands
   2.4 - Final Tweaks
      2.4.1 - Enable connect on boot
      2.4.2 - Generate the *real* key

3.0 - References

4.0 - About the Authors

---------------------------------------------------------

1.0 - Introduction

1.1 - License
Copyright (c)  2001  Josh Hyman and Ilan Rabinovitch
Permission is granted to copy, distribute and/or modify this document under 
the terms of the GNU Free Documentation License, Version 1.1 or any later 
version published by the Free Software Foundation.

A copy of the license is available here

1.2 - Goals of this Howto

The goal of this howto is to make it as easy and painless to securely
connect to subnets via the Internet using a VPN based on the FreeS/WAN
implementation of IPSEc. In this howto we assume that you already have
setup your Internet connection, Network, and firewall.  We also assume
that you have some knowledge of Linux.  With a good amount of patience 
anybody should be able to get this working.

1.3 - What is a VPN and Why would you want one?

"VPN" stands for Virtual Private Network.  What does a VPN do? It allows
you to connect two or more remote networks securely over an insecure
connection.  The reason it is called "virtual" is that there is no
physical connection between the 2 networks instead a non-dedicated "secure
tunnel" is created through an insecure connection (like the Internet).
This tunnel is generally encrypted and is only decrypted when it arrives
at the destination host.

Why would you need such a network?  In today's connected world employees
always need access to the data on the corporate network.  Until recently
this was done by dialing directly into the servers.  The issue with this
is that it costs a lot of money with regards to long distance bills as
well as equipment and extra phone lines.  By letting the employee connect
via local internet access where ever he is at the costs are dramatically
reduced.

Another reason for implementing a VPN is to integrate the LANs in several
office or branches.  By connecting the 2 networks, a user in Los Angeles
can access network services in New York while still using their regular
Internet connection.

1.4 - Types of VPNs

There are many ways to implement a VPN.  Many companies use proprietary
software implementation while others use their routers because many
routers have VPN support built in.  These VPNs can be as simple as an SSH
tunnel or very complicated.  But all implementations create a virtual
tunnel through an unsecure network.  Some various VPNs implementations you
should know of are:
   - IPSEC
   - VPND
   - SSH
   - Many Cisco Routers

1.5 - Why Use FreeS/WAN?

Why so many options why have we chosen the Linux FreeS/WAN implementation
of IPSEC for our VPN?  The reason is that we found FreeS/WAN to be one of
the most secure VPN implementations available for Linux.  It is based on
3DES encryption.  In addition we experimented with SSH and VPND but found
that they lacked some of the functionality and support that is available
with FreeS/WAN.  In addition IPSEC (the protocol FreeS/WAN is built
around) is supported by many other pieces of VPN software.  For example
NAI's PGPnet has been found to work very well with FreeS/WAN.  Using that
software you could connect directly into a VPN with out passing through a
Linux box (that is not covered in this howto)

1.6 Uses for a VPN:

  - Connecting 2 or more offices securely over an Internet connection.
  - Allowing an employee to connect to the corporate network remotely with out
    having to dialin and pay long distance charges.
  - Securing traffic / data that is being transferred over the Internet.


2. - Installing IPSec and FreeS/WAN 1.3
2.1 - Recompiling Kernel
2.1.1 - Upgrade to latest version (2.2.14)

When attempting to run IPSec and FreeS/WAN, we recommend you also run at
least kernel 2.2.14.  This is at the recommendation of Alin, who claims
that the 2.2.12 kernel is kinda buggy.  You can download the latest source
from http://www.kernel.org/.  We are assuming that you already know and
understand how to compile the kernel.  We recommend that you compile the
kernel without IPSec so that if something happens, IPSec is not to blame.
One you have a working copy of the 2.2.14 kernel, continue with this howto.


2.1.2 - Downloading Compiling IPSec into the Kernel
Go download the newest version of FreeS/WAN available at
http://www.freeswan.org/.  Un-tar and Un-GZip the file and you will be left
with a directory called "freeswan-x.x" where x.x is the version number.  To
make life easier later, you may want to move this directory into /usr/src/
although that is not necessary.  Assuming that you will be compiling from
the command line and you already created the kernel menu, then you can just
type `make menugo` from *within* the FreeS/WAN directory.  In the
networking section, make sure that all of the items that start with IPSec
are compiled in.  These should be selected by default, but you should check
any way.  Exit the menu and let the kernel recompile.  

2.1.3 - Implementing the new Kernel
Now you need to implement the newly compiled kernel.  So run `cp
/usr/src/linux-2.2.x/arch/i386/boot/bzImage /boot/vmlinuz-2.2.14` to move
the bzImage into the /boot directory. Then run `cp
/usr/src/linux-2.2.14/System.map /boot/System.map-2.2.14` to create the new
System.map file.  You now have the move the symbolic links to the new files
by removing the sym. links named "System.map" and "vmlinuz", and recreating
them.  All that remains is to recreate the modules specific to this kernel
compile.  This can be done by running `make modules` and `make
modules_install` from /usr/src/linux-2.2.14 directory.  

When this is complete configure LILO or what ever boot loader you use and
restart the system, choosing to boot off the new kernel.  When you reboot,
you will notice that IPSec running under FreeS/WAN x.x will start up.  You
should also notices that a new adapter will now show up.  You should make
sure that it exists by running `ifconfig` and making sure that there is an
ipsec0 (or something like that).

2.2 - Configuration
2.2.1 - The ipsec.conf file
Now that IPSec in installed you need to configure your VPN. You will have a
right and left side of the VPN; it doesn't matter who is who, it just has
to be consistent.  See the example below:

 Left Net ===== Left Gate ---------- Right Gate ===== Right Net
                          (Internet)

For the rest of the example the following information holds true:
Left Net:               192.168.1.0/24
Left Gate (internal):   192.168.1.1
Left Gate (external):   100.100.100.100
Left Name:              North

Right Net:              192.168.2.0/24
Right Gate (internal):  192.168.2.254
Right Gate (external):  200.200.200.200
Right Name:             South

Now you need to create connections in the IPSec.conf file.  Each connection
applies to different communication situations.  There is a connection for
the following situations: Net to Net, Left Gate to Right Net, Left Net to
Right Gate, and Gate to Gate.  There is one more connections that is only
used to set global variables.  We recomend that you name these connections
based on their geographic location.  Our 5 connection names will be:
%default (global vars.), NorthNet-SouthNet, NorthGate-SouthNet,
NorthNet-SouthGate, and NorthGate-SouthGate. Remember these names *cannot*
contain spaces!  This is what the config file should look like (the
original %default connection should be ok for the time being):

conn NorthNet-SouthNet   
      left=100.100.100.100
      leftsubnet=192.168.1.0/24
      leftfirewall=yes
      right=200.200.200.200
      rightsubnet=192.168.2.0/24
      rightfirewall=yes
        
conn NorthGate-SouthNet
      left=100.100.100.100
      right=200.200.200.200
      rightsubnet=192.168.2.0/24
      rightfirewall=yes
        
conn NorthNet-SouthGate
      left=100.100.100.100
      leftsubnet=192.168.1.0/24
      leftfirewall=yes
      right=200.200.200.200

conn IlanGate-JoshGate   
      left=100.100.100.100
      right=200.200.200.200

This config file should be pretty self explanatory.  The only thing that
need explanation is left/right firewall.  Set to "yes" if there is a
firewall in play that suppresses forwarding, for example if a subnet behind
left uses non-routable addresses and left does IP masquerade for them.  You
can enable these connections to start automatically, but it would be better
to test them first.  

Now you need to make sure that the correct variables are set in the
configuration portion of the ipsec.conf file.  The section named "config
setup" should look something like this:

  config setup
        interfaces=%defaultroute
        klipsdebug=none
        plutodebug=none

The interfaces option just specifies which interface to use then attempting
to contact where ever IPSec need to go.  By using "%defaultroute", IPSec
just uses the interface that would be used according to the machine route
table. If you are having problems later, you can set "klipsdebug" and
"plutodebug" to all, which will then print messages to the console
(available at /var/log/messages).  However, when anything happens that uses
IPSec, about 5 lines are written to this file.  So be careful how long you
leave this running, you may find you hard drive filling up rapidly!

Next you have to make sure that both sides have the same secrets file.
Since we are only testing now, you can transmit this file by unsecured
means, but in the future, you should send this file using the highest
encryption possible, or send it on CD or Disk. The file should looks
something like this:

 100.100.100.100 200.200.200.200 "jxTR1lnmSjuj33n4W51uW3kTR55luUmSmnlRUuWnkjRj3UuTV4T3USSu23Uk55nWu5TkTUnjT"

Remember we need to recreate this file with a more secure key once testing
is complete.  

2.2.2 - Firewall Configuration
Lastly, if you are using IPChains for your firewall you may want to add the
internal and external NIC IP addresses as "trusted networks".  This will
allow communication on all port between those interfaces.  Sample IPChains
lines follow:

  ipchains -A input -s 100.100.100.100 -d 0/0 -j ACCEPT
  ipchains -A input -s 100.100.100.100 -d 192.168.2.0/24 -j ACCEPT
  ipchains -A input -s 192.168.1.0/24 -d 192.168.2.0/24 -j ACCEPT

These lines will accept input from the external NIC with IP address
100.100.100.100 to the world and the South internal subnet.  This also
allows traffic from one internal subnet to the other.

2.3 - Testing
2.3.1 - Bring up Connections Manually
Once both sides have the ipsec.conf and ipsec.secrets file then testing can
start.  To do this execute the following commands on both gateways:

  [root@wank /etc]# ipsec manual --up NorthGate-SouthGate
  [root@wank /etc]# ipsec manual --up NorthGate-SouthNet
  [root@wank /etc]# ipsec manual --up NorthNet-SouthGate
  [root@wank /etc]# ipsec manual --up NorthNet-SouthNet


2.3.2 - IPSec look and barf
When this is done, run the following command to see what you have
accomplished:

  [root@wank /etc]# ipsec look

If this command prints out something similar to the following you are
probably in good shape; otherwise, there is something wrong with your
configuration.

  foo.spsystems.net Wed Nov 25 22:51:45 EST 1998
  -------------------------
  192.168.1.0/24 -> 192.168.2.0/24 => tun0x200@192.168.2.254 esp0x202@192.168.2.254
  -------------------------
  tun0x200@192.168.2.254 IPv4_Encapsulation: dir=out   192.168.1.1 -> 192.168.2.254
  esp0x203@192.168.1.1 3DES-MD5-96_Encryption: dir=in iv=0xc2cbca5ba42ffbb6  seq=0  bit=0x00000000  win=0  flags=0x0<>
  esp0x202@192.168.2.254 3DES-MD5-96_Encryption: dir=out iv=0xc2cbca5ba42ffbb6  seq=0  bit=0x00000000  win=0  flags=0x0<>
  Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
  192.0.0.0       0.0.0.0         255.255.255.0   U      1500 0          0 eth1
  192.168.2.0     192.168.2.254   255.255.255.0   UG     1404 0          0 ipsec0

If you are really ambitious and want to know exactly what IPSec is doing on
your box, you can type the following command.  We recommend that you write
this to a file, because it is highly likely to fill up your screen many
times over.  Also if you run across a snag, you can send the output of the
command to help diagnose and fix the problem.

  [root@wank /etc]# ipsec barf

2.3.3 - Pings and TCPDump
Now to test our work.  Try pinging the other internal network while keeping
an eye on the tcpdump of ipsec0.  The setup should look like this...

  --- session 1 --- (shows actual pinging)
  [root@wank /etc]# ping 192.168.1.25
  PING 192.168.1.25 (192.168.1.25) from 63.193.147.70 : 56(84)   bytes of data.
  64 bytes from 192.168.1.25: icmp_seq=0 ttl=127 time=45.7 ms
  64 bytes from 192.168.1.25: icmp_seq=1 ttl=127 time=45.2 ms
  64 bytes from 192.168.1.25: icmp_seq=2 ttl=127 time=45.5 ms
  64 bytes from 192.168.1.25: icmp_seq=3 ttl=127 time=43.0 ms

  --- 192.168.1.25 ping statistics ---
  4 packets transmitted, 4 packets received, 0% packet loss
  round-trip min/avg/max = 43.0/44.8/45.7 ms

  --- session 2 --- (shows tcpdump)
  [root@wank /root]# tcpdump -i ipsec0
  Kernel filter, protocol ALL, datagram packet socket
  tcpdump: listening on ipsec0
  21:02:52.873587 > 200.200.200.200 > 192.168.1.25: icmp: echo request
  21:02:52.921596 < 192.168.1.25 > 200.200.200.200: icmp: echo reply
  21:02:53.890317 > 200.200.200.200 > 192.168.1.25: icmp: echo request
  21:02:53.935618 < 192.168.1.25 > 200.200.200.200: icmp: echo reply
  21:02:54.890277 > 200.200.200.200 > 192.168.1.25: icmp: echo request
  21:02:54.936592 < 192.168.1.25 > 200.200.200.200: icmp: echo reply
  21:02:55.890284 > 200.200.200.200 > 192.168.1.25: icmp: echo request
  21:02:55.934099 < 192.168.1.25 > 200.200.200.200: icmp: echo reply

  8 packets received by filter

If all this stuff works for you, then your VPN is most likely up.  You can
further test by setting up a web server that only is available on the
internal NIC of the gateway, or some other internal *only* service.

2.3.4 - Misc. but Useful Commands
IF you ever need to restart the IPSec server the following command
starts/stops/restarts the server.

  [root@wank /root]# ipsec setup start/stop/restart

Obviously you would choose one of those options, as all three at the same
time will confuse IPSec.  If you brought up a connection using `ipsec
manual --up name` then you can take that single connection down by using
the following command (kinda obvious!)

  [root@wank /root]# ipsec manual --down name

That's about all of the useful command that were not previously covered
above.

2.4 - Final Tweaks
Once you have IPSec working and you have tested it using pings and tcpdump,
you are ready to enable these connections to connect on startup.  You also
need to recreate the ipsec.secrets file as the one that is currently being
used is very insecure!  

2.4.1 - Enable connect on boot
To enable automatic connections is actually quite simple.  All you need do
to is tell pluto daemon to automatically load the connections you want
loaded.  This action consists of adding 4 lines of information to the
`config setup` section of the ipsec.conf file.  The lines to be added
follow:

        pluto=yes
        plutoload="NorthGate-SouthGate NorthGate-SouthNet NorthNet-SouthGate NorthNet-SouthNet"
        plutostart="NorthGate-SouthGate NorthGate-SouthNet NorthNet-SouthGate NorthNet-SouthNet"
        plutowait=no

The order that the connections are placed in `plutoload` and `plutostart`
are trivial because each connection is independent. Now to explain what is
happening here!  The first line tells pluto that you plan to load
connections in the first place.  If we haven't added any connections to
pluto search in the individual connection setup (which we haven't) we have
to tell pluto which connections to load (in this case all of them).  The
`plutostart` line tells the daemon which of the loaded connections to start
on startup.  And lastly, the `plutowait=no` command tells pluto not to wait
until each connection is completely up before trying to load the next one.
Since we have already tested all our connections (or should have), then
there should be no problems.  Just to make sure that this is true, restart
ipsec using the following command:

  [root@wank /etc]# ipsec setup restart

If all goes well, the output should look something like this:

  ipsec_setup: Stopping FreeS/WAN IPSEC...
  ipsec_setup: Shutting down Pluto:
  ipsec_setup: Taking ipsec0 down:
  ipsec_setup: Misc cleanout:
  ipsec_setup: ...FreeS/WAN IPSEC stopped
  ipsec_setup: Starting FreeS/WAN IPSEC 1.3...
  ipsec_setup: KLIPS debug `none'
  ipsec_setup: KLIPS ipsec0 on eth0 200.200.200.200/255.255.255.0 broadcast 200.200.200.255
  ipsec_setup: Disabling core dumps:
  ipsec_setup: Starting Pluto (debug `none'):
  ipsec_setup: Loading Pluto database `NorthGate-SouthGate NorthGate-SouthNet NorthNet-SouthGate NorthNet-SouthNet':
  ipsec_setup: Enabling Pluto negotiation:
  ipsec_setup: Routing for Pluto conns `NorthGate-SouthGate NorthGate-SouthNet NorthNet-SouthGate NorthNet-SouthNet':
  
  ipsec_setup: Initiating Pluto tunnel `NorthGate-SouthGate' (asynchronously):
  ipsec_setup: Initiating Pluto tunnel `NorthGate-SouthNet' (asynchronously):
  ipsec_setup: Initiating Pluto tunnel `NorthNet-SouthGate' (asynchronously):
  ipsec_setup: Initiating Pluto tunnel `NorthNet-SouthNet' (asynchronously):
  
  ipsec_setup: ...FreeS/WAN IPSEC started

If you have a similar output, then you are in business.  These connections
should then start every time that Pluto starts.  This includes boot time
and any other time that you choose to restart IPSec.

2.4.2 - Generate *real* key
Previous to now, a sample key has been used on each side for authentication
purposes.  This, however, is completely insecure, as a similar key to the
one you are most likely using exists on the net.  Therefore, this key
should and must be changed when testing is complete.  A random string can
be generated by a program called ranbits, which can be run using the
following command:

  [root@wank /etc]# ipsec ranbits 192 >> ipsec.secrets

This will create a string of random alpha-numeric data.  This file should
then be edited to contain the IP addresses of the gateways, similar to
above.  This file should be transferred by secure mean to the other gateway
via ssh, pgp, etc.  Further the permissions on this file should be 600
(-rw-------) and owned by root.  This will stop intruders from reading your
ipsec.secrets file.

3.0 - References
1) FreeS/Wan Documentation
   http://www.freeswan.org/freeswan_trees/freeswan-1.3/doc/

2) O'REILLY Virtual Private Networks 2nd Edition
   Charlie Scott, Paul Wolfe & Mike Erwin

3) Linux-IPSEC Mailing List
   http://www.freeswan.org/mail.html

**Special Thanks to Alex Guy for putting up with all our stupid questions.**

4.0 - About the Authors
Josh is a high school student who is into web design and programming.  He
currently works as an assistant network admin, programmer, and web
designer at American Reinsurance in Woodland Hills.  He also works at Net
Data Systems, a web design company out to Van Nuys.  He enjoys tinkering
with computers and playing sports.  He has just recently picked up Linux
and a hobby, and is learning more every day!  You can reach Josh vie email
at eagle2k@pacbell.net or on IRC (either openprojects.net/linux.com or
efnet) as eagle2k.

Ilan can be reached via e-mail at ilan@fonz.net or on IRC (openprojects.net / freenode / oftc.net) as fonz or ilan.
He is currently Conference Chair for the Southern California Linux Expo