               ****************************************
               * IPSEC for Linux, Preliminary Release *
               ****************************************

* 
* $Id: INSTALL.txt,v 0.4 1997/01/14 21:35:31 ji Rel $
*
* $Log: INSTALL.txt,v $
* Revision 0.4  1997/01/14 21:35:31  ji
* Added new transforms.
* Cleaned up the user-level programs.
*
* Revision 0.3  1996/11/20 11:59:33  ji
* *** empty log message ***
*
*
* New in this release (0.3; works with the 2.0.24 kernel)
*
*   > Cleaned up a fair amount of crud.
*   > Fixed truncated names of /proc/net entries.
*   > Made RCS versioning visible to the external release.
*   > Rationalized debugging facilities.
*   > Rationalized untar directory structure.
*   > Fixed non-incrementing IV in DES-CBC
*   > Cleaned up this file a bit and provided additional examples

1. Installation

You just untarred ipsec-0.4.tar.gz.
You are in ipsec-0.4/.
Around you you can see:
* A linux/ directory. 
* A utils/ directory.
* A test/ directory.
* A doc/ directory.

The contents of linux/ should go where your linux source tree is
(probably /usr/src/linux).

The utils/ directory contains the user-level utilities which you need
to run IPSEC.

The test/ directory contains test scripts.

The doc/ directory contains -- what else -- documentation (including
this file).

You may also want to copy this file to
/usr/src/linux/Documentation/networking/ipsec.txt.

1.1. Kernel Installation

Files go into /usr/src/linux/net/ipsec/.

1.1.1. Source files

