Easy certificate generation for openvpn

This script automates the process of generating certificates for OpenVPN on the edgerouter. Place this script under /config/openvpn and chmod it 755. Remember to edit the setup part of the script before running it. All output files are saved in cwd.

#!/bin/bash

#-----------------------------------------------------------------------------------------------
# Setup

CAname=Alex-CA
CAsubject="/C=DK/ST=SomeCity/L=SomeCity/O=CAworld"
CAexpire=1000
CAkeyLength=2048

ServerName=vpn.mydomain.com
ServerSubject="/C=DK/ST=SomeCity/L=SomeCity/O=ServerWorld/CN=${ServerName}"
ServerExpire=1000
ServerKeyLength=2048

ClientName=myclient
ClientSubject="/C=DK/ST=SomeCity/L=SomeCity/O=ClientWorld/CN=${ClientName}"
ClientExpire=1000
ClientKeyLength=2048

DHkeyLength=1024

#-----------------------------------------------------------------------------------------------
# Functions

function makeCA () {
	CAname=$1
	CAexpire=$2
	CAsubject=$3
	CAkeyLength=$4
	printf "Generating Certificate Authority ${CAname}...\n\n"

	openssl genrsa -out ${CAname}.key ${CAkeyLength} 
	openssl req -x509 -new -nodes -key ${CAname}.key -sha256 -days ${CAexpire} -out ${CAname}.pem -subj $CAsubject 
}

function makeCert () {
	CAname=$1
	CertName=$2
	CertExpire=$3
	CertSubject=$4
	CertKeyLength=$5
	printf "\nGeneration certificate for ${CertName}...\n\n"

	ConfigFile=`mktemp`
	printf 'basicConstraints = CA:FALSE\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid' > ${ConfigFile}

	openssl genrsa -out ${CertName}.key ${CertKeyLength}
	openssl req  -new -key ${CertName}.key -out ${CertName}.csr -subj ${CertSubject} 
	openssl x509 -req -extfile ${ConfigFile} -in ${CertName}.csr -CA ${CAname}.pem -CAkey ${CAname}.key \
		     -CAcreateserial -out ${CertName}.crt -days ${CertExpire} -sha256

	rm ${CertName}.csr
	rm ${ConfigFile}
}

function makeOvpnFile () {
	CAname=$1
	ClientName=$2
	HostName=$3
	printf "\nGenerating .ovpn file ${ClientName}.ovpn...\n\n"

	echo client > ${ClientName}.ovpn
	echo dev tun >> ${ClientName}.ovpn
	echo proto udp >> ${ClientName}.ovpn
	echo remote ${HostName} 1194 >> ${ClientName}.ovpn
	echo cipher AES-256-CBC >> ${ClientName}.ovpn
	echo auth SHA256 >> ${ClientName}.ovpn
	echo resolv-retry infinite >> ${ClientName}.ovpn
	echo redirect-gateway def1 >> ${ClientName}.ovpn
	echo nobind >> ${ClientName}.ovpn
	echo comp-lzo yes >> ${ClientName}.ovpn
	echo persist-key >> ${ClientName}.ovpn
	echo persist-tun >> ${ClientName}.ovpn
	echo user nobody >> ${ClientName}.ovpn
	echo group nogroup >> ${ClientName}.ovpn
	echo verb 3 >> ${ClientName}.ovpn
	echo setenv ALLOW_PASSWORD_SAVE 0 >> ${ClientName}.ovpn 
	echo auth-user-pass >> ${ClientName}.ovpn
	echo '<ca>' >> ${ClientName}.ovpn
	cat ${CAname}.pem >> ${ClientName}.ovpn
	echo '</ca>' >> ${ClientName}.ovpn
	echo '<cert>' >> ${ClientName}.ovpn
	cat ${ClientName}.crt >> ${ClientName}.ovpn
	echo '</cert>' >> ${ClientName}.ovpn
	echo '<key>' >> ${ClientName}.ovpn
	cat ${ClientName}.key >> ${ClientName}.ovpn
	echo '</key>' >> ${ClientName}.ovpn
}

function showConfGuide () {
	CAname=$1
	ServerName=$2
	printf "\nAdd these configuration lines to your edgerouter...\n\n"

	CurrentPath=`pwd`
	echo set interfaces openvpn vtun0 tls ca-cert-file ${CurrentPath}/${CAname}.pem
	echo set interfaces openvpn vtun0 tls cert-file ${CurrentPath}/${ServerName}.crt
	echo set interfaces openvpn vtun0 tls key-file ${CurrentPath}/${ServerName}.key
	echo set interfaces openvpn vtun0 tls dh-file ${CurrentPath}/dh.pem
}

function makeDH () {
	DHkeyLength=$1
	printf "\nMaking diffie-hellman keypair for perfect forward secrecy...\n\n"

	openssl dhparam -out dh.pem -2 ${DHkeyLength}
}

#-----------------------------------------------------------------------------------------------
# Make everything

makeCA ${CAname} ${CAexpire} ${CAsubject} ${CAkeyLength}
makeCert ${CAname} ${ServerName} ${ServerExpire} ${ServerSubject} ${ServerKeyLength}
makeCert ${CAname} ${ClientName} ${ClientExpire} ${ClientSubject} ${ClientKeyLength}
makeDH ${DHkeyLength}
makeOvpnFile ${CAname} ${ClientName} ${ServerName} 
showConfGuide ${CAname} ${ServerName}

The script will make three certificates. a CA authority, a server certificate and a client certificate. It will also generate a finished .ovpn file you can use on your client devices. It even ends up telling you what lines to add to your edgerouter config.

2 thoughts on “Easy certificate generation for openvpn

  1. Hi Alex,

    Thanks for creating that wonderful script.

    I am trying to replace several ASUS routers running OpenVPN with Edgerouters, but it is critical for me that I can duplicate the OpenVPN functionality of the ASUS+Merlin SW on the ER.

    I had no problem editing and running it to create my client.ovpn file.

    However at the end of the run I get this message:

    “Add these configuration lines to your edgerouter…

    set interfaces openvpn vtun0 tls ca-cert-file /home/rob/Sunol-CA.pem
    set interfaces openvpn vtun0 tls cert-file /home/rob/sunol.robinett.us.crt
    set interfaces openvpn vtun0 tls key-file /home/rob/sunol.robinett.us.key
    set interfaces openvpn vtun0 tls dh-file /home/rob/dh.pem”

    Where do I make those changes? I can’t execute those as command lines.

    Then when I load and run that client.ovpn into the Tunnellblik OpenVPN client on my Mac, I get a warning “Use ‘down-root’ plugin for OpenVPN …’ dialog box. Selecting that gets me into a user/password login dialog, which I assume is my ERM admin account, After entering my user/admin the Tunnellblick client rapidly cycles through the login failures until I abort Tunnellblick.

    Knowing little about the ERM environment and less about OpenVPN administration, I would appreciate some direction. It seems that I may not understand how to configure and start the OpenVPN service on the ERM and in addition there may be some incompatibility between the ERM OVPN and my Tunnelblick client.

    Your help would be much appreciated.

    1. Hi Rob,

      When you ssh to your router you go to configure mode with this command:
      configure

      Then you can past the set interfaces lines….

      after that you type:
      commit
      save

Leave a Reply

Your email address will not be published. Required fields are marked *