03 July 2010
Due to a variety of circumstances out of my control, I found it necessary to control access to an OpenVPN server without depending on a certificate revocation list. After some effort, I discovered a way to execute a script that can check the common name of the client certificate and use the return code to authorize the connection.
First, create a whitelist file. One CN per line. For example, let’s say you have three openvpn clients:
# cat CN_whitelist client1 client2 client3
Second, create a verify-cn script. Here’s mine:
#!/usr/local/bin/python # original from http://svn.openvpn.net/projects/openvpn/trunk/openvpn/sample-scripts/verify-cn # verify-cn -- whitelist based on common name of client certificates # # Return 0 if cn matches the common name component of # X509_NAME_oneline, 1 otherwise. # # In OpenVPN, enable like this: # # tls-verify "./verify-cn whitelist_file" # # This would cause the connection to be dropped unless # the client common name is in whitelist_file. # # Format of whitelist_file is simple one CN per line. # import re, sys if len(sys.argv) < 4: sys.exit("Usage: %s whitelist_file depth x509_subject" % sys.argv) whitelist_file = sys.argv depth = int(sys.argv) x509 = sys.argv ## If depth is nonzero, tell OpenVPN to continue processing ## the certificate chain. if depth!=0: sys.exit(0) m = re.search(r'\/CN=([^\/]+)', x509) if m and m.group(1): # read whitelist f = open(whitelist_file, 'r') for line in f: if (m.group(1) == line.rstrip()): sys.exit(0) sys.exit(1) # reject
Then add the following to openvpn.conf:
tls-verify "./verify-cn CN_whitelist"
I’m not sure this should be a primary means of security. However, it could be useful in cases like mine where the crl was not sufficient.
It is useful in addition to a crl because a crl is a blacklist, while this is a whitelist. If it’s possible that some keys have been created that you may not be aware of, this might prevent them from slipping through.