6

I'm running OpenVPN 2.3.2 (still a newbie at this) in an Ubuntu 14.04 Server machine. I want to be able to disable/reenable clients that connect to my OpenVPN server.

I followed this guide for revoking a client's certificate, but it seems that this move is irreversible. Also, if I revoke a client's certificate, and the client is already connected, the connection does not seem to stop. I want the connection to stop immediately.

Is there any easy way to disable and reenable clients?

My server.conf file:

# OpenVPN server configuration file
dev tun
proto udp
port 1194
server 10.8.0.0 255.255.255.0
ca /usr/share/easy-rsa/keys/ca.crt
cert /usr/share/easy-rsa/keys/vpnserver.crt
key /usr/share/easy-rsa/keys/vpnserver.key
dh /usr/share/easy-rsa/keys/dh2048.pem
push "dhcp-option DNS 8.8.8.8"
push "redirect-gateway def1"
comp-lzo
keepalive 10 60
persist-tun
persist-key
user panos
group panos
log-append /var/log/openvpn.log
verb 3
# crl-verify keys/crl.pem

The last line is for the guide above.

Thank you.

3
  • Why not assign IP addresses per user and then use iptables to block/allow IP?
    – davidgo
    Aug 27, 2017 at 16:42
  • I don't know. I think that the solution you suggest is a little bit "dirty". Iptables is something irrelevant than the VPN mechanism. Also if someone has a way to change his IP then he could easily re-connect with the same certificate.
    – panos
    Aug 28, 2017 at 18:02
  • I'd just point out that I'm suggesting that the IP blocked is the one issued by the VPN server - so - if correctly set up server side the user could not reconnect with the same cert.
    – davidgo
    Aug 28, 2017 at 22:25

4 Answers 4

6

I implemented a solution similar to davidgo's. Unfortunately I faced an openssl error similar to this bug, and it took me a lot of time to find a workaround for this.

I wrote finally two scripts for revoking and unrevoking client certificates:

revoke.sh:

#!/bin/bash

keys_index_file=/usr/share/easy-rsa/keys/index.txt
fileline="$(grep "/CN=$1/" $keys_index_file)"
columns_number="$(echo $fileline | awk -F' ' '{print NF;}')"

if [[ $columns_number -eq 5 ]] && [[ $fileline == V* ]]; then

    source /usr/share/easy-rsa/vars 
    /usr/share/easy-rsa/revoke-full $1

    {
        sleep 3
        echo kill $1
        sleep 3
        echo exit
    } | telnet localhost 7505

    echo "Client certificate revoked successfully."
    exit 0;

elif [[ $columns_number -eq 6 ]] && [[ $fileline == R* ]]; then

    echo "Client certificate is already revoked."
    exit 0;

else

    echo "Error; key index file may be corrupted."
    exit 1;
fi

unrevoke.sh:

#!/bin/bash

keys_index_file=/usr/share/easy-rsa/keys/index.txt
linenumber="$(grep -n "/CN=$1/" $keys_index_file | cut -f1 -d:)"
fileline="$(grep -n "/CN=$1/" $keys_index_file)"
line="$(grep "/CN=$1/" $keys_index_file)"

columns_number="$(echo $line | awk -F' ' '{print NF;}')"
echo $columns_number



if [[ $columns_number -eq 6 ]] && [[ $line == R* ]]; then

    column2="$(echo $fileline | awk '{print $2}')"
    column4="$(echo $fileline | awk '{print $4}')"
    column5="$(echo $fileline | awk '{print $5}')"
    column6="$(echo $fileline | awk '{print $6}')"
    echo -e "V\t$column2\t\t$column4\t$column5\t$column6" >> $keys_index_file
    sed -i "${linenumber}d" $keys_index_file
    cd /usr/share/easy-rsa; source ./vars; openssl ca -gencrl -out "keys/crl.pem" -config "$KEY_CONFIG"

    echo "Certificate unrevoked successfully."
    exit 0;

elif [[ $columns_number -eq 5 ]] && [[ $fileline == V* ]]; then

    echo "Certificate is already unrevoked and active"
    exit 0;

