This project has closed down, and all project members have left the University.

Linux x-kernel IPSEC

This page describes our Linux IPSEC implementation.

Getting the Software

We are distributing our complete x-kernel environment (minus the export controlled protocols) at our site. To build the x-kernel you will also need Christopher Provenzano's pthreads package. You can find both of these packages below.

You may request the export controlled sections by sending email to

Building the Software

  1. Build and install the pthreads library as per the packages README file.
  2. Build and install the x-kernel as per the instructions in the x-kernel reference manual.
  3. Build and install the ETHTAP module as per the instructions in linux/kernel/README.


This software implements IP security inside a user space x-kernel process. This is done by severing the connection between the Linux Kernel and the NIC loadable module driver, and inserting IPSEC code to secure all Ethernet frames at the IP level.

The following sections explain how this is accomplished.

Loadable Drivers

Linux provides for kernel loadable modules. The most common use for these modules is to provide for a multitude of device drivers without polluting the kernel proper. The above diagram shows a NIC driver loaded into the kernel.


The ETHTAP module is used to intercept all network traffic both to and from the lower level NIC driver. This is accomplished by a combination of overriding a few kernel functions which are exported to the NIC driver module, and overriding a few device methods used in the NIC driver module. To allow user processes access to the intercepted Ethernet frames, the module provides two pseudo-devices.

Each device has three states which are defined as follows:

Device not in use, network flow undisturbed.
All received Ethernet frames are copied and queued for subsequent reading. Network flow is undisturbed.
All received Ethernet frames are queued for subsequent reading, all written frames are transmitted to the kernel or NIC, depending on the device.

Network flow is disturbed since only frames written to /dev/htap get to the Kernel, and only frames written the /dev/ltap get to the NIC.

User Level Filtering

If the above isn't entirely clear, consider a user process which opens /dev/htap and /dev/ltap. It then sets both devices to Active mode using an ioctl. Doing so the process severs the connection between the Kernel network stack and the NIC driver. To restore the connection the process must continuously read from /dev/htap and write to /dev/ltap, and read from /dev/ltap and write the /dev/htap.

Or, in pseudo-code from:

	FILE  *htap = open("/dev/htap")
	FILE  *ltap = open("/dev/ltap")
	char   hbuf[BUFSIZE]
	char   lbuf[BUFSIZE]

	while !done {

		if read(htap, hbuf)
			write(ltap, hbuf)

		if read(ltap, lbuf)
			write(htap, lbuf)

x-kernel forwarder

The above diagram shows an x-kernel IP forwarder graph attached to the /dev/htap and /dev/ltap devices. This graph interposes itself between the Kernel network stack and the NIC driver in the same manner explained in the previous section.

To illustrate the flow of data in this diagram consider the following scenario (numbers match points on the diagram).

  1. A user process transmits data on an open TCP socket. The datas flow into the Linux Kernel via the Socket API. The Kernel passes the data through the TCP, IP, and finally Ethernet protocols.
  2. The x-kernel ETHKERN protocol reads the new Ethernet frames from /dev/htap and creates a new thread for each Ethernet frame to demutiplex each packet up the left side of the graph.
  3. The IP protocol receives TCP packets from the left side of the graph. The packets are further demultiplexed up to IPF_TCP which turns the packets around to be sent back through IP and out the right hand side of the graph.
  4. The ETHDEV protocol receives Ethernet frames from above and writes them to /dev/ltap.
  5. The NIC driver, having received new frames from the x-kernel transmits the Ethernet frames out the physical Ethernet.

There are a few things glossed over in the above scenario. First of all there are also forwarders for UDP and ICMP so TCP is not the only supported protocol. Second, the data flow from the NIC to the Kernel is exactly the reverse of the above procedure.

Lastly, there is a bit of IP and Ethernet address manipulation required to get traffic to flow from one side of the graph to the other. This manipulation takes place in the following protocols ETHKERN, ETHDEV, TCP_IPF, UDP_IPF, and ICMP_IPF. Additionally, the left hand side ARP must change to allow all IP addresses to resolve to the Ethernet address of the host machine. For more information see the source code for the mentioned protocols.

x-kernel IP security

Imagine the IP protocol in the previous diagram replaced with several protocols implenting IP security. This is exactly how we provide for transparent IPSEC over Linux.

There is no diagram for this configuration since it would be too complex, but you can see the x-kernel graph.comp file used to implement this.

name=eth/1	protocols=ethdev;
name=arp/1	dir=arp
name=eth/0	protocols=ethkern;
name=arp/0	protocols=eth/0;
name=vnet	protocols=eth/0,arp/0,eth/1,arp/1;

name=rfc1825	protocols=km/sauser,km/sauser,md5,md5,

name=ip 	dir=ip 


name=md5 	protocols=km/md5;
name=tcrypt	protocols=km/tcrypt;
name=crypt	protocols=km/crypt;
name=crypt3	protocols=km/crypt3;
name=crypt3in	protocols=km/crypt3in;

name=spiint  	protocols=ip,saidmgr;
name=saidmgr	protocols=sink,vnet,km/sauser,km/b,km/alg,km/md5,km/crypt;
name=ipf_udp 	protocols=spiint;
name=ipf_tcp 	protocols=spiint;
name=ipf_icmp 	protocols=spiint;


name=prottest		trace=TR_MAJOR_EVENTS;
name=init		trace=TR_FULL_TRACE;
name=watchdogp		trace=TR_FULL_TRACE;


romopt md5		useipsec;
romopt md5		leafmode;
romopt md5		rfc1828;
romopt crypt		useipsec;
romopt tcrypt		useipsec;
romopt km/sauser	kmparams 8 0-100 100;
romopt km/b		kmparams 4 0-100 100;
romopt km/md5		kmparams 8 16 16;
romopt km/crypt		kmparams 8 8 10;
romopt km/tcrypt	kmparams 8 8 10;
romopt km/crypt3	kmparams 8 16 10;
romopt km/crypt3in	kmparams 8 16 10;

Last modified: Sun May 9 12:18:41 MST 1999