VPN Certificate management for strongswan

Templating openssl

Openssl is found to work best with a templating strategy, with different config files for each application, so we make a .cnf file for each target certificate, though in some situations the same .cnf can make several targets.

They are based on /etc/ssl/openssl.cnf, and can define files such as /etc/ipsec.d/req/phone.cnf or /etc/ipsec.d/req/gate.cnf

Reference sections

  1. oid_section = new_oids

Define some oids

  1. [ new_oids ]
  2. dnssecEmbeddedChain = 1.3.6.1.4.1.11129.2.1.4
  3. xmppAddr = 1.3.6.1.5.5.7.8.5
  4. xpserver_ext = 1.3.6.1.5.5.7.3.1
  5. xpclient_ext = 1.3.6.1.5.5.7.3.2
  6. ipsec_end_sys = 1.3.6.1.5.5.7.3.5
  7. ipsec_tunnel = 1.3.6.1.5.5.7.3.6
  8. ipsec_user = 1.3.6.1.5.5.7.3.7
  9. pkinit_usage_client = 1.3.6.1.5.2.3.4
  10. pkinit_usage_kdc = 1.3.6.1.5.2.3.5

Define the ingredients of a certificate request

  1. [ req ]
  2. default_bits = 4096
  3. distinguished_name = req_distinguished_name
  4. attributes = req_attributes
  5. x509_extensions = v3_ca
  6. req_extensions = v3_req
  7. utf8 = yes

Define the name of the target certificate

This defines the friendly name, some implementations may expect it to match a node DNS name, even though that is what alternate names are for.

  1. [ req_distinguished_name ]
  2. commonName =
  3. commonName_default =Example Station

No request attributes are required

  1. [ req_attributes ]

Define CA section

  1. [ ca ]
  2. default_ca = CA_default

CA section

All work relates to ipsec directory.

  1. [ CA_default ]
  2. unique_subject = no
  3. dir = /etc/ipsec.d
  4. certificate = $dir/cacerts/example.crt
  5. private_key = $dir/private/example.key
  6. database = $dir/reqs/example.ca.txt
  7. serial = $dir/reqs/example.ca.serial
  8. certs = $dir/certs
  9. new_certs_dir = $dir/certs
  10. default_days = 365
  11. x509_extensions = usr_cert
  12. default_md = default
  13. policy = policy_anything

Define the policy

  1. [ policy_anything ]
  2. commonName = supplied

Tell CA about settings for certificate extensions.

  1. [ usr_cert ]
  2. basicConstraints = CA:FALSE
  3. subjectKeyIdentifier=hash
  4. authorityKeyIdentifier=keyid,issuer
  5. subjectAltName=@example_alt_names

Tell request module settings for certificate extensions.

  1. [ v3_req ]
  2. basicConstraints = CA:FALSE
  3. keyUsage = nonRepudiation, digitalSignature, keyEncipherment
  4. #extendedKeyUsage = ipsec_user,ipsec_tunnel,ipsec_end_sys
  5. subjectAltName=@example_alt_names

Tell ca module settings for certificate extensions.

  1. [ v3_ca ]
  2. ##dnssecEmbeddedChain = ASN1:FORMAT:HEX,OCT:${ENV::CHAIN}
  3. #dnssecEmbeddedChain = DER:${ENV::CHAIN}
  4. basicConstraints = CA:TRUE
  5. subjectKeyIdentifier=hash
  6. authorityKeyIdentifier=keyid:always,issuer
  7. subjectAltName=@example_alt_names
  8. keyUsage = nonRepudiation, digitalSignature, keyEncipherment
  9. #extendedKeyUsage = ipsec_user,ipsec_tunnel,ipsec_end_sys

Define alternatives for certificate common name, such as a DNS name.

  1. [ example_alt_names ]
  2. DNS.0 = example.
  3. #otherName.0 = xmppAddr;UTF8:example.

Regeneration script

Here it is kept in /etc/ipsec.d/ipsecinit to keep it with the other files

The key regeneration hopefully is only rarely needed, so is commented off; that is, if a compromise is suspected.

A choice of elliptic curve or power modulus keys is possible.

The remainder of script will be run much more often to adjust certificate parameters to handle any new features in future versions of clients and servers.

Intentionally we keep nothing that is key derived, this means certificates etc, except config files and scripts.

(Re)generating all the selfsigned certificates

  1. for N in gate phone
  2. do
  3. S=/etc/ipsec.d/reqs/$N.cnf
  4. K=/etc/ipsec.d/private/$N.key
  5. P=/etc/ipsec.d/reqs/$N.pub
  6. C=/etc/ipsec.d/cacerts/$N.crt
  7. R=/etc/ipsec.d/reqs/$N.req
  8. #openssl rsa -pubout -in $K > $P
  9. D=`grep ^default_days $S | cut -d= -f2` # openssl took no notice of the days in the .cnf
  10. openssl req -new -batch -key $K -config $S -out $R
  11. openssl req -new -batch -key $K -config $S -x509 -out $C -days $D
  12. done

Regenerate cross certificates for the gateway

  1. rm /etc/ipsec.d/reqs/gate.ca.*
  2. touch /etc/ipsec.d/reqs/gate.ca.txt
  3. echo 00 > /etc/ipsec.d/reqs/gate.ca.serial
  4. openssl ca -batch -config /etc/ipsec.d/reqs/gate.cnf -in /etc/ipsec.d/reqs/phone.req -out /etc/ipsec.d/certs/phone-by-gate.crt

Regenerate cross certificates for the phone

  1. rm /etc/ipsec.d/reqs/phone.ca.*
  2. touch /etc/ipsec.d/reqs/phone.ca.txt
  3. echo 00 > /etc/ipsec.d/reqs/phone.ca.serial
  4. openssl ca -batch -config /etc/ipsec.d/reqs/phone.cnf -in /etc/ipsec.d/reqs/gate.req -out /etc/ipsec.d/certs/gate-by-phone.crt

Make a certificate package for android

Store the $USER-phone.p12 and /etc/ipsec.d/cacerts/phone.crt to the android SDCARD, as it is usually preserved if the android needs a factory reset.

Use the native filesystem to import the .p12, saying it is for VPN and apps. Use the strongswan app to import phone.crt, it appears in the IMPORTED and may appear in USER. It can be then removed from USER (leaving it in IMPORTED) to stop Android generating security warnings, which makes USER effectively useless.

Can now configure an IKEv2 Certificate connection strongswan app in android with independence from pkix, selecting the imported ca from IMPORTED.

The cross certifying where the phone's keypair was used to sign the gateway keypair allows a VPN to be setup using the native android client, such as IPSEC hybrid RSA, in this case there is no warning about trusting "an app" strongswan but it did not support both ipv4 and ipv6 over ipv4. When creating a connection, select the same p12 as both server certificate and ca certificate.

Next steps

See the strongswan ipsec setup