Implementation of IPSEC-NAT compatibility with UDP encapsulation of IPSEC packets

EECS 801 - Directed Graduate Reading
Divya Mukundan (divi@ku.edu)
Muthuvelan KP  (kpm@ku.edu)
Directed by Dr. Joseph B. Evans
Department of Electrical Engineering and Computer Science
The University of Kansas
Lawrence, KS 66045

Fall 2001 

Download code.
See Real Video (80 kbps, 56 kbps).
See PPT slides.

Table of Contents

  1. Proposal
  2. Schedule
  3. Introduction
  4. The Problem
  5. Implementer's Thoughts
  6. Installation
  7. Test Setup & Configuring IPSEC
  8. Test Plan & Test Tools
  9. Implementation Details
  10. Test Cases & Results
  11. References

1. Proposal

The aim of the project is to provide an implementation of IPsec that can address some of the compatibility issues documented in IPsec-NAT Compatibility Requirements. This involves implementing the changes required in two phases. Our project undertakes Phase-1 of this effort. During Phase-1, we will implement the encapsulation and decapsulation of ESP and AH packets in UDP to traverse NAT. NAT Keepalive packets will also be implemented. Phase-2 will add more functionality to our implementation. The functionality will include detection of NAT between IPsec hosts, detection of NAT traversal support in IKE at both ends and negotiation of UDP encapsulation for IPsec packets through IKE. We will use the IPsec and IKE implementation provided by FreeS/wan (Linux kernel 2.4.5) to make the changes that will accommodate NAT. The specifications for Phase-1 are documented in "UDP Encapsulation of IPsec Packets <draft-ietf-ipsec-udp-encaps-00.txt>"

 


2. Schedule

September 1 - September 30 Reading NAT, AH, ESP, IKE, IETF IPsec-NAT drafts
September 1 - September 30 Installation and testing of FreeS/wan IPsec system on Linux machines
October 1 - October 15 Understanding FreeS/wan KLIPS implementation
October 16 - October 30 Design of IPsec-NAT functionality changes
October 31 - November 30 Implementation of Phase-1
December 1 - December 15 Phase-1 Testing & Troubleshooting
December 16 - December 17 Preparation of project website and presentation



3. Introduction

 

IPSEC is a solution to make Virtual Private Networks (VPN) possible. It provides security services such as data origin authentication, integrity, confidentiality (encryption) at the IP layer. IPSEC allows hosts/gateways to select the security protocols and algorithms they want to use and also provide a mechanism to exchange cryptographics the authentication/encryption algorithms may need. IPSEC can be setup to provide security services for traffic passing between host-host, gateway-gateway, host-gateway.

Figure-1 - Host-Host

Figure-2 - Gateway - Gateway

Figure-3 - Host - Gateway

The following are the security protocols used in IPSEC.

Authentication Header (AH)

AH provides integrity, authentication and anti-replay services. It protects the upper layer data as well as certain portions of the IP header, extension headers and options. See AH encapsulation below.
Figure-4 shows the location of the AH header (transport mode) in an IP packet.

Figure-4

Figure-5 shows the location of the AH header (tunnel mode) in an IP packet.

Figure-5

Encapsulating Security Payload (ESP)

ESP provides confidentiality in addition to the services provided by AH and is the preferred protocol. However, ESP only protects the payload portion of the IP packet. Figure-6 and Figure-7 show the location of the ESP header in transport and tunnel mode respectively.

Figure-6

Figure-7

Internet Key Exchange (IKE)

The security protocols need cryptographic keys in place to serve as input to the algorithms they may use. The keys can be setup between the machines using either manual or automatic key distribution. IKE provides automatic key management functionality.

Security Association (SA)

A security association is a one-way connection between two machines that specifies the services that are applied to the traffic flowing between those machines. The SA specifies the protocol used (can be either AH or ESP but not both). For example, in Figure-1, if the end hosts require ESP to protect the traffic between them, we would need to establish two SAs, one on each host.  If both AH and ESP are required to protect the traffic, then we need to establish two SAs on each host, one for AH and the other for ESP. An SA is identified by the Security Parameter Index (SPI), IP destination address and the security protocol.

