free web hit counter visitors since Apr 24,2005
How to easily build a VPN with KAME IPSec (Kernel 2.6)
by Cristiano da Cunha Duarte (cunha17@gmail.com)
homepage at http://cunha17.cristianoduarte.pro.br

Page created:  Jan 04, 2005
Page last modified: Nov 12, 2005
The most up-to-date version of this page can be found at http://cunha17.cristianoduarte.pro.br/ipsec/index.en_us.html

You may ask: "Look, nice job, but I don't want to learn IPSec basics and don't want to understand what I'll be doing, just a really easy IPSec(so no IKE) between two Linux machines!" and I will answer "Take any of the examples at the Apendix A! For encryption security take the ESP ones... ;)"

Introduction

This tutorial aims at showing how easy it is to build a VPN between machines using the KAME IPSec standard available in Linux kernel 2.6.
At the topic "Building your VPN step-by-step" it will be shown how to build a VPN (tunnel mode) between gateways using KAME IPSec,  Racoon and a Shared Key(or Shared Secret).
This tutorial is implemented on a VPN between one machine running Linux
Debian "testing" (sarge) and another machine running FreeBSD with Aker Firewall 5.0.(The process would be the same if the machine is running "pure Linux" like Debian, Fedora Core, etc.)
Successful tests were made between two hosts running Fedora Core 2. On these tests, streams in tunnel and transport mode were created, but no IKE(racoon) tests were made, so fixed keys were used. The scripts that create the all flavors of IPSec streams are available at  Apendix A.

Purpose

IPSec can operate in two modes:

Tunnel mode: in which the main purpose is to build a secure communication between remote networks over a non-secure channel. For instance:
Network1 comm1
Gateway1
tunnel1connection1tunnel1
tunnel2connection2tunnel2
Internet
tunnel1connection1tunnel1
tunnel2connection2tunnel2
Gateway2 comm2
Network2
Net1
Gw1
IPSec Channels
Internet
IPSec Channels
Gw2
Net2
IPSec in tunnel mode between gateways Gw1 and Gw2

Transport mode: in which the main purspose is to build a end-to-end secure comunication, between two hosts, over a non-secure channel. For instance:

tunnel1connection1tunnel1
tunnel2connection2tunnel2
Conexão Dial-up
tunnel1connection1tunnel1
tunnel2connection2tunnel2
Internet tunnel1connection1tunnel1
tunnel2connection2tunnel2
Servidor
Client
IPSec Channels
Dial-up
IPSec Channels
Internet
IPSec Channels
Server
IPSec in transport mode between hosts Client and Server

Note: Usually VPNs are built in tunnel mode.


Building your VPN step-by-step

The necessary steps needed to establish a VPN in tunnel mode between Net1(10.67.112.0) and Net2(10.0.0.0) using the racoon IKE daemon will be described. The gateways will be connected over the internet, where Gateway1 IP Addres is 100.100.100.100 and Gateway2 IP Address is 200.200.200.200.

Step 1: Installation of the necessary packages


# apt-get install ntpdate ntp-server

# apt-get install ipsec-tools racoon iproute iptables kernel-image-2.6
Note1: during racoon installation, choose the option to NOT use racoon-tool. You will configure racoon manually.
Note2: if the current installed kernel is version 2.4.x or earlier, a reboot is necessary before going any further.

# apt-get install dnsutils lynx tcpdump

Step 2: Policy configuration
  IPSec is made by two distinct databases:
    Policies tell IPSec when it should or shouldn't act over an IP packet.
Keyword: WHEN
    A Security Policy(SP) is made, basically, by the following aspects:
Note: if a SA is not available, the kernel requests a SA negotiation to the IKE daemon (racoon)
    Associations tell IPSec how it should create a channel between two hosts.
Keyword: HOW
    A Security Association(SA) is made, basically, by the following aspects:

ATTENTION:  a SA can only be used if it's "associated"  with a policy, this association can only be established if there is a policy which rule has the same parameters as the SA.

