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.

15 thoughts to “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

  2. When running the commands the script generates I get this error:

    [ interfaces openvpn vtun0 ]
    OpenVPN configuration error: Must specify “mode”.

      1. Hi,

        Are you running “sudo -i” first?
        I have it working on an edgerouter POE version.

        Best regards,
        Alex

        1. I got the same error,

          I had to run the below commands before the commit would work;

          set interfaces openvpn vtun0 mode server
          set interfaces openvpn vtun0 server subnet 192.168.200.0/24
          set interfaces openvpn vtun0 server push-route 192.168.10.0/24
          set interfaces openvpn vtun0 server name-server 192.168.200.1
          set interfaces openvpn vtun0 openvpn-option “–port 1194”
          set interfaces openvpn vtun0 openvpn-option –tls-server
          set interfaces openvpn vtun0 openvpn-option “–comp-lzo yes”
          set interfaces openvpn vtun0 openvpn-option –persist-key
          set interfaces openvpn vtun0 openvpn-option –persist-tun
          set interfaces openvpn vtun0 openvpn-option “–keepalive 10 120”
          set interfaces openvpn vtun0 openvpn-option “–user nobody”
          set interfaces openvpn vtun0 openvpn-option “–group nogroup”
          set interfaces openvpn vtun0 openvpn-option ‘–plugin /usr/lib/openvpn/openvpn-auth-pam.so openvpn’

    1. You have to declare a mode for openVPN on the router. Two options I know of are “server” and “site-to-site”. If you’re connecting two routers via openVPN, use site-to-site, otherwise set it to server as LukeB did in this comment thread.

      @Alex – thanks much for this script! I modified it to use ecdsa for better security and to include some missing options. Email me if you want me to send you my tweaks.

      1. “I modified it to use ecdsa for better security and to include some missing options. Email me if you want me to send you my tweaks.”

        Why not just post them anyway?

      2. I am real new to this but am trying to set up my edgerouter X so that all traffic goes out thru the OpenVPN, My home network is for use by my family (wife, & grandkids) and is a mix of Windows, iOS, and a couple of Ubuntu systems. security is very important, but I also am trying to setup Kodi to record TV series and movies (which I am saving to my NAS) so they can access from their location. Any step-by-step guidance would be appreciated.

  3. Hello,

    I was happy to find this script, although when I ran it, I was getting an error: “CA certificate and CA private key do not match” during the first part of the key generation.

    Is this normal or is something wrong?

    I was saving the script to a file called openvpn and running sudo -i before executing the script.

    My Linux chops are rusty so if I’m going about running the script wrong to begin with, pointers would be great!

  4. Hi Alex,

    Is there any chance on a follow up to this with a how to revoke a certificate that has been created using a crl file?

  5. Hi There,

    Is there a way to adjust the script to make it create multiple user certificates or is it only designed for 1 shared client certificate?

    Regards,

Leave a Reply

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