Mac OSX IPSEC VPN via command line using builtin Racoon client

September 19, 2012 at 07:30 AM | categories: Mac OS X, Howto, Sysadmin, Linux, Tips, Security, IPSEC | View Comments

Introduction

The Mac OSX IPSEC VPN client setup via "System preferences" only supports IPSEC/XAUTH and IPSEC/L2TP both of which give you a different IP address for your tunnel interface. System preferences on the backend uses Racoon so it is possible via the command line to setup a pure IPSEC connection.

In my previous post i described how to configure a Strongswan server for use with Mac OSX, Ipad, Iphone clients. For the sake of brevity i will not repeat that in this post.

This scenario assumes you are connected to a lan 10.128.1.0/24 and your IP address is 10.128.1.2 and you are connecting to a remote network 192.168.1.0/24 protected by an IPSEC VPN running Strongswan on a gateway with a dynamic address being resolved via dynamic DNS. IPSEC Authentication is done using Certificates.

Configuration

Client configuration.

Edit /etc/racoon/racoon.conf and add the following to the bottom.

include "/opt/local/etc/cmdline-ipsec.conf" ;

Create a configuration template file /opt/local/etc/cmdline-ipsec.conf.tmpl. I am using a template because the remote side has a dynamic ip address and racoon does not support DNS names only IP addresses, a custom script resolves the hostname and then generates an updated racoon configuration from this template file with the resolved IP address.

remote %SERVERIP% {
        exchange_mode main;
        ca_type x509 "/opt/local/etc/pki/cacert.pem";
        certificate_type x509 "/opt/local/etc/pki/example.pem" "/opt/local/etc/pki/example.key.pem";
        proposal_check obey;
        mode_cfg off;
        dpd_delay 360;
        nat_traversal on;
        my_identifier asn1dn;
        ike_frag on;
        script "/opt/local/bin/phase1-up.sh" phase1_up;
        script "/opt/local/bin/phase1-down.sh" phase1_down;
        lifetime time 24 hour;
        passive off;
        proposal {
                encryption_algorithm aes256;
                hash_algorithm sha512;
                authentication_method rsasig;
                dh_group 2;
       }
}

sainfo anonymous {
        lifetime time 24 hour;
        pfs_group modp2048;
        encryption_algorithm aes256;
        authentication_algorithm hmac_sha1, hmac_sha256, hmac_sha512;
        compression_algorithm deflate ;
}

Create the phase1 up script /opt/local/bin/phase1-up.sh

#!/bin/sh

#
# sa-up.sh local configuration for a new SA
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/local/bin:/opt/local/sbin
MYIP=10.128.1.2
PROTECTEDNET=192.168.1.0/24

echo $@
echo "LOCAL_ADDR = ${LOCAL_ADDR}"
echo "LOCAL_PORT = ${LOCAL_PORT}"
echo "REMOTE_ADDR = ${REMOTE_ADDR}"
echo "REMOTE_PORT = ${REMOTE_PORT}"

LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"

echo "
spdadd ${MYIP}/32[any] ${PROTECTEDNET}[any] any
       -P out ipsec esp/tunnel/${LOCAL}-${REMOTE}/require;
spdadd ${PROTECTEDNET} ${MYIP}[any] any
       -P in ipsec esp/tunnel/${REMOTE}-${LOCAL}/require;
" | setkey -c

Create the phase1 down script /opt/local/bin/phase1-down.sh

#!/bin/sh

#
# sa-down.sh local remove SA
#

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
MYIP=10.128.1.2
PROTECTEDNET=192.168.1.0/24

echo $@
echo "LOCAL_ADDR = ${LOCAL_ADDR}"
echo "LOCAL_PORT = ${LOCAL_PORT}"
echo "REMOTE_ADDR = ${REMOTE_ADDR}"
echo "REMOTE_PORT = ${REMOTE_PORT}"

LOCAL="${LOCAL_ADDR}[${LOCAL_PORT}]"
REMOTE="${REMOTE_ADDR}[${REMOTE_PORT}]"

echo "
deleteall ${REMOTE_ADDR} ${LOCAL_ADDR} esp;
deleteall ${LOCAL_ADDR} ${REMOTE_ADDR} esp; 
spddelete ${MYIP}/32[any] ${PROTECTEDNET}[any] any
        -P out ipsec esp/tunnel/${LOCAL}-${REMOTE}/require;
spddelete ${PROTECTEDNET}[any] ${MYIP}[any] any
        -P in ipsec esp/tunnel/${REMOTE}-${LOCAL}/require;
" | setkey -c

Create the custom start script /opt/local/sbin/start-vpn

#!/bin/bash
#
#
SERVERNAME="strongswan-example.dyndns.org"
SERVERIP=$(host $SERVERNAME|awk '{print $4}')
status=$(racoonctl show-sa isakmp|wc -l|awk '{print $1}')
if [ "$status" != "2" ]; then
   echo "Not connected, starting conn"
   sed -e "s:%SERVERIP%:${SERVERIP}:" \
   /opt/local/etc/cmdline-ipsec.conf.tmpl > /opt/local/etc/cmdline-ipsec.conf
   racoonctl reload-config
   racoonctl vpn-connect $SERVERIP
else
   racoonctl show-sa isakmp
   echo "Already connect, exiting"
fi

Make the script executable

chmod +x /opt/local/sbin/start-vpn

Server configuration

Update the ipsec.conf configuration from my previous post to add the following conn

conn rw
        leftcert=vpn.example.org.pem
        leftid=@vpn.example.org
        leftfirewall=yes
        right=%any
        rightsubnet=0.0.0.0/0
        rekey=yes

Testing

Open a command prompt and run the command, as root or using sudo.

start-vpn

You should be able to connect to hosts on the protected network (192.168.1.0/24)

To stop the connection run the command.

racoonctl vpn-disconnect strongswan-example.dyndns.org

Related articles


blog comments powered by Disqus