IPSEC Config for OpenBSD to Cisco ASA 8.2.x

In this sample config the HQ LAN is protected by a cisco ASA running
8.2.2 with a LAN ip scheme of and the remote side is
running standard OpenBSD 4.6 with a LAN scheme of   

OpenBSD public IP:  z.y.207.125
Cisco ASA public IP: a.b.204.181

Some notes/caveats:
1. The crypto map is named l2l (short for lan2lan).

2. The ASA has all 10.x/8 to 10.x/8 and 192.168.x/16 traffic
NO-NATTed. This allows the no-nat acl to be short and simple when many
spoke vpn sites are added with 192.168.x/24 or 10.x/16 or /24 subnets.
3. The OpenBSD ipsec implementation does not turn on dead peer
detection it seems currently unless dynamic mode is chosen and FQDN
IDs (instead of IPv4 addresses) are used as gateway IDs.  This means
that if you do a hard clear (clear crypto ipsec sa on the ASA  or
ipsecctl -F -f /etc/ipsec.conf on OpenBSD) the same hard clear may
need to be done on the other side to bring the tunnel up before the
key lifetime expires. This seems to happen when the tunnel is torn
down on the OpenBSD side via a flush. The ASA side keeps the tunnel
open and traffic is stuck without a working SA.  The solution to this
is to use this command alias to clear the tunnel from the OpenBSD side
after changing a parameter.  It will let the ASA know to tear down the
existing SA if one exists, and the tunnel will come back up within a
few seconds once the new SAs are built.

ipsecctl -d -f /etc/ipsec.conf;
sleep 10;
ipsecctl -F -f /etc/ipsec.conf

If you have multiple SAs (multiple tunnels) on the OpenBSD side, then
use ipsecctl- sa to view the SAs and only terminate the ones that you
need to restart. Same thing applies for the ASA side; you can clear
crypto ipsec sa peer [ip_of_peer_to_clear].     

4. You need to source your pings properly from both the ASA and the
OpenBSD gateway when testing if a tunnel is up.  

ping inside a.b.204.181
OpenBSD: ping -I [ipv4 of inside interface that is part of the tunnel] a.b.c.d
Example: ping -I  
Cisco ASA configuration
interface GigabitEthernet0/0
 nameif outside
 security-level 0
 ip address a.b.204.181 

interface GigabitEthernet0/1
 nameif inside
 security-level 100
 ip address 

route outside a.b.204.182 1

! define the acl that will tell the ASA NOT to NAT the matching traffic:
access-list nonat extended permit ip
access-list nonat extended permit ip

! bind the acl to the no nat (nat = 0 means no nat for the ASA) config:
nat (inside) 0 access-list nonat

! Define the acl which will control the traffic which will be
! encapsulated in the ipsec tunnel from the ASA to the sgw:
access-list 101 extended permit ip

! enable IKE on the outside interface of the ASA:
crypto isakmp enable outside

! enable nat-awareness code in the ASA, set the keep alive for 20 sec:
crypto isakmp nat-traversal 20

! configure IKE policies on the ASA - phase 1 negotiation
crypto isakmp policy 10
 authentication pre-share
 encryption 3des
 hash sha
 group 2
 lifetime 86400

! configure the IPSec Policies - phase 2 negotiations:
crypto ipsec transform-set ESP-3DES-SHA esp-3des esp-sha-hmac

! tell the ASA that the inside intf is the management interface:
management-access inside
Note: This will allow us to source pings from the inside interface to the remote side of the vpn tunnel.  Example: ping from the inside interface  ping inside
! build the tunnel group:
tunnel-group z.y.207.125 type ipsec-l2l
tunnel-group z.y.207.125 ipsec-attributes
 pre-shared-key test1234

! install the crypto map which will scan egress traffic
! and tunnel the matching traffic based on the match keyword:
crypto map l2l 10 match address 101
crypto map l2l 10 set peer z.y.207.125
crypto map l2l 10 set transform-set ESP-3DES-SHA
crypto map l2l interface outside
OpenBSD IPSEC Configuration
The "main" params define the method and crypto transforms used in
phase 1 of automatic keying (that is what IKE daemons do).  The "auth"
params define the settings used for the second phase.  

OpenBSD /etc/ipsec.conf    

ike esp from to \
   peer a.b.204.181 \
   main auth hmac-sha1 enc 3des group modp1024 \
   quick auth hmac-sha1 enc 3des group none \ 
   psk "test1234"
/etc/pf.conf fw rules -   This rule goes in section 1 - macros:

fw_main  = "a.b.c.d"

## Start rules for ipsec
## ipsec rule 1: allow esp:
pass in quick on $ext_if proto 50 from { $fw_main } to $fwip keep state
## ipsec rule 2: allow ike and udp 4500 ike:
pass in quick on $ext_if proto udp from { $fw_main } to $fwip port { isakmp, ipsec-nat-t }
## ipsec rule 3: allow lan2lan tunneled traffic by default:
## Uncomment the below rule to allow all ipsec encapsulated traffic
## on the encryption interface. This will allow all lan2lan traffic to flow thru the tunnel:
pass on enc0

Upgrading phase2 negotiation to use perfect forward secrecy

1. Add this setting to the crypto map on the ASA:
crypto map l2l 10 set pfs group5
2. Change the quick auth line on the OpenBSD gw to enable DH group 5:
quick auth hmac-sha1 enc 3des group modp1536 \

There are 3 commonly used dh group settings for phase 2:
A. none
B. modp1024 = dh group 2
C. modp1536 = dh group 5

The ASA and the OpenBSD must match in order for the tunnel to come up.
To look at the isakpmd logging on the OpenBSD side: tail -f
/var/log/daemon  You can also do ipsecclt -m to monitor interactively
the keying attempts while pinging across the tunnel.

Use iperf to test your tunnel
If you have workstation with iperf installed on each side of the
computer.  You should test performance across the tunnel:    

server side:iperf -s -m -p 5000  (let it run)
client side: iperf -c -m -p 5000 -t 120

The server side iperf instance is running on a machine with an IP of: which is what the client instance connects to.  The -m
option prints the detected maximum segment size. 

Dealing with packet Fragmentation and Path MTU issues:
If you determine that you need to clamp the MSS then these commands
may be useful:   

ASA clamp the MSS: sysopt connection tcpmss 1360
ASA clear the df bit on packets leaving an ipsec tunnel (flowing outbound):
crypto ipsec df-bit clear-df outside

OpenBSD MSS clamp and DF bit clear:

# set mss clamp on enc0 to 1360:
match on enc0 scrub (no-df max-mss 1360)
# standard scrub on all other traffic:
match in all scrub (no-df)
# pass all other traffic on enc0:
pass on enc0

After running iperf you should have a good idea of what to set the MSS
to; 1360 is good for standard ethernet. If you are using a PPPoATM or PPPoE 
dsl connection you may need to adjust this number down.