User Tools

Site Tools


strongswan_certificates

IPSec Strongswan IKEv2 using authentication by certificates

Wiki entry for setting up IPSec iPhone/iPad Configuration is a bit outdated, so I created a new example which provides compatibility with most systems supporting IKEv2. Referencing this wiki entry.

This Gist was helpful when I built this.

Read me first

This is a tested example which should allow anyone to easily setup a secure and working VPN server.

In these examples lan is 192.168.0.0/16 and router's IP address is 192.168.0.1.

/etc/config/network:

config interface 'lan'
	option type		'bridge'
	option ifname		'eth0'
	option proto		'static'
	option ipaddr		'192.168.0.1'
	option netmask		'255.255.0.0'
	option ip6assign	'60'

This setup is not necessary or mandatory, it was just used on this example. If you have DHCP issues when connecting, most likely reason is because LAN broadcast address in /etc/strongswan.conf is not configured accordingly to your LAN setup.

In this example, VPN Server's name is set to VpnTest and country code is set to Finland(FI), so you might want to change these, they appear in scripts used to generate certificates (in the end of this wiki entry). Also this setup is created for system behind a dynamic IP address, so WAN ip address is not used at all because it might change, in these cases, it is handy to use a dynamic IP hostname, there are some free provides out there, google them if in need, or if you have your own domain, it's DNS services might have a way of updating dynamic IP for a hostname. In these document this domain name is set to vpntest.lan so make sure you change occurrences of it to your own hostname. Also if you have a static IP and want it in your server certificate, check commented part in mk_server.sh script.

vpntest.lan occurs in following files:

  1. ipsec.conf: leftid
  2. mk_server.sh: SRVNAME and IPADDR variables

Also in scripts, change ORG (organisation name) to something of your liking. Accordingly, to your lan setup, make changes in:

  1. ipsec.conf: leftsubnet, rightsubnet, rightdns
  2. strongswan.conf: charon.dns1, charon.plugins.dhcp.server

Otherwise, you just could copy & paste ;) Connectivity has been tested on Mac OS X and iPhone, and there should not be any problems with Android and Windows either.

Connectivity issue with dynamic IP address

In case that you have a dynamic IP, you might face some connectivity issues after IP address has changed/updated. A workaround to this is to create a script which updates IP address to your name server, and after successful update, it restarts firewall and ipsec.

Packages

Install necessary packages.

opkg update
opkg install strongswan-default strongswan-pki ipset strongswan-mod-openssl strongswan-mod-curl strongswan-mod-dhcp strongswan-mod-eap-tls strongswan-mod-eap-identity strongswan-mod-kernel-libipsec kmod-tun openssl-util strongswan-mod-test-vectors strongswan-mod-farp

/etc/config/network

Define ipsec interface

config interface 'ipsec'
	option ifname		'ipsec0'
	option proto		'none'
	option defaultroute	'0'
	option peerdns		'0'
	option ipv6		'0'

/etc/firewall.user

Append policy rules.

iptables -I INPUT   -m policy --dir in  --pol ipsec --proto esp -j ACCEPT
iptables -I FORWARD -m policy --dir in  --pol ipsec --proto esp -j ACCEPT
iptables -I FORWARD -m policy --dir out --pol ipsec --proto esp -j ACCEPT
iptables -I OUTPUT  -m policy --dir out --pol ipsec --proto esp -j ACCEPT

/etc/config/firewall

Create vpn zone

config zone
	option name		'vpn'
	list network		'ipsec'
	option input		'ACCEPT'
	option output		'ACCEPT'
	option forward		'ACCEPT'
	option masq		'1'
	option mtu_fix		'1'

Enable forwardings

config forwarding
	option src		'vpn'
	option dest		'lan'

config forwarding
	option src		'lan'
	option dest		'vpn'

config forwarding
	option src		'vpn'
	option dest		'wan'

Append rules to allow IPSec connections through firewall.

config rule
	option name		'IPSec-ESP'
	option src		'wan'
	option proto		'esp'
	option target		'ACCEPT'