The SA also specifies the mode - transport or tunnel mode. A transport mode SA is setup between two hosts whereas a tunnel mode SA is an SA applied to an IP tunnel. The following table lists the basic combinations of SAs that can be setup on hosts/gateways.

For the setup shown in Figure-1, any one of the following SAs could be used.
 

Transport Mode [IP1] [AH] [upper]
- [IP1] [ESP] [upper]
- [IP1] [AH] [ESP] [upper]
Tunnel Mode [IP2] [AH] [IP1] [upper]
- [IP2] [ESP] [IP1] [upper]
Table-1

For the setup in Figure-2, any one of the following SAs could be used.
 

No Transport Mode  -
Tunnel Mode [IP2] [ESP] [IP1] [upper]
- [IP2] [AH] [IP1] [upper]
Table-2

For the setup in Figure-3, only a tunnel mode SA can be setup between the host-gateway. See Table-2.
Read Security Architecture for the Internet Protocol.

 

NAT provides a simple, economic solution to the problem of tight IPv4 address space. All the computers in a small sized network could be provided access to the Internet without investing in a whole lot of globally registered IP addresses. IPSEC, on the other hand, is the standard solution for VPN. If the network above needed secure access to its main network across the Internet, IPSEC would be its choice. See Figure-4.

Figure-4


4. The Problem

However, NAT and IPSEC do not function well together due to known incompatibilities. Some of the incompatibilities are listed below. The draft "UDP Encapsulation of IPSec Packets" specifies the changes required that would address these incompatibilities.

One of the main services provided by IPSEC is message integrity. But, NAT modifies the IP header of outgoing packets. Here, lies the problem.

Apart from the problems discussed above, IKE and NAT have their share of incompatibilities as well. These are addressed in "IPsec-NAT Compatibility Requirements".

 


5. Implementer's Thoughts

AH calculates the Authentication Data or Integrity Check Value (ICV) using IP source and destination addresses (See 3.3.3.1.1 in RFC 2402). With NAT changing these fields on the way, the ICV would be invalidated. ESP does not suffer from this problem while calculating the ICV as it computes this over the ESP packet minus the Authentication Data (See 2.7 in RFC 2406).

2. TCP/UDP Checksums and NAT

TCP/UDP checksums are based on the pseudo-header. "The pseudo  header  conceptually prefixed to the UDP header contains the source  address,  the destination  address,  the protocol,  and the  UDP length.": Source RFC 768. These checksums are recalculated by the NAT device. This will however invalidate the ESP Authentication Data as the packet has been altered en route.
  1. IKE must not generate packets with the Initiator Cookie field set to all zeroes.
  2. IKE must not generate ESP SPIs that are all zero.
  3. UDP encapsulation of ESP header (See 2.1 in draft-ietf-ipsec-udp-encaps-00.txt).
  4. UDP encapsulation of AH header (See 2.2 in draft-ietf-ipsec-udp-encaps-00.txt).
  5. Sending NAT keepalive packets (See 2.3 and 4 in draft-ietf-ipsec-udp-encaps-00.txt). The reciver should ignore this packet.
  6. The source and destination ports of the UDP header (just added) should be the same as used by the IKE traffic.

 


6. Installation

The installation of FreeS/wan consists of two parts.

Installation of a new kernel

The linux kernel 2.4.5 can be downloaded and should be extracted into the /usr/src directory (after renaming the already existing linux directory, ofcourse). Then the following commands are executed. The configuration chosen while executing 'menuconfig' should be the defaults.
make menuconfig
make dep
make clean
make bzImage
All the above commands should be executed with super user privileges. The new kernel image is copied to a different location.
cp /usr/src/linux/arch/i386/boot/bzImage /kernels/kpm/bzImage-2.4.5


The file /etc/lilo.conf is updated as below and lilo command is executed before rebooting the system.

image=/kernels/kpm/bzImage-2.4.5
    label=linux-2.4.5
    root=/dev/sda1
    read-only


The above procedure is done on testbed30 & testbed35 on which IPSEC needs to be installed. The machines are rebooted with the new kernel as below.

lilo -R linux-2.4.5
reboot


