OpenVPN with Modern Cryptography
The standard OpenVPN installation uses RSA and a hefty Diffie-Hellman parameters file. This is not ideal, but it’s possible to run OpenVPN using elliptic curves.
This was all done on OpenVPN 2.4.1. As far as I know, elliptic curve cryptography support in OpenVPN is for 2.4.0+.
PKI
Get Easy-RSA and set up variables in the vars
file.
set_var EASYRSA_ALGO ec set_var EASYRSA_CURVE secp521r1 set_var EASYRSA_DIGEST "sha512"
The choice of curve is a personal one. secp521r1
is P-521. DJB considers it a nice prime. All supported curves are listed with openvpn --show-curves
(these are mine).
There’s a bug in Easy-RSA regarding sourcing this file. The workaround is to export EASYRSA_VARS_FILE=/etc/easy-rsa/vars
(or put it in .bashrc
or whatever).
Make the PKI and build the CA with easyrsa init-pki
, easyrsa build-ca
.
easyrsa gen-req servername nopass easyrsa sign-req server servername easyrsa gen-req clientname [nopass] easyrsa sign-req client clientname
We now have all the server files
pki/ca.crt pki/issued/servername.crt pki/private/servername.key
and all the client files
pki/ca.crt pki/issued/clientname.crt pki/private/clientname.key
(there’s some nonsense about 3DES-encrypting the client key, which I’m ignoring).
If you didn’t set the nopass
option but now regret it, run openssl ec -in clientname.key -out clientname_nopass.key
, enter your password and rename the keys.
VPN
Copy the server and client files to their respective OpenVPN directories.
Here’s an example server configuration.
port 1194 proto udp dev tun ca ecc/ca.crt cert ecc/servername.crt key ecc/servername.key dh none server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway def1" push "dhcp-option DNS 1.2.3.4" keepalive 10 120 tls-crypt ecc/tc.key auth SHA512 keysize 256 tls-server tls-version-min 1.2 tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 cipher AES-256-GCM reneg-sec 360 remote-cert-eku "TLS Web Client Authentication" script-security 2 auth-user-pass-verify /etc/openvpn/server/auth/auth.py via-file user nobody group nobody persist-key persist-tun status openvpn-status.log explicit-exit-notify 1
And a client configuration.
client dev tun proto udp remote serverurl 1194 resolv-retry infinite nobind #user nobody #group nobody persist-key persist-tun tls-client mute-replay-warnings ca servername/ecc/ca.crt cert servername/ecc/clientname.crt key servername/ecc/clientname.key remote-cert-eku "TLS Web Server Authentication" verify-x509-name 'CN=servername' subject remote-cert-tls server tls-crypt servername/ecc/tc.key cipher AES-256-GCM auth SHA512 tls-version-min 1.2 tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 reneg-sec 360 #comp-lzo verb 3 #mute 20 auth-user-pass servername/secret.password redirect-gateway def1 script-security 2 up /etc/openvpn/client/servername/update-resolv-conf.sh down /etc/openvpn/client/servername/update-resolv-conf.sh
For several devices/users, managing certs, etc., can be tedious to do by hand. I wrote some code to automate it.