Create /usr/src/linux/net/ipsec. The files in from linux/net/ipsec/* go
there. Create /usr/src/linux/net/ipsec/libdeslite and put the files in
libdeslite/* there.

Makefile			The Makefile
Config.in			The configuration script for make menuconfig

radij.c				General-purpose radix-tree operations

ipsec_init.c			Initialization code, /proc interface.
ipsec_radij.c			Interface with the radix tree code.
ipsec_netlink.c			Interface with the netlink code.
ipsec_xform.c			Routines and structures common to transforms.
ipsec_tunnel.c			The tunneling interface code.
ipsec_ipe4.c			IP-in-IP encapsulation code.
ipsec_ah.c			Generic AH transfrom code.
ipsec_ahmd5.c			Specific AH-MD5 transform code.
ipsec_ahhmacmd5.c		Specific AH-HMAC-MD5 transform code.
ipsec_ahhmacsha1.c		Specific AH-HMAC-SHA1 transform code.
ipsec_md5c.c			Somewhat modified RSADSI MD5 C code.
ipsec_sha1.c			Somewhat modified Steve Reid SHA-1 C code.
ipsec_esp.c			Generic ESP transform code.
ipsec_espdes.c			Specific ESP-DES-CBC code.
ipsec_espdesmd5.c		Specific ESP-DES-MD5 code.
ipsec_esp3desmd5.c		Specific ESP-3DES-MD5 code.

libdeslite/*			Selected files from libdes.3.21.

radij.h				Headers for radij.c
ipsec_radij.h			Interface with the radix tree code.
ipsec_netlink.h			Headers used by the netlink interface.
ipsec_encap.h			Headers defining encapsulation structures.
ipsec_xform.h			Transform headers.
ipsec_tunnel.h			Headers used by tunneling code.
ipsec_ipe4.h			Headers for the IP-in-IP code.
ipsec_ah.h			Headers common to AH transforms.
ipsec_md5h.h			RSADSI MD5 headers.
ipsec_sha1.h			SHA-1 headers.
ipsec_esp.h			Headers common to ESP transfroms.

Also, apply the following diffs to files in /usr/src/linux/net:

$ rcsdiff -p Config.in
===================================================================
RCS file: RCS/Config.in,v
retrieving revision 1.1
diff -p -r1.1 Config.in
*** Config.in   1996/08/04 20:05:53     1.1
--- Config.in   1996/08/04 20:15:24
*************** bool 'Kernel/User network link driver' C
*** 27,30 ****
--- 27,34 ----
  if [ "$CONFIG_NETLINK" = "y" ]; then
    bool 'Routing messages' CONFIG_RTNETLINK
  fi
+ tristate 'IP Security Protocol' CONFIG_IPSEC
+ if [ ! "$CONFIG_IPSEC" = "n" ]; then
+   source net/ipsec/Config.in
+ fi
  endmenu


$ rcsdiff -p Makefile
===================================================================
RCS file: RCS/Makefile,v
retrieving revision 1.1
diff -p -r1.1 Makefile
*** Makefile    1996/08/04 20:05:46     1.1
--- Makefile    1996/08/04 23:31:59
*************** else
*** 66,69 ****
--- 66,77 ----
    endif
  endif

+ ifeq ($(CONFIG_IPSEC),y)
+ SUB_DIRS += ipsec
+ else
+   ifeq ($(CONFIG_IPSEC),m)
+   MOD_SUB_DIRS += ipsec
+   endif
+ endif
+
  include $(TOPDIR)/Rules.make

1.1.2. Kernel configuration.

Go to the /usr/src/linux and type "make menuconfig" (or whatever). In
the "Networking options" menu, enable IP Forwarding, IP tunneling, and
the Kernel/User netlink driver. You will also see a new entry for "IP
Security". Enable it as a module. Currently, the IPSEC code works ONLY
AS A MODULE. Enabling IPSEC will give you several more options. Enable
IP-in-IP encapsulation, IP Authentication Header, and IP Encapsulated
Security Payload. You will get some more options for AH and ESP;
enable any that you want -- they all work!

Go through the usual make process, install the resulting kernel, and
reboot. When the system comes back up, go back to /usr/src/linux and
do a make modules; this should create ipsec.o in the modules/
directory. Then:
	# insmod ipsec.o

The following messages should appear on your console:

	ipsec_init: attaching <IPv4 Simple Encapsulation>
	ipe4_attach: called.
	ipsec_init: attaching <Keyed MD5 Authentication>
	ahmd5_attach: called.
	ipsec_init: attaching <DES-CBC Encryption>
	espdes_attach: called.
	ipsec_init: attaching <HMAC MD5 Authentication>
	ahhmacmd5_attach: called.
	ipsec_init: attaching <HMAC SHA-1 Authentication>
	ahhmacsha1_attach: called.
	ipsec_init: attaching <DES-MD5 Encryption>
	espdesmd5_attach: called.
	ipsec_init: attaching <3DES-MD5 Encryption>
	esp3desmd5_attach: called.
	ipsec_tunnel: tunnel: version v0.2b2

The module does not support unloading (yet). Reboot your machine to
get rid of it.

1.1.3. Debugging messages.

You may selectively enable debugging at the configuration stage. Grep
through the IPSEC source files for variable names beginning with
debug_. By setting various bits in those variables, you can control
which (if any) messages get printed. 

Ignore any outb() calls that remain; they are there for my
hardware-assisted debugging.

1.2. User-level files.

The user-level files are in the utils/ directory. They are:

addrt.c		Create an "extended route"
setsa.c		Set up Security Associations
spigrp.c	Link SPIs together.

Typing "make" Compiles them into executables with the same name. They
don't need any libraries. You may need to edit the makefile if your
linux kernel source tree is not under /usr/src/linux.The rest of this
document assumes these programs are in your search path.

1.3. Initialization.

When you load the ipsec.o module, the /proc/net/ipsec-rt and
/proc/net/ipsec-spi entries are created, and interface ipsec0 is
attached. The first time you play with the code, you should also
create the necessary netlink device file:

	# mknod /dev/ipsec c 36 10

The system is now ready to use as an encrypting router. The rest of
this file gives examples of how to set things up. The scripts in test/
are just all the commands described here put together.

2. Operation.

Here is a simplified view of my testbed:


    +-------+						    +-------+
    |  elf  |						    |  del  |
    +---*---+						    +---*---+
   eth1 * 10.1.0.145      	        		    ef1 * 10.3.0.140
	*							*
    *************************               *************************
			*			*
                   eth1 * 10.1.0.143       eth2 * 10.3.0.139
                    +---*---+	            +---*---+
                    |  fir  |               |  ice  |
                    +---*---+               +---*---+
		   eth2 * 10.2.0.143       eth1 * 10.2.0.139
			*			*	
		    *********************************


In case you are wondering, all machines are connected to the same
"main" network with their eth0 interfaces, but this is irrelevant to
the examples, and hence not shown in the diagram.

Only fir and ice need to run IPSEC. 

All netmasks are 255.255.0.0.

Elf has a route to 10.3.xx.xx via fir, and del has a route to
10.1.xx.xx via ice. 

fir and ice know how to route only to their connected subnets; fir
does not (yet) know how to get to 10.3.xx.xx, and ice does not know how to
get to 10.1.xx.xx. 

First, let us set up fir. The setup for ice is the reverse.

The first order of business is to configure the ipsec0 virtual interface:

	fir# ifconfig ipsec0 10.2.0.143 netmask 255.255.0.0 


Now, we want to set up fir so that packets from elf to del will be
tunneled through the (fir->ice) tunnel. The first step is to set up a
route to net 10.3.xx.xx through the ipsec0 interface:

	fir# route add -net 10.3.0.0 netmask 255.255.0.0 dev ipsec0

This is just a hack to force the packets destined for net 10.3 to go
through our code by forcing them through the ipsec0 interface. Now, we
want to tell them exactly what will happen to these packets. 

Issue the following command:

	fir# addrt 10.1.0.0 255.255.0.0 10.3.0.0 255.255.0.0 10.2.0.139 103

To verify it has worked, type:

	fir# cat /proc/net/ipsec-rt

you should get:

(10.1.0.0/255.255.0.0 -> 10.3.0.0/255.255.0.0) => (10.2.0.139, 0x00000103)


This means that packets originating from net 10.1.xx.xx and destined
for net 10.3.xx.xx should be IPSEC-processed, with a "Destination
Address" of 10.2.0.139 and a "Security Parameters Index" of 103. The
Destination Address indicates the other point of the tunnel, whether
it is a real tunnel (as in this case), or simply the destination (in
what we call "transport mode" which doesn't quite work yet). The
Security Parameters Index, or SPI, is an opaque value that indicates,
along with the DA, what processing these packets will receive at our
end as well as the remote end. The pair (DA, SPI) is called a SAID
(Security Association IDentifier) in this document.

We now want to tell the IPSEC code what the processing for packets
which have been selected to be processed with DA=10.2.0.139 and
SPI=103. First, they will be encapsulated in simple IP-in-IP (proto 4)
encapsulation, and to enable that we type:

	fir# setsa 10.2.0.139 103 ip4 10.2.0.143 10.2.0.139

This tells the IPSEC code that packets which have been selected to be
processed with DA=10.2.0.139 and SPI=103 should be run through algorithm
1 (IP-in-IP), with "outer" (encapsulating packet) source and
destination addresses of 10.2.0.143 (fir) and 10.2.0.139 (ice)
respectively. Type
	
	fir# cat /proc/net/ipsec-spi

to verify that the SAID has been formed. You should get

(10.2.0.139, 00000103, 1: [10.2.0.143 -> 10.2.0.139])

So far so good, but we've simply reproduced already existing
functionality. Now, let's add security. First, we'll tell the code to
encrypt packets using the ESP-DES-CBC transform. We'll create another
SAID, this time for algorithm 4 (ESP-DES-CBC).

	fir# setsa 10.2.0.139 105 esp des-cbc 66306630 6630663066303132

This tells the IPSEC layer that packets destined to be processed with
DA=10.2.0.139, SPI=105, should be processed with algorithm #4
(ESP-DES-CBC), use 0x66306630 as the DES-CBC Initialization Vector,
and use 0x6630663066303132 as the DES key (the DES parity bits are
ignored, so this yields the 56-bit DES key). 

Finally, we also want to authenticate the resulting packet, so we
create another SAID, this time for the AH-MD5 transform:

	fir# setsa 10.2.0.139 106 ah md5 66306630663031326630663066303132

Now comes the crucial step. What the original addrt command did was to
establish that outgoing packets are to be processed with IP-in-IP
encapsulatino first. Now, we need to "link" this transform (IPIP) to the ESP
transform and then the AH. We do that with the spigrp ("group SPIs")command:

	fir# spigrp 10.2.0.139 103 10.2.0.139 105 10.2.0.139 106

Now, we also need to specify what will happen when we receive
packets. IP-in-IP does not need any special handling. ESP and AH,
however, need the SAIDs to be established. We use the same commands we
used for the outgoing packets, but specifying ourselves as the
destination (of course). 

	fir# setsa 10.2.0.143 115 esp des-cbc 66306630 6630663066303132
	fir# setsa 10.2.0.143 116 ah md5 66306630663031326630663066303132

To see the whole picture, type:
	fir# cat /proc/net/ipsec-spi
	(10.2.0.143, 00000116, 2: klen = 16, alen = 16)
	(10.2.0.143, 00000115, 4: ivlen = 4, iv = 66 30 66 30)
	(10.2.0.139, 00000106, 2: klen = 16, alen = 16)
	(10.2.0.139, 00000105, 4: ivlen = 4, iv = 66 30 66 30)
	(10.2.0.139, 00000103, 1: [10.2.0.143 -> 10.2.0.139])

On ice, now, we have to send things up the opposite way. Here are the
commands to use:

	ice# ifconfig ipsec0 10.2.0.139 netmask 255.255.0.0
	ice# route add -net 10.1.0.0 netmask 255.255.0.0 dev ipsec0

	ice# addrt 10.3.0.0 255.255.0.0 10.1.0.0 255.255.0.0 10.2.0.143 113
	ice# setsa 10.2.0.143 113 ip4 10.2.0.139 10.2.0.143
	ice# setsa 10.2.0.143 115 esp des-cbc 66306630 6630663066303132
	ice# setsa 10.2.0.143 116 ah md5 66306630663031326630663066303132

	ice# spigrp 10.2.0.143 113 10.2.0.143 115 10.2.0.143 116

	ice# setsa 10.2.0.139 105 esp des-cbc 66306630 6630663066303132
	ice# setsa 10.2.0.139 106 ah md5 66306630663031326630663066303132

	ice# cat /proc/net/ipsec-rt 
	(10.3.0.0/255.255.0.0 -> 10.1.0.0/255.255.0.0) => (10.2.0.143, 0x00000113)
	ice# cat /proc/net/ipsec-spi 
	(10.2.0.143, 00000116, 2: klen = 16, alen = 16)
	(10.2.0.143, 00000115, 4: ivlen = 4, iv = 6f 30 66 30)
	(10.2.0.143, 00000113, 1: [10.2.0.139 -> 10.2.0.143])
	(10.2.0.139, 00000106, 2: klen = 16, alen = 16)
	(10.2.0.139, 00000105, 4: ivlen = 4, iv = 66 30 66 30)

If you ping del from elf, ICMP packets will leave elf, reach fir, get
encapsulated in IPIP, encrypted with DES and authenticated with MD5,
tunneled to ice, get decapsulated, and then sent to del; the return
packets will follow the inverse path.

For completeness, let us show part of the routing tables on all four machines:

fir# netstat -r -n
Kernel routing table
Destination     Gateway         Genmask         Flags Metric Ref Use    Iface
<my-home-net>   0.0.0.0         255.255.255.128 U     0      0       32 eth0
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        2 eth1
10.2.0.0        0.0.0.0         255.255.0.0     U     0      0        3 eth2
10.3.0.0        0.0.0.0         255.255.0.0     U     0      0        2 ipsec0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        4 lo

ice# netstat -r -n
Kernel routing table
Destination     Gateway         Genmask         Flags Metric Ref Use    Iface
<my-home-net>   0.0.0.0         255.255.255.128 U     0      0       10 eth0
10.2.0.0        0.0.0.0         255.255.0.0     U     0      0        1 eth1
10.3.0.0        0.0.0.0         255.255.0.0     U     0      0        2 eth2
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        1 ipsec0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        1 lo

elf$ netstat -r -n
Kernel routing table
Destination     Gateway         Genmask         Flags Metric Ref Use    Iface
<my-home-net>   0.0.0.0         255.255.255.128 U     0      0       11 eth0
10.1.0.0        0.0.0.0         255.255.0.0     U     0      0        1 eth1
10.3.0.0        10.1.0.143      255.255.0.0     UG    0      0        1 eth1
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        1 lo

del$ netstat -r -n
<...>
Destination      Gateway            Flags     Refs     Use  Interface
10.1/16          10.3.0.139         UGS         0      613  ne1
10.3/16          link#1             UC          0        0  ne1
<...>

(del is a BSD machine).

3. Some of the known bugs and problems

Here is a partial list of what I consider the most urgent problems to
solve. Feel free to send bug reports, fixes (preferred!), extensions,
or even just advice. My address is ji@hol.gr. 

* The current code cannot work when the source of the original packet
is the same machine doing the encapsulations. This is a problem with
the way we (ab)use the notion of the virtual interface. There are
various quick-and-dirty kludges, but I'm still looking for a good
solution. THIS WILL HOPEFULLY GET FIXED WHEN I MOVE THE CODE TO THE 
2.1.x kernel.

* More examples need to be written on how to use the "new"
transforms. In particular, someone should write detailed instructions
on how to set up VPNs, hopefully conforming to a recent I-D,

* IP Options are not handled. TCP options are, of course, handled.

* Incoming packets, after they have been processed, should appear as
if they are arriving from the ipsec0 interface (so that, e.g.,
firewalling code has a chance of distinguishing between properly
authenticated packets that reach the input hopper, and ordinary
packets arriving from a real interface). This is not currently
working, although some hooks are already in the code.

* PMTU discovery is not explicitely supported. It may or may not work.

* The transforms supported are the ones defined in RFCs in current
I-Ds. More transforms will be added if people write I-Ds for them.

* The /proc interface needs to be cleaned up. Currently, bad things
will happen if we need to output more than 3K worth of SPIs or
e-routes. Any takers?

* Hooks are in place, but actual code has to be written to remove
unwanted SPIs and routes. I don't think there are memory leaks in
steady-state operation, but if, for example, a SAID is redifined, the
old transform data linger around. This is a problem when keys are
frequently changed and reboots don't happen often enough.

* Maybe some code should be ripped out of the user-level programs and
turned into a set of library routines so that, for example, a key
daemon may use them without invoking the programs themselves. Not a
top priority!

* I'm not being careful where I copy keys; we should be zeroizing
memory where keys have been deposited after they are no longer needed.

* The netlink interface should be expanded so that events (such as
"packet with unknown SPI arrived") may be reported to a listening
daemon so that a key exchange may be triggered. Kinda like a glorified
version of NRL's PF_KEY interface or my PF_ENCAP interface (used in
my BSDI code).