config rule
	option name		'IPSec-IKE'
	option src		'wan'
	option dest_port	'500'
	option proto		'udp'
	option target		'ACCEPT'

config rule
	option name		'IPSec-NAT-T'
	option src		'wan'
	option dest_port	'4500'
	option proto		'udp'
	option target		'ACCEPT'

config rule
	option name		'IPSec-Auth-Header'
	option src		'wan'
	option proto		'ah'
	option target		'ACCEPT'

Optional - Enable igmp pinging.

config rule
	option name		'Allow-Ping-From-VPN'
	option src		'vpn'
	option proto		'igmp'
	option icmp_type	'echo-request'
	option family		'ipv4'
	option target		'ACCEPT'

config rule
	option name		'Allow-Ping-To-VPN'
	option dest		'vpn'
	option proto		'igmp'
	option icmp_type	'echo-request'
	option family		'ipv4'
	option target		'ACCEPT'

/etc/init.d/ipsec

Replace init script contents with following simple script (provided script uses /etc/config/ipsec for configuration, this setup uses ipsec/strongswan files).

#!/bin/sh /etc/rc.common
# ipsec init script

START=90
STOP=10

USE_PROCD=1
PROG=/usr/lib/ipsec/starter

service_running() {
	ipsec status > /dev/null 2>&1
}

reload_service() {
	running && {
		ipsec rereadall
		ipsec reload
		return
	}

	start
}

check_ipsec_interface() {
	procd_add_interface_trigger "interface.*" "ipsec0" /etc/init.d/ipsec  reload
}

service_triggers() {
	procd_add_reload_trigger "ipsec"
	check_ipsec_interface
}

start_service() {
	procd_open_instance
	procd_set_param command $PROG --daemon charon --nofork
	procd_set_param respawn
	procd_close_instance
}

/etc/ipsec.secrets

      # /etc/ipsec.secrets - strongSwan IPsec secrets file
      : RSA host-vpn.der

/etc/ipsec.conf

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
	strictcrlpolicy = no
	uniqueids = no

# Add connections here.

conn default
	keyexchange = ikev2
	ike = aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes256-aes128-sha256-sha1-modp2048-modp4096-modp1024,aes256-sha1-modp1024,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-sha256-sha1-modp2048-modp4096-modp1024,3des-sha1-modp1024!
	esp = aes128-aes256-sha1-sha256-modp2048-modp4096-modp1024,aes128-sha1,aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp2048-modp4096-modp1024,aes128gcm16,aes128gcm16-ecp256,aes256-sha1,aes256-sha256,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16,aes256gcm16-ecp384,3des-sha1!
	mobike = yes        
	dpdaction = clear
	dpddelay = 60s
	left = %any
	#leftid = <VPN SERVER ID / DOMAINNAME!!!>
	leftid = vpntest.lan
	leftsubnet = 0.0.0.0/0
	leftcert = host-vpn.der
	leftsendcert = always
	right = %any
	rightauth = eap-tls
	rightsourceip = %dhcp
	#rightdns = <LAN DNS SERVER>
	rightdns = 192.168.0.1
	eap_identity = %identity
	forceencaps = yes
	auto = add

/etc/strongswan.conf

# strongswan.conf - strongSwan configuration file
#
# Refer to the strongswan.conf(5) manpage for details
#
# Configuration changes should be made in the included files