NOTE: There may exist a functional SP without a SA in two ways:
  • When the SP has the none or discard type, where there is no SA to be used since IPSec will not be applied
  • When the SA is created dinamically by the IKE daemon(racoon)
In any other way, a SP without a SA queues the packet until it gets discarded.

To setup the SPD and/or the SAD, we use setkey. This application can act as a shell script processor(much like bash). Example:

#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

The code above can be saved on a file named ipsec-off, with permission mode rwx to root. When ./ipsec-off is executed, all rules existing at the SAD(AH and ESP) and SPD will be removed.
Since we are going to use racoon to create our SAD entries, we just need to create our SPD policies. So, the ipsec-on file will be:

#!/sbin/setkey -f
flush;
spdflush;

#NET1 to NET2
spdadd 10.67.112.0/22[any] 10.0.0.0/8[any] any -P in ipsec esp/tunnel/100.100.100.100-200.200.200.200/require;
#NET2 to NET1
spdadd 10.0.0.0/8[any] 10.67.112.0/22[any] any -P out ipsec esp/tunnel/200.200.200.200-100.100.100.100/require;

Note: "flush;" has the same effect of "flush ah;" followed by "flush esp;"

Step 3: Configuring Racoon
Before going into racoon configuration, we need to make some change to the racoon loader script. Edit the /etc/init.d/racoon script and make the following change:
start-stop-daemon --start --quiet --exec /usr/sbin/racoon
to:
start-stop-daemon --start --quiet --exec /usr/sbin/racoon -- -l /var/log/racoon.log
With this modification, we put any log information into the file /var/log/racoon.log.

Now, racoon will be configured to use a shared secret for the initial authentication between the gateways. This is how the  /etc/racoon/racoon.conf file must look like:

path pre_shared_key "/etc/racoon/psk.txt";
log debug2;

listen {
        isakmp 200.200.200.200 [500];
        strict_address;
}

remote 100.100.100.100 {
        exchange_mode main;
        send_cr off;
        send_cert off;
        proposal {
                encryption_algorithm blowfish;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group 2;
                lifetime time 300 seconds;
        }
}

Line 1 tells the location of the file where the shared secret can be found. This file has the same format as the /etc/hosts file, two columns separated by spaces/tabs, where the first column is the gateway IP address and the second column, the shared secret of this gateway.  Then the /etc/racoon/psk.txt file will be:

200.200.200.200    1234567890

100.100.100.100    1234567890
 
Line 2 configured racoon log to debug2(afterwards you can put another level here, like notify) which makes racoon generate tons of log info.

The listen clause tells racoon at which IP and port it should wait for IKE requests. In this example, the address used is 200.200.200.200 and the port 500/udp, that is the standard IPSec IKE port. The strict_address entry forces racoon to abort if it can't listen at this IP and port.

Now the remote clause. It starts with the remote gateway IP and has the following clauses:

Step 4: Firewall rules setup
IPSec in tunnel mode uses protocol number 50 (ESP) to encrypt IP packet data.
Attention: is protocol number 50 and not port 50!!!
Racoon uses port 500/udp to exchange keys(IKE) between the gateways.

Just add these linhas to your iptables rule file:

#configure kernel parameters
echo 0 > /proc/sys/net/ipv4/ip_dynaddr
echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
echo 1 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/all/log_martians
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
echo 0 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
#accept ESP packets
iptables -I INPUT 1 -j ACCEPT -p 50

iptables -I OUTPUT 1 -j ACCEPT -p 50
iptables -I FORWARD 1 -j ACCEPT -p 50
#accept IKE packets
iptables -I INPUT 1 -j ACCEPT -p udp --dport 500
iptables -I OUTPUT 1 -j ACCEPT -p udp --dport 500
iptables -I FORWARD 1 -j ACCEPT -p udp --dport 500
#accept ICMP packets
iptables -I INPUT 1 -j ACCEPT -p icmp
iptables -I OUTPUT 1 -j ACCEPT -p icmp
iptables -I FORWARD 1 -j ACCEPT -p icmp

ATTENTION: if you want to create more restrictive rules(and you should), just add the source and destination address of the gateways to the rules above. Don't forget that those address are Internet(or non-secure) source and destination address of the gateways.