Before applying the freeswan patch, the machines should be tested to see if the existing or newly installed kernel functions properly. This would help in detecting problems, which may occur later.

Application of FreeS/wan patch

Freeswan should be extracted into the /usr/src directory. The following two commands are executed in the freeswan-1.91 directory.
make menugo
make kinstall


The new kernel is copied to an appropriate location.

cp /usr/src/linux/arch/i386/boot/bzImage /kernels/kpm/bzImage-ipsec-2.4.5


The file /etc/lilo.conf is updated as below the lilo command is executed.

image=/kernels/kpm/bzImage-ipsec-2.4.5
        label=linux-ipsec
        root=/dev/sda1
        read-only


The two machines are rebooted with the ipsec enabled kernel.

lilo -R linux-ipsec-2.4.5 // reboot with the new kernel
reboot


We can verify the installation of ipsec by looking at dmesg or by executing ipsec. The output of dmesg should show you the following. klips_info:ipsec_init: KLIPS startup, FreeS/WAN IPSec version: 1.91.

 


7. Test Setup & Configuring IPSEC

Test Setup
Testing the Installation

Test Setup

Logical Topology

 

Physical Topology

 

Testing the Installation

Configuration

Turn on IP forwarding on all the machines. Add route information on the IPsec test machines so that packets sent between them are sent via the NAT gateway.

testbed30:

route add -host 129.237.127.235 gw 129.237.125.242
echo "1" > /proc/sys/net/ipv4/ip_forward
testbed35:
route add -host 129.237.126.205 gw 129.237.125.242
echo "1" > /proc/sys/net/ipv4/ip_forward
testbed21:
echo "1" > /proc/sys/net/ipv4/ip_forward
The above configuration can be tested by running traceroute on the two IPsec machines.

testbed30:

traceroute testbed35
traceroute to testbed35.ittc.ku.edu (129.237.127.235), 30 hops max, 40 byte packets
 1  testbed21 (129.237.125.242)  0.584 ms  0.300 ms  0.328 ms
 2  testbed35 (129.237.127.235)  0.678 ms  0.827 ms  0.729 ms
testbed35:
traceroute testbed30
traceroute to testbed30.ittc.ku.edu (129.237.126.205), 30 hops max, 38 byte packets
 1  testbed21 (129.237.125.242)  0.558 ms  0.389 ms  0.372 ms
 2  testbed30 (129.237.126.205)  2.353 ms  0.961 ms  0.773 ms
The FreeS/WAN IPsec subsystem and VPN connection configuration is added to /etc/ipsec.conf and /etc/ipsec.secrets.
See an example configuration for manual connection - ipsec.conf , an example for automatic connection ipsec.conf and ipsec.secrets for testbed30.
See an example configuration for manual connection - ipsec.conf , an example for automatic connection ipsec.conf and ipsec.secrets for testbed35.

Authentication in PLUTO can be done using RSA or by using shared keys.

Generating RSA keys

The RSA private/public key pair can be generated on the testbeds using the following command. The output from the command is added to ipsec.conf and ipsec.secrets.

testbed35:

