In my earlier blog post about VPNs, I looked at a range of VPN options.
The strongSwan wiki documentation is generally quite good but it doesn't describe the exact procedure for an Android user anywhere. This blog aims to fill that gap.
Here I am sharing some working examples of how to configure and use RSA certificate authentication between a Linux box and an Android phone using strongSwan. There are several commands to execute for each step, but they can be easily scripted.
Here are the versions in play:
For production, I would highly recommend creating your own root CA on a smart card and managing it from a clean machine without any network connection.
To start quickly for testing, just create a CA using the steps from the strongSwan wiki, in particular:
umask 0177 ipsec pki --gen > caKey.der ipsec pki --self --in caKey.der \ --dn "C=CH, O=Acme Ltd, CN=example.org CA root" \ --ca > caCert.der
Now you need to create a key for the server. The key thing to observe here is the use of the "--san" argument: the Android client expects a subjectAltName in the certificate from the server. The VPN gateway has the hostname vpn.example.org:
ipsec pki --gen > vpnKey.der ipsec pki --pub --in vpnKey.der | \ ipsec pki --issue --cacert caCert.der --cakey caKey.der \ --dn 'CN=vpn.example.org' \ --san vpn.example.org > vpnCert.der cp vpnKey.der /etc/ipsec.d/private/ cp vpnCert.der /etc/ipsec.d/certs/
For the Android client, it is necessary to create a private key and certificate and then embed them together with a copy of the root certificate in a PKCS#12 file. We will need OpenSSL or GnuTLS for some of these steps. The pkcs12 command will prompt for a password: make up a long, obscure password, you will only use it once when importing the certificate into the phone. Here is a script you can use for each client certificate you want to create:
#!/bin/bash -e umask 0177 TARGET_HOST=$1 DOMAIN=example.org IPSEC=/usr/sbin/ipsec KEY_FILE="${TARGET_HOST}Key.der" CRT_FILE="${TARGET_HOST}Cert.der" if [ -f ${KEY_FILE} ]; then echo "$KEY_FILE exists" exit 1 fi ${IPSEC} pki --gen > ${KEY_FILE} ${IPSEC} pki --pub --in ${KEY_FILE} | \ ${IPSEC} pki --issue \ --cacert caCert.der --cakey caKey.der \ --dn "CN=${TARGET_HOST}.${DOMAIN}" > ${CRT_FILE} [ -f caCert.pem ] || \ openssl x509 -in caCert.der -inform der -out caCert.pem -outform pem openssl rsa \ -in ${KEY_FILE} -out ${TARGET_HOST}Key.pem -inform der openssl x509 \ -in ${CRT_FILE} -inform der \ -out ${TARGET_HOST}Cert.pem -outform pem openssl pkcs12 \ -export \ -in ${TARGET_HOST}Cert.pem \ -inkey ${TARGET_HOST}Key.pem \ -certfile caCert.pem \ -out ${TARGET_HOST}.p12 # delete the key files, leaving only the key in the p12 file: rm ${KEY_FILE} ${TARGET_HOST}Key.pem
Assuming you call that script make-client-creds, you would run it once for each Android device:
$ ./make-client-creds phone1 $ ./make-client-creds phone2 ...
Copy the cert bundle (the p12 file only) to the SD card in the phone. You can mount the phone over USB or using ADB, e.g.
$ adb push phone1.p12 /sdcard/
Now go to the Android settings, select Security and Install from SD card. Follow the prompts.
Add the following line to /etc/ipsec.secrets
: RSA vpnKey.der
and add a stanza like the following to /etc/ipsec.conf
conn private-droid left=vpn.example.org leftsubnet=insert gateway IP here/32 leftcert=vpnCert.der leftid=@vpn.example.org leftfirewall=no lefthostaccess=no right=%any rightsourceip=192.168.10.0/24 auto=add
Finally, restart ipsec and you should be ready.
# service ipsec restart
Finally, install the app on the phone. This bit should be quite easy. Once installed, press the option ADD VPN, put in the DNS name of the VPN gateway (must match the name in the certificate, e.g. vpn.example.org from the example above) and tell it to use IKEv2 Certificate as the authentication type. Press to select a certificate and highlight the certificate that you installed earlier.
You should see a message on the phone telling you it is connected to the VPN.
If it fails, it will let you see the log messages. If you see the error Constraint check failed it often means that the subjectAltName was not included in the VPN gateway's certificate (see the steps above) or the DNS name doesn't match the name in the certificate.
On the server side, this command shows who is connected:
# ipsec status
Once the packets are decrypted by strongSwan on the VPN gateway, the kernel will route them appropriately just like any other packet. Use standard Linux netfilter/iptables rules to ensure that routing is restricted appropriately so that the clients can access the services they need and nothing else.
Please feel free to post comments below or discuss on the strongSwan Users mailing list
More news and policy statements regarding my campaign for Dublin Bay South:
Please print my brochure if you want Ireland to change