CAREFUL: the kernel parameter /proc/sys/net/ipv4/conf/all/rp_filter blocks for IP spoofing and, as it is now disabled, the cheking must be done by your own IPTABLES rules! However these rules must appear after the ones above.

IMPORTANT NOTE 1: The IP header of an ESP packet cannot be modified by NAT, so we cannot do NAT with a IPSec channel(at least directly, NATT exists for this matter): there must not be any NAT between the Gateways. If you use NAT at your firewall, add the following rules before any other to tell iptables to not do NAT with the packets flowing in the VPN:
#We don't do NAT for ESP
iptables -t nat -I PREROUTING 1 -j ACCEPT -p 50

iptables -t nat -I POSTROUTING 1 -j ACCEPT -p 50

IMPORTANT NOTE 2: There must not exist NAT between the networks connected by the tunnel if they are mutually routeable. It is not necessary that the internal address be valid, neither are the creation of static routes: IPSec handles the routing of the packets to the remote gateway every time that the destination address is within the remote network range. Ex:
Network1 comm1
Gateway1
tunnel1connection1tunnel1
tunnel2connection2tunnel2
Internet
tunnel1connection1tunnel1
tunnel2connection2tunnel2
Gateway2 comm2
Network2
Net 10.1.0.0
G1
INTERNET
G2
Net 10.0.0.0
If a packet is sent by "Network 10.1.0.0" to network "10.0.0.0", the gateway "G1" sends this packet to the gateway "G2". Since the gateway "G2" has the network "10.0.0.0" DIRECTLY connected to it(by one of its network interfaces), it routes the packet to this network. If the network is not directly connected, you will need to create static routes.

Step 5:  Starting the VPN
Execute your iptables loading script(with the step 4 rules added).
Execute the ipsec-on script.
Execute racoon (/etc/init.d/racoon restart).

The VPN is not established yet, we need a packet to flow trough the firewal so that racoon can negotiate a SA. Now it's time to execute:
# ping 100.100.100.100
or
# ping 200.200.200.200
as the case.
The first answer may delay many seconds, since the tunnel needs to be established first.

Step 6:  Testing the VPN
If ping works, it's time to test loading a Web page. So, type lynx followed by the address of a web page hosted at the remote network.
If the web page open, and if it's possible to navigate on the links, then it's time to test in graphics mode with the good and old Mozilla. If you can open the remote web pages inside Mozilla, with all images and text, your VPN is working ! Congratulations !
Otherwise if any kind of problem happens, check the racoon log file(/var/log/racoon.log), the kernel log file(/var/log/kern.log) and go to the Troubleshooting section.

NOTE: This tutorial assumes that at the other end an Aker Firewall is correctly configured. If you wish to use a host with Linux and kernel 2.6 as Gateway2, perform the same steps above with this second machine, just replacing in with out and vice versa at step 2 and the remote address at step 3.

Troubleshooting
  1. I can only "ping" the other gateway
    1. If you can ping the remote gateway internet address, but can't ping this gateway local network(internal)  address, probably:
      1. The VPN wasn't established
Verify racoon's log at /var/log/racoon.log and look for problems. If the remote firewall doesn't have a rule that let ESP and IKE packets pass, the VPN won't be established.
      1. The remote gateway has a firewall blocking your "pings"
At the remote gateway: verify the firewall's log and run TCPDUMP to see if the ICMP ECHO REQUEST packet arrives and the ICMP ECHO REPLY leaves.
    1. If you can ping the remote gateway local network address, but can't ping other hosts at the remote network, probably:
      1. The remote gateway is not forwarding the received packets.
Issue this command: cat /proc/sys/net/ipv4/ip_forwad and see if the result is "1". Otherwise issue:
echo 1 > /proc/sys/net/ipv4/ip_forwad
      1. The remote gateway has a firewall blocking your "pings"