ipsec rsasigkey --verbose 2048 >testbed35
getting 32 random bytes from /dev/random...
looking for a prime starting there (can take a while)...
found it after 29 tries.
getting 32 random bytes from /dev/random...
looking for a prime starting there (can take a while)...
found it after 283 tries.
swapping primes so p is the larger...
computing modulus...
computing lcm(p-1, q-1)...
computing d...
computing exp1, exp1, coeff...
output...
# RSA 512 bits   testbed35.ittc.ku.edu   Wed Oct 31 23:42:32 2001
# for signatures only, UNSAFE FOR ENCRYPTION
#pubkey=0sAQOTMVGj6lWAzyKAqo4rzx6hfoFndgCZDtxNfuwB8UM7m5PsNj/O/uURitPT2P2nPg8pZE6sCNfKTSu1NHQ+QT1X
#IN KEY 0x4200 4 1 AQOTMVGj6lWAzyKAqo4rzx6hfoFndgCZDtxNfuwB8UM7m5PsNj/O/uURitPT2P2nPg8pZE6sCNfKTSu1NHQ+QT1X
# (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
Modulus: 0x933151a3ea5580cf2280aa8e2bcf1ea17e81677600990edc4d7eec01f1433b9b93ec363fcefee5118ad3d3d8fda73e0f29644eac08d7ca4d2bb534743e413d57
PublicExponent: 0x03
# everything after this point is secret
PrivateExponent: 0x18883845fc639577db1571c25ca2851aea6ae693aac42d24b7952755a835df4455840cb066fdb14cb58ce7f01a0161faeaa63ad6304b6caeab05866cc1ae0997
Prime1: 0xff233af68837b83ec0ca03e6eb8c274a200310036e2dc9f3d28372b0cdd65a95
Prime2: 0x93b0af26dcd5050688bc60517612cae3897bdda378e5744157109b36e656a93b
Exponent1: 0xaa177ca45acfd029d5dc0299f25d6f86c0020aacf41e86a28c57a1cb33e43c63
Exponent2: 0x6275ca19e88e0359b07d958ba40c87425ba7e917a5ee4d80e4b5bccf4439c627
Coefficient: 0x126315ef4c52b834fa12c0bea11225737778ed9c81583ce2af7f6efff1391151
testbed30:
ipsec rsasigkey --verbose 2048 >testbed30
getting 32 random bytes from /dev/random...
looking for a prime starting there (can take a while)...
found it after 106 tries.
getting 32 random bytes from /dev/random...
looking for a prime starting there (can take a while)...
found it after 70 tries.
computing modulus...
computing lcm(p-1, q-1)...
computing d...
computing exp1, exp1, coeff...
output...
# RSA 512 bits   testbed30.ittc.ku.edu   Wed Oct 31 23:43:55 2001
# for signatures only, UNSAFE FOR ENCRYPTION
#pubkey=0sAQPgjVKjzmVFznS0TxEiUzfVVXxvKQyPOtl4p170s6q8/w/4YDemf879IVpqdiSltby73FsDp21bZ9ReVPxM0O7V
#IN KEY 0x4200 4 1 AQPgjVKjzmVFznS0TxEiUzfVVXxvKQyPOtl4p170s6q8/w/4YDemf879IVpqdiSltby73FsDp21bZ9ReVPxM0O7V
# (0x4200 = auth-only host-level, 4 = IPSec, 1 = RSA)
Modulus: 0xe08d52a3ce6545ce74b44f11225337d5557c6f290c8f3ad978a75ef4b3aabcff0ff86037a67fcefd215a6a7624a5b5bcbbdc5b03a76d5b67d45e54fc4cd0eed5
PublicExponent: 0x03
 # everything after this point is secret
 PrivateExponent: 0x256ce31b4d10e0f7be1e0d2d85b8894e38ea1286d76d3479941be528c89c74d4dd686a8126e399f41482c6ac583429c443180e184aa372c67c06a9a0d348b39d
 Prime1: 0xf041f9e5e59e4450923e233aadfd018ed090dfe761b35ea45c33e1b02e31bb2b
 Prime2: 0xef43e74ad78beef4140b9f31656fb99458bb268a85e54c1c900279872aeafdff
 Exponent1: 0xa02bfbee99142d8b0c296cd1c953565f35b5ea9a41223f183d77ebcac9767cc7
 Exponent2: 0x9f829a31e507f4a2b807bf76439fd10d907cc45c594388130aac5104c74753ff
 Coefficient: 0x077d3d4c716febdb39125cb4b61028c9cb1f02c9615efd37817f4b0c6c8ce3b8

Generating shared secret keys

Pre-shared secret keys can be used to authenticate PLUTO in IPSEC. The keys can be generated using the following command.
ipsec ranbits --bytes 25
0x187da44c_0e64589f_1696470f_b2dc6476_51dc8853_5cb052c5_e1

The output should be added to ipsec.secrets at both IPSEC endpoints as shown below.
: PSK "0x187da44c_0e64589f_1696470f_b2dc6476_51dc8853_5cb052c5_e1"

Testing the IPSEC installation and sample connection