else

    echo "Error; Key index file may be corrupted."
    exit 1;

fi

Note that revoke.sh script also opens a telnet connection with openVPN and kicks out the client to be revoked.

0
2

Panos answer was correct as of 5 years ago. So it deserves a thumbs up. However since then, what has happened is the vars directory has been moved / removed, the /usr/share/easy-rsa directory doesn't seem to be present anymore and the $KEY_CONFIG seems to either not be there or coupled to the vars directory, which as i say seems to no longer be there, at least in Ubuntu 21.10 (April 2022).

I found this script submitted into github, and it looked good to me, I ran it and it worked, it unrevoked my revoked certificate.

#!/bin/bash
set -e

keys_index_file="/etc/openvpn/server/easy-rsa/pki/index.txt"
linenumber="$(grep -n "/CN=$1"'$' $keys_index_file | cut -f1 -d: | head -1)"
fileline="$(grep -n "/CN=$1"'$' $keys_index_file | head -1)"
line="$(grep "/CN=$1"'$' $keys_index_file | head -1)"

columns_number="$(echo $line | awk -F' ' '{print NF;}')"
echo $columns_number

if [[ $columns_number -eq 6 ]] && [[ $line == R* ]]; then

    column2="$(echo $fileline | awk '{print $2}')"
    column4="$(echo $fileline | awk '{print $4}')"
    column5="$(echo $fileline | awk '{print $5}')"
    column6="$(echo $fileline | awk '{print $6}')"
    echo -e "V\t$column2\t\t$column4\t$column5\t$column6" >> $keys_index_file
    sed -i "${linenumber}d" $keys_index_file

    cd /etc/openvpn/server/easy-rsa
    EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
    rm -f /etc/openvpn/server/crl.pem
    cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
    # CRL is read with each client connection, when OpenVPN is dropped to nobody
    chown nobody:nogroup /etc/openvpn/server/crl.pem

    echo "Certificate unrevoked successfully."
    exit 0;

elif [[ $columns_number -eq 5 ]] && [[ $fileline == V* ]]; then

    echo "Certificate is already unrevoked and active"
    exit 0;

else

    echo "Error; Key index file may be corrupted."
    exit 1;

fi

To run the script, you provide it with the name of the vpn certificate that you've revoked. This will be as it appears in the index.txt file in the /etc/openvpn/server/easy-rsa/pki/ directory on the command line. So copy and paste this into a file, say unrevoke.sh then run:

chmod 777 unrevoke.sh
./unrevoke.sh <Openvpn-Cert-name>

Now, I understand the arguments for why you should not unrevoke certificates. But this was an emergency.

Let me explain the circumstances:

I'm a developer working for a startup. I'm not a network admin or a system admin so i'm not the best person to ask, but there's nobody else to ask at all, so the responsibility fell onto me.

Essentially what had happened is we needed to move a piece of remote and unsupervised equipment from one vpn to another. Despite all our testing on the new vpn we (by that i mean "I") overlooked the fact that the system would by default try to send everything via the vpn. Including streaming tens of gigabytes of data across a 4G connection.

Naturally after switching the system became totally unresponsive and we couldn't logon via either vpn connection (nor through teamviewer). After trying to work out why, i came to the conclusion that it was because it was trying to stream data through the internet back to itself and that would probably cost us thousands in bills.

To mitigate the situation while i thought about how to resolve the issue, i revoked the vpn certificate, so at least the bandwidth it's trying to use is just limited to connection attempts not huge data streams.

The command i used to revoke the vpn cert was:

openvpn-install.sh

This comes with the openvpn installation and it provides a way to revoke a given certificate.

In the middle of the night, i worked out that there's a way to push the from the openvpn server config more specific routing information to stop it streaming everything. So I did that, and i unrevoked the revoked openvpn certificate.

Sure enough, after about 20-30 minutes the remote equipment picked up the vpn changes and began to calm down enough so that i could log in and revert the VPN back to the old settings before we tried to switch it over and the system was recovered.