At the remote gateway: verify the firewall's log and run TCPDUMP to see if the ICMP ECHO REQUEST packet arrives and the ICMP ECHO REPLY leaves.
  1. I can only "ping" the remote network hosts(or only ping works)
  2. I can open main page frames, but I can't open images neither other pages
  3. I can only open small pages
  4. Small packets pass, bigger packets don't
Before going any further, check if the remote gateway doen't have a firewall blocking your packets. Verifiy the firewall's log and run  TCPDUMP to see if the ICMP ECHO REQUEST packet arrives and the ICMP ECHO REPLY leaves.

These are symptoms of the same problem: MSS(or Maximum Segment Size).

The MSS is usually based on the MTU(Maximum Transfer Unit). The MTU is configured at each network interface or network device and has, for Ethernet networks, the default value of 1500. This value represents the maximum amount of bytes that the physical layer protocol, or Network Interface(on TCP/IP archtecture), can send at a time. So, if we wish to send more that this, we have to fragment the data in blocks of 1500 bytes before sending to the Ethernet protocol.


Aplication
Message


Transport
Segment


Inter-network
Datagram


Network Interface
Frame


Intra-network
TCP/IP archtecture

But, above the Network Interface layer protocol(Ethernet) we have the Inter-network(IP) protocol, that adds, at least, 20 bytes of header before sending data to the Network Interface layer network. Also, above the Inter-network layer, we have the transport(TCP or UDP) layer, that adds, at least, another 20 bytes of header (for TCP protocol).

So, the real size of the data that can be sent will be the MTU less all the bytes used for header at the upper layers until we reach the TCP protocol. This final value is the MSS(or Maximum Segment Size).

But, also, the MSS must be the same between the both sides of the connection and, because of this, negotiated between these before the connection establishment. Each one knows its MTU, so calculates its MSS and sends it to the other side during the connection establishment. The lower MSS will be chosen to avoid fragmentation at the connection edges. But, even with this, if there are other network equipments in the middle, that can have a lower MTU, these equipments will cause in-transit fragmentation. How we can avoid these fragmentations? The answer is "Path MTU Discovery".

The Path MTU Discovery send a packet will the maximum size for the segment (1500 bytes if Ethernet) or the MSS size informed at the connection establishment, marked to not be fragmented, and waits for some host in the path answering that it can't send the packet without fragmenting it. This answer is a ICMP "Can't Fragment" error message type 3 (destination unreachable) and code 4(fragmentation needed, but Don't Fragment bit set). Usually, this message carries, also, the MTU that caused the error. Now the Path MTU Discovery sends a new packet with the size of the MTU received in the ICMP message. This process repeats until the packet reaches the destination host and the Path MTU Discovery got an answer from it.

Therefore, is not clever to disable all kind of ICMP at your firewall, like the majority of network administrators do. Never blocks packets of type 3(destination unreachable) neither type 5(redirects). Otherwise, you can lead yourself into some big problems like the ones related at item 6.

However, the Path MTU Discovery calculates the MSS over the IP and TCP headers only. As we are adding an additional layer called IPSec, we should less the size of the IPSec header from the MSS value. This has to be done manually and that's why the  Path MTU Discovery doesn't work well with IPSec.

Packet smaller than the smallest MSS on the channel won't generate this error and, therefore, will flow. Like "ping" and small web pages

The solution for this Path MTU Discovery problem is to enable the arrival, at least, of ICMP type 3 and code 4 packets. But this doesn't solve the problem for IPSec since the Path MTU Discovery doesn't know this addicional layer. Therefore, the solution is to force a manual MSS on any attempt to make a connection between the two IPSec gateways. To acomplish this, just call this code(modifying REMOTE_GATEWAY and REMOTE_NETWORK to match your network configuration) from your firewall's loading script:
#!/bin/bash

#Forces a fixed MSS to deal with the Path MTU Discovery problem
#ATTENTION:
# 1.You must allow ICMP echo-request and echo-response packets exchange between the LOCAL and REMOTE gateways
# 2.You must allow ICMP redirect and destination-unreachable from the INTERNET
# 3.You will need the BC and IPROUTE packages installed

#definition of the remote gateway and network
REMOTE_GATEWAY=200.200.200.200
REMOTE_NETWORK=172.16.0.0/24

#DEBUG option: set to 1 to enable messages
DEBUG=0

function compute_mss() {
#compute the MSS for IPSec based on the MTU passed as a parameter
#returns the computed value on the MSS variable

local MTU
local IP_HEADER_LENGTH
local ESP_HEADER_LENGTH
local AH_HEADER_LENGTH
local IPSEC_HEADER_LENGTH
local ENCRYPTION_HEADER_LENGTH
local SUBTOTAL_DATA_LENGTH
local DISCARDED_DATA_LENGTH
local DATA_LENGTH

MTU=$1

#average IP header length(20<->60)
IP_HEADER_LENGTH=40

#ESP header length

ESP_HEADER_LENGTH=8

#AH header length

AH_HEADER_LENGTH=12

#IPSec header length = ESP + AH
IPSEC_HEADER_LENGTH=`echo "$ESP_HEADER_LENGTH + $AH_HEADER_LENGTH" | bc`

#Encryption algorithm header length
ENCRYPTION_HEADER_LENGTH=16 #CBC initial value

#Final length = MSS
SUBTOTAL_DATA_LENGTH=`echo "$MTU - $IP_HEADER_LENGTH - $IPSEC_HEADER_LENGTH - $ENCRYPTION_HEADER_LENGTH" | bc`
DISCARDED_DATA_LENGTH=`echo "$SUBTOTAL_DATA_LENGTH % 16" | bc`
DATA_LENGTH=`echo "$SUBTOTAL_DATA_LENGTH - $DISCARDED_DATA_LENGTH" | bc`
MSS=$DATA_LENGTH
}
function pmtu_discovery()
{
#Do a PMTU discovery through ICMP packets between the LOCAL and REMOTE gateways.
#In fact, it uses a binary search algorithm to find the maximum PAYLOAD length of a ICMP packet on the channel
#and, with this information, computes the PMTU
local MIN
local MAX
local MTU
local TARGET
local OK
local AVG
local IP_HEADER_LENGTH
local ICMP_PAYLOAD_MAX

#IP header MINIMUM length (20<->60 bytes)
IP_HEADER_LENGTH=20

#ICMP header length (echo-request/echo-reply)

ICMP_HEADER_LENGTH=8

#definition of a BC function that returns the absolute value of a number, that is, the number without sign
LOADABS="
define abs(x) {
if (x>=0) return(x)
return(-x)
}
"
#destination host (firewall -> internet interface)
TARGET=$1

#minimum ICMP PAYLOAD length
MIN=400
#get the MTU from the interface that will be used on the gateway communication
MTU=`ip route get $TARGET | xargs | sed "s/.*mtu \([[:digit:]]\+\) .*/\1/"`
#maximum ICMP PAYLOAD length => MTU - IP HEADER - ICMP HEADER
MAX=`echo "$MTU-$IP_HEADER_LENGTH-$ICMP_HEADER_LENGTH" | bc`

#Path MTU Discovery through binary search
while [ `echo "$LOADABS abs($MIN - $MAX)" | bc` -gt 1 ]; do
#Compute the average value between MIN and MAX
AVG=`echo "scale=0;($MIN + $MAX) / 2" | bc`
if [ $DEBUG -eq 1 ]; then
echo -n "AVG=$AVG "
fi

#We send a ICMP packet:
# -s $AVG : with the PAYLOAD size of $AVG
# -q : quiet
# -M do : with the DF(Don't Fragment) flag set
# -W 2 : wait the answer for 2 seconds
# -c 1 : only one packet
# $TARGET : to the $TARGET host
#and redirect the output to /dev/null since we just need the exit code(or $?)
ping -s $AVG -q -M do -W 2 -c 1 $TARGET 1>/dev/null 2>/dev/null
OK=$?
if [ $OK == 0 ]; then
#It worked! So, the minimum is set to the average, that is, MIN=AVG
if [ $DEBUG -eq 1 ]; then
echo "[OK]"
fi
MIN=$AVG
else
#It doesn't work... so, the maximum is set to the average - 1, that is, MAX=AVG-1
if [ $DEBUG -eq 1 ]; then
echo "[NOK]"
fi
MAX=`echo "$AVG-1" | bc`
fi
#we send ICMP packets each 0.5 seconds trying not to wake an IDS or FIREWALL
sleep 0.5
done
#the $MIN value will be the maximum ICMP PAYLOAD length allowed between LOCAL and REMOTE gateways
ICMP_PAYLOAD_MAX=$MIN
#now we compute the PMTU => PAYLOAD + ICMP HEADER + IP HEADER
PMTU=`echo "$ICMP_PAYLOAD_MAX+$ICMP_HEADER_LENGTH+$IP_HEADER_LENGTH" | bc`
}

#variable initialization

MSS=-1
PMTU=-1

#do the PMTU discovery to the remote gateway. The variable PMTU will have the final value.
pmtu_discovery $REMOTE_GATEWAY
#computes the MSS based on the PMTU returned. The variable MSS will have the final value.
compute_mss $PMTU

#We include the following IPTABLES rules to FORCE the MSS on any connection establishment with the remote network
iptables -I FORWARD 1 -p tcp -d $REMOTE_NETWORK --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
iptables -I FORWARD 2 -p tcp -s $REMOTE_NETWORK --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
iptables -I OUTPUT 1 -p tcp -d $REMOTE_NETWORK --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
iptables -I OUTPUT 2 -p tcp -s $REMOTE_NETWORK --tcp-flags SYN,RST SYN -j TCPMSS --set-mss $MSS
if [ $DEBUG -eq 1 ]; then
echo "PMTU=$PMTU"
echo "MSS=$MSS"
fi
exit 0
  1. Without a notice, the gateways start flooding packets at each other
This problem is due to Path MTU Discovery also, and therefore, related to items 2 to 5.

This symptom appear when a host tries to send a packet with the maximum segment size. This packet, at some point, or even at the remote gateway, is dropped for being too big. Whom dropped the packet sends back an ICMP Can't Fragment answer. The problem is that this answer never arrives due to firewall rules that stop it from reaching the destination. Read carefully the last topic that covers the ignorance of some network administrators on ICMP packets.

What happens when an ICMP "Can't Fragment" message is descaded? The Path MTU Discovery runs over TCP, therefore, it will wait for "timeout" and then retransmit the same segment. This process can be repeated indefinitely.

To solve this problem, force a MSS like covered at the last topic.
  1. Pages can be opened on the two connected networks, but not on networks connected to them
Another problem related to Path MTU Discovery, but this time, not related to your configurations. The problem is that, probably, the conected network that is to be accessed has firewall rules blocking any kind of ICMP, therefore, blocking the flow of TCP segments. The symptoms described above will also happen, but between your network and the connected one, not on the VPN channel.

To solve this problem, see the solution at items 2 to 5.