Boot the test machines once the .conf and .secrets files are ready. Check /proc/net/ipsec_tncfg file to verify that the ipsec interface has been setup. It should look like this.
ipsec0 -> eth0 mtu=16260(1500) -> 1500
ipsec1 -> NULL mtu=0(0) -> 0
ipsec2 -> NULL mtu=0(0) -> 0
ipsec3 -> NULL mtu=0(0) -> 0
 

If you don't see an IPsec interface associated with a physical interface, execute the 'ipsec tncfg' command.
ipsec tncfg --attach --virtual ipsec0 --physical eth0

Testing traffic before setting up an IPsec connection

The following can be used to test the traffic between testbed30 and testbed35.

testbed35:

ping -p feedfacedeadbeef testbed30

testbed21:
tcpdump -i eth0 -x -v dst host testbed30
00:45:20.757888 < testbed35.ittc.ku.edu > testbed30.ittc.ku.edu: icmp: echo request (DF) (ttl 64, id 0)
                         4500 0054 0000 4000 4001 3816 81ed 7feb
                         81ed 7ecd 0800 9d12 db27 2d00 80d8 e83b
                         5291 0b00 face feed dead beef face feed
                         dead beef face feed dead beef face feed
                         dead beef face feed dead beef face feed
                         dead beef

Starting IPSEC (KLIPS and PLUTO)

Below is a list of ipsec commands, sample output and its usage.

To start KLIPS and PLUTO on a testbed, use the following.

ipsec setup --start
ipsec setup: Starting FreeS/WAN IPsec 1.91...


To check the status of IPsec, use...

ipsec setup --status
IPsec running
pluto pid 10670

To check the status of a PLUTO, use...
ipsec whack --status
000 interface ipsec0/eth0 129.237.126.205
000
000 "host-host": 129.237.126.205---129.237.125.242...129.237.125.242---129.237.127.235
000 "host-host":   ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0
000 "host-host":   policy: RSASIG+ENCRYPT+PFS; interface: eth0; unrouted
000 "host-host":   newest ISAKMP SA: #0; newest IPsec SA: #0; eroute owner: #0
000


To listen on port 500 for IKE messages, use...

ipsec whack --listen
002 listening for IKE messages
002 forgetting secrets
002 loading secrets from "/etc/ipsec.secrets"


To start a connection using automatic keying, use...

ipsec auto --up host-host

(where host-host identifies the connection to be started)
104 "host-host" #1: STATE_MAIN_I1: initiate
106 "host-host" #1: STATE_MAIN_I2: from STATE_MAIN_I1; sent MI2, expecting MR2
108 "host-host" #1: STATE_MAIN_I3: from STATE_MAIN_I2; sent MI3, expecting MR3
004 "host-host" #1: STATE_MAIN_I4: ISAKMP SA established
112 "host-host" #2: STATE_QUICK_I1: initiate
004 "host-host" #2: STATE_QUICK_I2: sent QI2, IPsec SA established


To check the status of the connection, use...

ipsec whack --status
000 interface ipsec0/eth0 129.237.126.205
000
000 "host-host": 129.237.126.205---129.237.125.242...129.237.125.242---129.237.127.235
000 "host-host":   ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0
000 "host-host":   policy: RSASIG+ENCRYPT+PFS; interface: eth0; erouted
000 "host-host":   newest ISAKMP SA: #1; newest IPsec SA: #2; eroute owner: #2
000
000 #2: "host-host" STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 28038s; newest IPSEC; eroute owner
000 #2: "host-host" esp.9ff11fca@129.237.127.235 esp.47503eed@129.237.126.205
000 #1: "host-host" STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 2588s; newest ISAKMP


To stop both KLIPS and PLUTO on a testbed, use...

ipsec setup --stop
ipsec setup: Stopping FreeS/WAN IPsec...

 
ipsec status --status
IPsec stopped

 
ipsec auto --down host-host

Remember that the aboce command should be executed on both end-points.

For manual keying,

ipsec manual --up host-host
ipsec manual --down host-host

Testing traffic after setting up an IPsec connection

 

8. Test Plan & Test Tools

Test Plan

Basic Testing