charon {
	dns1 = 192.168.0.1
	load_modular = yes
	plugins {
		include strongswan.d/charon/*.conf
		dhcp {
			force_server_address = yes
			identity_lease = yes
			server = 192.168.255.255
			# use LAN broadcast address here, not IP address.        
		}
	}
}

pluto {
	threads = 8
	dns1 = 192.168.0.1
}
      
libstrongswan {
	# set to n, the DH exponent size is optimized
	#dh_exponent_ansi_x9_42 = no
	#crypto_test {
	#	on_add = yes
	#}
}

include strongswan.d/*.conf

Tools for certificates

Following scripts are provided for certificate operations:

  1. clean.sh: remove all generated certs
  2. mk_server.sh: Executed only once to root and server certificates.
  3. mk_user.sh: Executed for creation of client certificates.

After generating server certificates, you should disable mk_server.sh script, because if you re-create certificates, you client certificates no longer match. Also changes to these scripts allow changing certificate's validity time.

/etc/ipsec.d/clean.sh

#!/bin/sh
rm /etc/ipsec.d/*/*.* 2> /dev/null

/etc/ipsec.d/mk_server.sh

#!/bin/sh

SRVNAME="vpntest.lan"
IPADDR="vpntest.lan"
#Uncomment only if vpn server is behind a static IP
#IPADDR=$(. /lib/functions/network.sh; network_get_ipaddr ip wan; echo $ip)

COUNTRY="FI"
ORG="VpnTest"

VALIDDAYS="3650"
LIFETIME="730"

ipsec pki --gen --type rsa --size 4096 --outform der > private/strongswan.der
chmod 600 private/strongswan.der

ipsec pki --self --ca --lifetime $VALIDDAYS --in private/strongswan.der --type rsa --dn "C=$COUNTRY, O=$ORG, CN=$ORG Root CA" --outform der > cacerts/strongswan.der
openssl x509 -inform DER -in cacerts/strongswan.der -out cacerts/strongswan.pem -outform PEM

ipsec pki --print --in cacerts/strongswan.der

ipsec pki --gen --type rsa --size 4096 --outform der > private/host-vpn.der
chmod 600 private/host-vpn.der

ipsec pki --pub --in private/host-vpn.der --type rsa | ipsec pki --issue --lifetime $LIFETIME --cacert cacerts/strongswan.der --cakey private/strongswan.der --dn "C=$COUNTRY, O=$ORG, CN=$SRVNAME" --san=$SRVNAME --san $IPADDR --san @$IPADDR --flag serverAuth --flag ikeIntermediate --outform der > certs/host-vpn.der
ipsec pki --print --in certs/host-vpn.der

/etc/ipsec.d/mk_user.sh

#!/bin/sh

COUNTRY="FI"
ORG="VpnTest"

LIFETIME="730"

echo "Enter userid (no spaces or special characters):"
read USERID

[ -z "$USERID" ] && {
	echo Empty user ID. Cancelling.
	exit 0
}

echo "Enter fullname:"
read NAME

[ -z "$NAME" ] && {
	echo Empty full name. Cancelling.
	exit 0
}

mkdir -p /etc/ipsec.d/p12 2> /dev/null

ipsec pki --gen --type rsa --size 2048 --outform der > private/$USERID.der
chmod 600 private/$USERID.der

ipsec pki --pub --in private/$USERID.der --type rsa | ipsec pki --issue --lifetime $LIFETIME --cacert cacerts/strongswan.der --cakey private/strongswan.der --dn "C=$COUNTRY, O=$ORG, CN=$USERID" --san "$USERID" --outform der > certs/$USERID.der
openssl rsa -inform DER -in private/$USERID.der -out private/$USERID.pem -outform PEM

openssl x509 -inform DER -in certs/$USERID.der -out certs/$USERID.pem -outform PEM
openssl pkcs12 -export -inkey private/$USERID.pem -in certs/$USERID.pem -name "$NAME's VPN Certificate" -certfile cacerts/strongswan.pem -caname "$ORG Root CA" -out p12/$USERID.p12

Client configuration

Create client certificate with client.sh ( or manually if you want to.. ). Needed certificates:

  1. cacerts/strongswan.pem
  2. p12/USERID.p12

Where USERID is what you entered when using mk-client.sh

Copy these certificates to client device somehow (mail them, scp them, etc..) and install them (as trusted). Define connection like this:

VPN Type:		IKEv2
Server Address:		server ip/domain
Remote ID:		server domain
Local ID:		USERID

Authentication settings:
	Method:		Certificate
	Certificate:	USERID.p12
strongswan_certificates.txt · Last modified: 2018/10/13 18:02 by oskarirauta