Apendix A
VPN in Fedora Core 2 with static SA (without IKE)
This apendix will provide some scripts that will make all kinds of IPSec channels without using IKE. This scripts were used as the "proof of concept" of the IPSec standard between two Fedora Core 2 hosts.
These scripts can be executed in any two hosts that exists at the same ethernet colision domain(same phisical network - without VLAN's)  without the need to stop normal equipment usage. To acomplish this, we create an additional IP address on each network card to establish  the IPSec channels.
Host 1 will have the IP: 10.0.0.216
    configured by the following command:
     # ifconfig eth0:1 10.0.0.216 netmask 255.255.255.0 broadcast 10.0.0.255
Host2 will have the IP: 10.0.0.11
    configured by the following command:
     # ifconfig eth0:1 10.0.0.11 netmask 255.255.255.0 broadcast 10.0.0.255

The following combinations where implemented:


Mode
Host1 (10.0.0.216) Host2 (10.0.0.11):
AH/transport ipsec-transport-on-ah-216
#!/sbin/setkey -f
flush;
spdflush;

#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";

spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
  ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
  ah/transport//require;

ipsec-transport-on-ah-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";

spdadd 10.0.0.216 10.0.0.11 any -P in ipsec
  ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P out ipsec
  ah/transport//require;

ESP/transport ipsec-transport-on-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
  esp/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
  esp/transport//require;

ipsec-transport-on-esp-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 10.0.0.11 any -P in ipsec
  esp/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P out ipsec
  esp/transport//require;

AH/ESP/transport ipsec-transport-on-ah-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 10.0.0.11 any -P out ipsec
  esp/transport//require
  ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P in ipsec
  esp/transport//require
  ah/transport//require;

ipsec-transport-on-ah-esp-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#AH
add 10.0.0.11 10.0.0.216 ah 15700 -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -A hmac-sha1 "12345678901234567890";

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 10.0.0.11 any -P in ipsec
  esp/transport//require
  ah/transport//require;
spdadd 10.0.0.11 10.0.0.216 any -P out ipsec
  esp/transport//require
  ah/transport//require;

ESP/tunnel ipsec-tunnel-on-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 0.0.0.0/0 any -P out ipsec
  esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P in ipsec
  esp/tunnel/10.0.0.11-10.0.0.216/require;

ipsec-tunnel-on-esp-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 0.0.0.0/0 any -P in ipsec
  esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P out ipsec
  esp/tunnel/10.0.0.11-10.0.0.216/require;


ESP+Auth/tunnel ipsec-tunnel-on-esp-auth-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#ESP+AUTH
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc "123456789012123456789012" -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc "123456789012123456789012" -A hmac-sha1 "12345678901234567890";

spdadd 10.0.0.216 0.0.0.0/0 any -P out ipsec
  esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P in ipsec
  esp/tunnel/10.0.0.11-10.0.0.216/require;

ipsec-tunnel-on-esp-auth-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#ESP+AUTH
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc "123456789012123456789012" -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc "123456789012123456789012" -A hmac-sha1 "12345678901234567890";

spdadd 10.0.0.216 0.0.0.0/0 any -P in ipsec
  esp/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P out ipsec
  esp/tunnel/10.0.0.11-10.0.0.216/require;


AH/ESP/tunnel ipsec-tunnel-on-ah-esp-216
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#AH
add 10.0.0.11 10.0.0.216 ah 15700 -m tunnel -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -m tunnel -A hmac-sha1 "12345678901234567890";

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 0.0.0.0/0 any -P out ipsec
  esp/tunnel/10.0.0.216-10.0.0.11/require
  ah/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P in ipsec
  esp/tunnel/10.0.0.11-10.0.0.216/require
  ah/tunnel/10.0.0.11-10.0.0.216/require;

ipsec-tunnel-on-ah-esp-11
#!/sbin/setkey -f
flush ah;
flush esp;
spdflush;

#AH
add 10.0.0.11 10.0.0.216 ah 15700 -m tunnel -A hmac-sha1 "12345678901234567890";
add 10.0.0.216 10.0.0.11 ah 24500 -m tunnel -A hmac-sha1 "12345678901234567890";

#ESP
add 10.0.0.11 10.0.0.216 esp 15701 -m tunnel -E rijndael-cbc "123456789012123456789012";
add 10.0.0.216 10.0.0.11 esp 24501 -m tunnel -E rijndael-cbc "123456789012123456789012";

spdadd 10.0.0.216 0.0.0.0/0 any -P in ipsec
  esp/tunnel/10.0.0.216-10.0.0.11/require
  ah/tunnel/10.0.0.216-10.0.0.11/require;
spdadd 0.0.0.0/0 10.0.0.216 any -P out ipsec
  esp/tunnel/10.0.0.11-10.0.0.216/require
  ah/tunnel/10.0.0.11-10.0.0.216/require;



IMPORTANT: The script execution must be made in a related manner. The execution of a script that creates an ESP/tunnel at host1 must be related with the execution of a script that creates an ESP/tunnel at host2.

Cristiano da Cunha Duarte is graduated in Computer Science by PUC/MG, specialist in Communication Networks Application and Design by UnB and works with development in C, C++, PHP5, Java, CORBA and, of couse, Linux Servers. More information at: http://cunha17.cristianoduarte.pro.br/index.en_us.php.