To test the new implementation, we need to do the following.
  1. Testing outgoing IPsec packets
  2. Testing packet reception and processing
  3. Testing NAT keep alives.

Testing with NAT

To test whether the new implementation solves the incompabitibilities between NAT and the IPSEC security protocols (AH/ESP), we need to configure NAT between the testbeds that implement IPSEC. See test setup. We need to configure manual key distribution in IPSEC because IKE and NAT still have their differences which is not addressed in this implementation. See Figure-7.


Figure-7

 

Test Tools

The following test tools were used to aid the testing & debugging process.
  1. PING Program

 


9. Implementation Details

The following files in FreeS/wan were modified to make KLIPS conform to the specifications in UDP Encapsulation of IPsec Packets.
 
Config.in ipsec_rcv.c
ipsec_tunnel.c ipsec_netlink.c
ipsec_ah.h ipsec_xform.c
ipsec_esp.h pfkey_v2_parser.c
ipsec_init.c  

 

Introduction to FreeS/WAN

FreeS/WAN is a Linux implementation of the IPSEC (IP security) protocols. Their implementation consists of three parts.
  1. KLIPS (kernel IPSEC) implements AH, ESP, and packet handling within the kernel.
  2. Pluto (an IKE daemon) implements IKE, negotiating connections with other systems.
  3. Various scripts that provide an administrative interface to the IPsec.
The IPSEC layer is implemented as a virtual device. KLIPS defines four device structures dev_ipsec0, dev_ipsec1, dev_ipsec2, dev_ipsec3. The command IPSEC_TNCFG is used to attach one of these virtual devices to a physical device on the machine. For example,
ipsec tncfg --attach --ipsec0 --eth0
The ipsec devices register themselves with the linux kernel in the ipsec_init() function. The following functions are called to perform device registration - register_netdevice_notifier, register_netdev. The security protocols ESP, AH also register with INET in the ipsec_init() function by calling inet_add_protocol(). Device and protocol registration enables the IPsec system to receive packets from the kernel.

The data structure central to IPsec is struct tdb (tunnel descriptor block). This structure contains all the details about a Security Association. KLIPS maintains a hash table of such structures called tdbh. When a transport or tunnel mode connection is setup (either manually or automatically by IKE), the SAs negotiated are added to the tdbh. The combination of SPI, security protocol and destination IP address serves as the hash value to find the tunnel descriptor structure in tdbh. For example, when a transport mode connection with ESP SA is setup, we have the following list in the tunnel descriptor hash.

Figure-10 

When a tunnel mode connection with ESP SA is setup, we have the following list in the tunnel descriptor hash.

Figure-11 

Figure-9 explains the flow of outgoing packets through the kernel. Suppose that an ICMP packet needs to be transmitted.

Figure-9

Figure-12 shows the flow of incoming packets through the kernel.

Figure-12

 

Implementation

The following were the basic changes.
  1. Encapsulation of IPsec packets in UDP header.
  1. De-encapsulation of UDP header before IPsec processing.
Figure-13 
  1. Transmission of NAT keep-alive packets between every pair of IKE peers.

 


10. Test Cases & Results

This page documents the test cases executed to verify the behavior of the original (version 1.91) and our new (version EECS801) FreeS/wan implementation.
Browse: [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14]

1. Testing packet transmission (on testbed35 - version 1.91) to observe outgoing IPsec packets.

Testing transport mode ESP connection. See configuration file.

11. References

  1. Dixon. W , "IPSec over NAT Justification for UDP Encapsulation", June 2001.
  2. Kivinen. T, "Negotiation of NAT-Traversal in the IKE", June 2001.
  3. Huttunen. A, "UDP Encapsulation of IPsec Packets", June 2001.
  4. Bernard Aboba, "IPsec-NAT Compatibility Requirements", June 2001.
  5. Kent. S, "Security Architecture for the Internet Protocol", November 1998.
  6. Kent. S, "IP Encapsulating Security Payload (ESP)", November 1998.
  7. Kent. S, "IP Authentication Header", November 1998.
  8. Glenn Herrin, "Linux IP Networking", A Guide to the Implementation and Modification of the Linux Protocol Stack, May 2000.