I'm not going to lose my job over this. But someone else in a different company might. Anyway, I just wanted to share with you my experience and insight into why you might want to unrevoke a vpn certificate.

1

Wishing for a way to be able to activate/deactivate openvpn users without having to give them another *.ovpn configuration file derived me find this page.

I tried the Owl's answer and it is fine for the first round of revoke/unrevoke. But if you want to revoke a user for a second time easy-rsa will throw error because it cannot find valid *.crt, *.key and *.pem files to delete and move to /etc/openvpn/easy-rsa/pki/revoked directory.

So the solution is to add 3 lines to Owl's answer to copy back files to their original directories. They are:

cp /etc/openvpn/easy-rsa/pki/revoked/certs_by_serial/$column4.crt /etc/openvpn/easy-rsa/pki/issued/$1.crt
mv /etc/openvpn/easy-rsa/pki/revoked/certs_by_serial/$column4.crt /etc/openvpn/easy-rsa/pki/certs_by_serial/$column4.pem
mv /etc/openvpn/easy-rsa/pki/revoked/private_by_serial/$column4.key /etc/openvpn/easy-rsa/pki/private/$1.key

The unrevoke script will become:

#!/bin/bash
set -e

keys_index_file="/etc/openvpn/server/easy-rsa/pki/index.txt"
linenumber="$(grep -n "/CN=$1"'$' $keys_index_file | cut -f1 -d: | head -1)"
fileline="$(grep -n "/CN=$1"'$' $keys_index_file | head -1)"
line="$(grep "/CN=$1"'$' $keys_index_file | head -1)"

columns_number="$(echo $line | awk -F' ' '{print NF;}')"
echo $columns_number

if [[ $columns_number -eq 6 ]] && [[ $line == R* ]]; then

    column2="$(echo $fileline | awk '{print $2}')"
    column4="$(echo $fileline | awk '{print $4}')"
    column5="$(echo $fileline | awk '{print $5}')"
    column6="$(echo $fileline | awk '{print $6}')"
    echo -e "V\t$column2\t\t$column4\t$column5\t$column6" >> $keys_index_file
    sed -i "${linenumber}d" $keys_index_file

    cd /etc/openvpn/server/easy-rsa
    EASYRSA_CRL_DAYS=3650 ./easyrsa gen-crl
    rm -f /etc/openvpn/server/crl.pem
    cp /etc/openvpn/server/easy-rsa/pki/crl.pem /etc/openvpn/server/crl.pem
    # CRL is read with each client connection, when OpenVPN is dropped to nobody
    chown nobody:nogroup /etc/openvpn/server/crl.pem
    cp /etc/openvpn/easy-rsa/pki/revoked/certs_by_serial/$column4.crt /etc/openvpn/easy-rsa/pki/issued/$1.crt
    mv /etc/openvpn/easy-rsa/pki/revoked/certs_by_serial/$column4.crt /etc/openvpn/easy-rsa/pki/certs_by_serial/$column4.pem
    mv /etc/openvpn/easy-rsa/pki/revoked/private_by_serial/$column4.key /etc/openvpn/easy-rsa/pki/private/$1.key
    echo "Certificate unrevoked successfully."
    exit 0;

elif [[ $columns_number -eq 5 ]] && [[ $fileline == V* ]]; then

    echo "Certificate is already unrevoked and active"
    exit 0;

else

    echo "Error; Key index file may be corrupted."
    exit 1;

fi
0

Ignoring the iptables option (which I believe is technically superior), you can revoke and reinstate private keys by modifying the revokation file and reloading openvpn. (If you are using easyRSA you can edit easyRSA/index.txt. Find the appropriate line and change the "R" flag to a "V" flag, remove the third column.) Then

  source ./vars
  openssl ca -gencrl -out "crl.pem" -config "$KEY_CONFIG"

You can reload the opening server to make the new config take effect. This will kick ALL the clients, but they should automatically reconnect and negotiate a new session.

See http://sq4ind.eu/openvpn-revoke-unrevoke-certificates/ for the reference article this solution is based on.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .