The FreeBSD Diary

The FreeBSD Diary (TM)

Providing practical examples since 1998

If you buy from Amazon USA, please support us by using this link.
[ HOME | TOPICS | INDEX | WEB RESOURCES | BOOKS | CONTRIBUTE | SEARCH | FEEDBACK | FAQ | FORUMS ]

Things look quiet here. But I've been doing a lot of blogging at dan.langille.org because I prefer WordPress now. Not all my posts there are FreeBSD related. I am in the midst of migrating The FreeBSD Diary over to WordPress (and you can read about that here). Once the migration is completed, I'll move the FreeBSD posts into the new FreeBSD Diary website.

IPsec 27 December 2000
Share
Need more help on this topic? Click here
This article has 17 comments
Show me similar articles

This article was written by Greg Panula.

This is just my notes from setting up ipsec between two test boxes; phoenix and cardinal.

See also this ONLamp article.

The test uses both AH and ESP; packet and payload encryption.  It is a test of transport mode, i.e. direct communications between two hosts.

In order to use IPSEC, you must first add it to your kernel.  You'll need the following options:

options  IPSEC           #IP security
options  IPSEC_ESP       #IP security (crypto; define w/ IPSEC)
options  IPSEC_DEBUG     #debug for IP security

For instructions on how to create a new kernel, refer to the Configuring the FreeBSD Kernel section in the FreeBSD handbook.  Pay special attention to the section on Building and Installing a Custom Kernel.

Transport mode
Useful references:

http://www.netbsd.org/Documentation/network/ipsec/
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ipsec.html
man page for setkey

The initial test is between phoenix (10.0.1.57) and cardinal (10.1.2.45).  This test will use both AH and ESP; packet and payload encryption.  The test is using only transport mode (i.e. it is not creating a tunnel).  Phoenix and Cardinal reside on different network segments, there is a router between  them but no firewall, nat or packet filtering. 

Phoenix setup
This is the AH protocol setup:
setkey -c
add 10.0.1.57 10.1.2.45 ah 15700 -A hmac-md5 "1234567890123456";
add 10.1.2.45 10.0.1.57 ah 24500 -A hmac-md5 "1234567890123456";
^D

This sets up the AH protocol using hmac-md5 as the encryption algorithm.  hmac-md5 requires a 128bit key, which means it must be 16 characters (bytes) long. 

Breakdown of the first line:

  • 10.0.1.57 source 
  • 10.1.2.45 destination
  • AH protocol
  • 15700 SPI (unique ID#)
  • -A hmac-md5 authenication algorithm to use
  • "1234567890123456"  secretkey 

SPI tells the kernel which encryption rule and algorithm to use on  traffic tagged with that SPI

This is the ESP protocol setup:

setkey -c
add 10.0.1.57 10.1.2.45 esp 15701 -E blowfish-cbc "12345";
add 10.1.2.45 10.0.1.57 esp 24501 -E blowfish-cbc "12345";
^D

This sets up the ESP protocol using the blowfish-cbc encryption algortihm.   blowfish-cbc allows for key lengths of 40-448 bits (5 to 56 bytes).

Cardinal setup
This is the AH protocol setup:
setkey -c
add 10.0.1.57 10.1.2.45 ah 15700 -A hmac-md5 "1234567890123456";
add 10.1.2.45 10.0.1.57 ah 24500 -A hmac-md5 "1234567890123456";
^D

This is the ESP protocol setup:

setkey -c
add 10.0.1.57 10.1.2.45 esp 15701 -E blowfish-cbc "12345";
add 10.1.2.45 10.0.1.57 esp 24501 -E blowfish-cbc "12345";
^D
Using ESP
Now we will configure both machines to use AH and ESP.  We will use the level of default.  Which means the kernel consults the sysctl variable esp_trans_deflev to determine whether to encrypt or not.  This allows us to remotely setup one end (phoenix in this case) without losing connectivity.  The default value of esp_trans_deflev is 1.  After looking at /sys/netinet6/ipsec.h and then doing a quick tcpdump of the traffic between phoenix and cardinal, I have selected a value of 1, means use encryption if available.

This is the relevent section from ipsec.h:

/* Security protocol level */  
#define IPSEC_LEVEL_DEFAULT    0  /* reference to system default */
#define IPSEC_LEVEL_USE        1  /* use SA if present. */
#define IPSEC_LEVEL_REQUIRE    2  /* require SA. */
#define IPSEC_LEVEL_UNIQUE     3  /* unique SA. */

Cardinal

setkey -c  
spdadd 10.1.2.45 10.0.1.57 any -P out ipsec
           esp/transport/10.1.2.45-10.0.1.57/default
           ah/transport/10.1.2.45-10.0.1.57/default;

Phoenix 

setkey -c
spdadd 10.0.1.57 10.1.2.45 any -P out ipsec
           esp/transport/10.0.1.57-10.1.2.45/default
           ah/transport/10.0.1.57-10.1.2.45/default;

Note: the above spdadd line is one line and it encrypts all traffic (the `any' before the -P).  Check the setkey man page for info on how to encrypt certain packets, e.g. rsh.

I'm only encrypting outbound traffic. And the format for the spdadd line is: spdadd <src> <dst> <upperspec> <policy>

<upperspec> is upper layer protocol; tcp, udp or any are the options

<policy> is one of the following:
-P direction discard
-P direction none
-P direction ipsec protocol/mode/src-dst/level

What's it look like?
A tcpdump of the traffic between phoenix and cardinal shows this:

14:15:30.919115 cardinal.foo.bar > phoenix.foo.bar: AH(spi=24500,seq=0x2ac): ESP(spi=24501,seq=0x59e) (DF) 
14:15:30.924053 phoenix.foo.bar > cardinal.foo.bar: AH(spi=15700,seq=0x38): ESP(spi=15701,seq=0x198) (DF) 
14:15:31.002687 cardinal.foo.bar > phoenix.foo.bar: AH(spi=24500,seq=0x2ad): ESP(spi=24501,seq=0x59f) (DF) 
14:15:31.007360 phoenix.foo.bar > cardinal.foo.bar: AH(spi=15700,seq=0x39): ESP(spi=15701,seq=0x199) (DF) 
14:15:31.098242 cardinal.foo.bar > phoenix.foo.bar: AH(spi=24500,seq=0x2ae): ESP(spi=24501,seq=0x5a0) (DF) 
14:15:32.826557 cardinal.foo.bar > phoenix.foo.bar: AH(spi=24500,seq=0x2af): ESP(spi=24501,seq=0x5a1) (DF) 
14:15:32.832951 phoenix.foo.bar > cardinal.foo.bar: AH(spi=15700,seq=0x3a): ESP(spi=15701,seq=0x19a) (DF) 

Setting the keys at boot time
One thing learned afterwards was the kernel loses the keys after a reboot.   There is a mechanism built into /etc/rc.conf which set the keys for you at boot time.  Note: do not modify /etc/defaults/rc.conf, make the changes to /etc/rc.conf instead.

$ grep -i IPSEC /etc/defaults/rc.conf
ipsec_enable="NO"      # Set to YES to run setkey on ipsec_file
ipsec_file="/etc/ipsec.conf"   # Name of config file for setkey

If you put your setkey commands into /etc/ipsec.conf, and set ipsec_enable to true, your keys will be set for you at system startup.  My thanks to Michael C. Cambria for pointing this out to me.

Share
Need more help on this topic? Click here
This article has 17 comments
Show me similar articles