OpenVPN Security Advisory: Dec 14, 2018
Action needed: Important update for OpenVPN Access Server

Additional security command line options

Change the encryption cipher for server and client

As of Access Server 2.5 we now use by default the encryption cipher AES-256-CBC. Older versions used BF-CBC. Since the OpenVPN programs used work with a single encryption scheme, meaning that clients and server must all agree to use the same encryption cipher, it is not possible to alter this from one side without affecting connectivity. If you change the cipher on an existing installation of Access Server, be prepared to reprovision or reinstall your already installed clients, so that they are updated correctly with instructions to use the new cipher, or they may simple be unable to connect. There is no automatic provisioning solution to automate this included in Access Server or the Connect Client. An exception is the OpenVPN Connect Client for Windows and macOS, if a server-locked profile is used. Those are updated automatically with the new cipher settings.

As of Access Server version 2.5, we have introduced 2 new configuration keys that you can use to alter the cipher used by clients and the server. If you install a fresh Access Server 2.5 or newer, the Access Server will automatically create these 2 configuration keys, and set these to AES-256-CBC, which is the current default for new Access Server 2.5+ installations. If you migrate old data from an older Access Server, or if you do an upgrade from an older Access Server, these configuration keys are not added automatically, and the Access Server will then assume you want to use BF-CBC, which was the old standard used on Access Server 2.1.12 and older. This way, we can maintain backward compatibility. If in the past you used the fields client config directives and server config directives in the Advanced VPN page of the Admin UI on an older Access Server to change the cipher to a custom setting, and have now migrated/updated to Access Server 2.5 or newer, then please remove these entries from those fields, and implement the new configuration keys instead.

The following information is valid only on Access Server 2.5 and newer. And of course the ciphers used must be one of the allowed type and must be the same on server and client side.

View current cipher configuration keys (if defined):

 ./sacli ConfigQuery | grep "cipher"

Remove cipher configuration keys to make Access Server assume old BF-CBC cipher:

./sacli --key "vpn.client.cipher" ConfigDel
./sacli --key "vpn.server.cipher" ConfigDel
./sacli start

Set the cipher configuration key to the desired cipher:

./sacli --key "vpn.client.cipher" --value <CIPHER> ConfigPut
./sacli --key "vpn.server.cipher" --value <CIPHER> ConfigPut
./sacli start

Valid values for <CIPHER>:

  • RC2-CBC
  • BF-CBC
  • RC2-40-CBC
  • RC2-64-CBC
  • AES-128-CBC
  • AES-192-CBC
  • AES-256-CBC
  • none

Mid-session TLS encryption key renegotiation

In the Admin UI this setting can be found in the Advanced VPN section. But it can also be controlled through the command line with a specific configuration key. This mid-session TLS renegotiation period controls when an OpenVPN client session will renegotiate the underlying SSL/TLS session and therefore the encryption key used. Normally this renegotiation is invisible to the end-user because the session token, if still valid, will be used as an authentication proxy/token. By default, this value is set to 360 minutes (6 hours). Session expiration will only be tested for during TLS renegotiation which occurs automatically at the specified schedule with this setting or when the connection is disrupted and reconnects. So if you change the session token expiration, make sure to adjust this parameter as well, or else the connection may not stop at the exact threshold that the session token timeout is set to, which may lead to connections that last longer than what you set your session token expiration parameter to.

Change the mid-session TLS renegotiation period (default 360 minutes):

./sacli --key "vpn.tls_refresh.interval" --value <MINUTES> ConfigPut
./sacli start

Restore this value to default:

./sacli --key "vpn.tls_refresh.interval" --value "360" ConfigPut
./sacli start

It is important to note that there is also a parameter in the OpenVPN protocol (no configuration key in Access Server) that determines after how many bytes a key should be renegotiated, and that in the past, Blowfish was the encryption cipher used, and we use this additional bytes threshold parameter for vulnerability mitigation. Unfortunately a flaw was found in Blowfish not so long ago that could be abused if enough data was gathered that used the same encryption key. To resolve this we have moved to AES-256 as the default but still allow Blowfish on older installations and clients, but have set the key renegotiation byte threshold at around 60 megabytes on up-to-date OpenVPN client programs, to prevent any possible gathering of enough data to exploit that particular flaw in the Blowfish encryption cipher.

Authentication failure lockout policy

As a security precaution the Access Server automatically locks out user accounts temporarily when authentication attempts fail repeatedly when using a server-locked profile in Connect Client, or when using the web services directly. The lockout policy will not be triggered when a user-locked profile is used with an OpenVPN client program since this requires that the user already has a valid connection profile with certificates for his account, and to be in possession of such a file you would most likely already have the correct credentials anyways (unless you stole the file from a user somehow – in which case the certificate should be revoked by an administrator), and the connection itself is also secured with the user’s personal certificate and key so it is extremely unlikely to be intercepted in some way. When repeated authentication failures occur through a server-locked profile in Connect Client, or via the web services directly, the user is temporarily banned from further login attempts. This is to prevent brute-forcing the password by endlessly trying different passwords. When this lockout is triggered on an account the user will receive a message like “LOCKOUT" or “user temporarily locked out due to multiple authentication failures". By default the lockout is triggered when a wrong password is entered 3 times consecutively. When the lockout is triggered and you wait 15 minutes, the lockout will be lifted. Lockouts can also be lifted manually by the administrator. The lockout policy is configurable with the settings below.

Set the number of authentication failures after which the user will be locked out (default is 3):

./sacli --key "vpn.server.lockout_policy.n_fails" --value <NUMBER> ConfigPut
./sacli start

Release the lockout on a user after the specified amount of seconds passes (default is 900 seconds, or 15 minutes):

./sacli --key "vpn.server.lockout_policy.reset_time" --value <SECONDS> ConfigPut
./sacli start

Maximum size of lockout dictionary (default is 10000):

./sacli --key "vpn.server.lockout_policy.max_history" --value <BYTES> ConfigPut
./sacli start

The lockout dictionary is used to keep track of all the hashes of wrong passwords that were entered by users recently. Unless you have thousands of users repeatedly entering incorrect passwords then the default value should be more than fine, and if you do have such a situation then you can increase the dictionary size. If the dictionary reaches its maximum size it will eventually be purged. The consequence of this dictionary reaching its limits with thousands of users entering wrong passwords is that if the failed authentication attempts are spread far enough apart (hours) that the number of authentication failures can be higher than configured. If however the failed authentication attempts occur shortly after one another then the number of authentication failures per user will be adhered to just fine. Generally you never need to adjust this value except in extreme circumstances which are very unlikely to ever occur. We recommend you do not change this value.

As mentioned an exception to the lockout policy are authentication attempts made with a valid user-locked connection profile. Additionally the so-called “bootstrap" users, which are special administrative users of which by default only one exists, are also an exception to the lockout policy. When Access Server is installed the initial administrative bootstrap user is called openvpn. This user account can always log in and does not adhere to the lockout policy. This account is meant to initially set up the server and to serve as a way to gain access to the Admin UI even when for example an external authentication backend like LDAP or RADIUS is failing. This allows you to correct any problems with LDAP/RADIUS settings in the Admin UI. In our security recommendations to secure the openvpn administrative user account we specifically advise you to disable this special bootstrap user after initial setup.

When you have run into the problem that your users have run into the automatic authentication lockout policy and are currently blocked, and you wish to unblock them, please follow the steps below. It is important to note that at this time it is not possible to unlock a single specific user. Instead what we advise is that you set the automatic lockout reset period to 1 second, wait a moment so that all lockouts are reset, and then to set the lockout period back to whatever you had it set to before. The below lines will do this and assumes your lockout policy automatic reset period is supposed to be set back to the default 15 minutes (900 seconds) afterwards and restarts the Access Server to clear any locked sessions.

./sacli --key "vpn.server.lockout_policy.reset_time" --value "1" ConfigPut
./sacli start
sleep 2
./sacli --key "vpn.server.lockout_policy.reset_time" --value "900" ConfigPut
./sacli start
service openvpnas restart

TLS authentication (HMAC firewall)

To explain the concept of TLS authentication in simpler terms, the idea here is to have a unique TLS key, a certificate, that is known and used by the server and its clients. A shared secret if you will, that will be used to digitally sign and verify packets in both directions. What this does is make it possible for the OpenVPN protocol to easily recognize if packets are truly VPN packets from a known VPN client, or if they are garbage packets from unknown sources. Every OpenVPN packet by itself contains encrypted information inside of it, but on top of that, the packet itself is signed digitally. The other party receiving the packet can then check if the signature matches with the known shared TLS key, and if it does, can then handle it further. If it doesn’t match, the packet is not from a known client and can be discarded. Aside from helping to filter away some attempts at denial of service attacks it also improves security by making other attacks impossible. It is simply an extra layer of security which is enabled by default on the OpenVPN Access Server.

There are unfortunately products on the market that do implement OpenVPN for connectivity to an OpenVPN server, but they come with a GUI that unfortunately does not give you the option to use TLS authentication. Some only have some menu options to provide a certificate, a key, and some encryption options for the OpenVPN tunnel, but no means to upload a configuration file or a TLS authentication key with the necessary instructions that the OpenVPN binary requires to implement TLS. This leads to the odd situation that the OpenVPN binary in the product can support TLS authentication, but there is no way to configure it to use it. In these situations if connectivity is required it is possible to disable TLS authentication. Unfortunately this is an option that cannot be set per user account. This is a server-wide global setting. It can be disabled or enabled from the Admin UI under “Advanced VPN" or in the command line with the commands below.

Enable TLS authentication (default):

./sacli --key "vpn.server.tls_auth" --value ="true" ConfigPut
./sacli start

Disable TLS authentication:

./sacli --key "vpn.server.tls_auth" --value="false" ConfigPut
./sacli start

It is important to note that when switching a server from one mode to another, to enable or disable TLS authentication, requires that all the clients currently installed are reconfigured for the new setting. OpenVPN Connect Client installations with a server-locked profile will automatically retrieve an updated connection profile when they next log on, but any clients that have a stored copy of a user-locked or auto-login type profile will need to be reconfigured or provided with a new connection profile in order to be able to connect again to a server that previously had a different TLS authentication setting.

Google Authenticator multi-factor authentication

The basic principle of how Google Authenticator works is reasonably simple but very secure. The server and the program, for example the Google Authenticator app for Android or iOS that generates your 6 digit codes, both need to know the current time and date. If they deviate too much then this can cause the codes to not correspond and thus not work. Timezones are automatically adjusted for so this is not an issue unless you set the timezone wrong. With the correct current time and a shared secret 16 character random text string agreed upon by the server and the Google Authenticator application when you go through an initial enrollment procedure, a computation is done that results in a 6 digit code. Every 30 seconds, the computation is repeated and a new 6 digit code results. When you make a connection using a correctly enrolled user account that requires Google Authenticator code, you will be asked for your user name, your password, and finally the Google Authenticator 6 digit code for that specific moment. It is only valid within a small window of time (about 30 seconds). This way anyone peeking over your shoulder still won’t be able to somehow use the gathered information to make a connection, because they don’t have the shared secret key that generates the unique 6 digit codes every 30 seconds.

It is also important for security reasons to know that at no point a connection with Google’s systems is made when enrolling a user, generating a shared secret key, or generating 6 digit one-time passwords. Everything happens within the Access Server itself without requiring outside contact with any servers or services, and within the application used to generate the 6 digit codes. The specifications of the Google Authenticator system have been made public and the code is, to put it oversimplified, a matter of: “shared key * current time = 6 digit code". To give users some leeway in entering the code, the Access Server will accept the current valid code, the one just before it, and the one just after it. This creates a slightly larger window of time in which a user can enter the 6 digit code. More information on the conceptual and technical aspects of Google Authenticator can be found on this Google Authenticator WikiPedia page.

The Access Server supports the Google Authenticator multi-factor authentication system, but it is not enabled by default. It can be enabled via the Admin UI under “Client Settings" or via the command line with the command line examples given below. It is also possible to enable or disable the requirement for a Google Authenticator per user or per group. This can be important if for example for some reason a client device making a VPN connection is unable to provide the Google Authenticator key by itself. To use Google Authenticator you need an application or device that can accept a Google Authenticator type shared secret, and with that generate 6 digit codes that change every 30 seconds. A smartphone with Android, iPhone, or BlackBerry for example can do this with the free Google Authenticator app. There are also plugins for browsers and applications for tablets and desktop computers, as well as separate credit card sized (or smaller) devices that can be provided with the unique key and can generate keys for years off the built-in battery. For a list of known compatible devices and applications please look at the client and devices compatibility list. (UNFINISHED MARKER – our apologies, this section of the documentation is under construction and will be finished later)

Disable Google Authenticator globally for all users and groups (the default):

./sacli --key "vpn.server.google_auth.enable" --value "false" ConfigPut
./sacli start

Enable Google Authenticator globally for all users and groups:

./sacli --key "vpn.server.google_auth.enable" --value "true" ConfigPut
./sacli start

Disable Google Authenticator for a specific user or group:

./sacli --user <USER_OR_GROUP> --key "prop_google_auth" --value "false" UserPropPut

Enable Google Authenticator for a specific user or group:

./sacli --user <USER_OR_GROUP> --key "prop_google_auth" --value "true" UserPropPut

Undo an enable/disable override for Google Authenticator on a group or user, so that it inherits the setting instead:

./sacli --user <USER_OR_GROUP> --key "prop_google_auth" UserPropDel

To unlock an already scanned and locked secret for a user, so the user can obtain/scan it again:

./sacli --user <USER> --lock 0 GoogleAuthLock

To manually lock a secret key, for example when you as administrator have already set up the user’s device yourself:

./sacli --user <USER> --lock 1 GoogleAuthLock

To generate a new secret key and unlock it so the user can enroll anew:

./sacli --user <USER> --lock 0 GoogleAuthRegen

To generate a new secret key and lock it so the user must obtain the secret key from the server administrator:

./sacli --user <USER> --lock 1 GoogleAuthRegen

The GoogleAuthLock and GoogleAuthRegen functions that actually handle these two keys, which can also be edited manually:

./sacli --user <USER> --key "pvt_google_auth_secret" --value <GOOGLE_AUTH_SECRET> UserPropPut
./sacli --user <USER> --key "pvt_google_auth_secret_locked" --value <SCANNED/LOCKED> UserPropPut

Where <GOOGLE_AUTH_SECRET> must be a 16 character alphanumerical value in capitals and must be known at the Google Authenticator device/application to generate the 6 digit codes, and the <SCANNED/LOCKED> value must be either 1 or 0, indicating that the code is scanned and must now be used by the user, or is awaiting enrollment by the user.
If a user’s device that contains the Google Authenticator application with the shared key in it has been lost, stolen, or otherwise compromised, you should use the sacli GoogleAuthRegen command as shown in the examples above to generate a new unique secret key for his account, making it impossible for the old secret key to be used. This command also unlocks the account Google Authenticator enrollment so that the user can enroll again. As an aside, the GoogleAuthRegen command also generates on the command line a string with otpauth:// URI format that can be used in a QR code generator. Of course in the client web service the Access Server already does this for the user, but this could be some use for customized process automation.

An exception to the Google Authenticator requirement is for obvious reasons any client using the auto-login type connection profiles. A common problem people encounter is creating a user account with auto-login privileges, and then downloading and installing an OpenVPN Connect Client from the Access Server. Such an installation will come bundled with an auto-login type profile. Enabling the Google Authenticator afterwards on such an account will not make this Connect Client installation require a Google Authenticator password to make a connection. It will simply use its stored copy of the auto-login type profile to make a connection. To resolve this, remove the auto-login privilege from this user account, and uninstall the already installed Connect Client. Now download a new copy from the client web service and install it. It will now be configured with a server-locked connection profile, and will ask for user name, password, and Google Authenticator to make a connection. Of course don’t forget to enroll the user with a Google Authenticator application or else you will receive a message telling you to complete the enrollment.

Another exception to the Google Authenticator requirement is less obvious. The default bootstrap administrative user account called openvpn is an exception to the requirement for Google Authenticator. It can log in without having to enter a valid Google Authenticator code. This is done on purpose so that this user can always log in and correct problems. So if you are testing with this account and aren’t asked for Google Authenticator code, you now know why this is so. Also, during initial configuration, it is possible to reconfigure the user name so it does not specifically have to be called openvpn, but in most cases it is.

This of course begs the question on how to secure this account when you want Google Authenticator to be required. The suggested solution is to create a new normal user account in the Access Server and giving it admin privileges and enrolling it in Google Authenticator. This will then be your new administrative user account for the Admin UI. And this account will require a valid Google Authenticator code to log on. Then disable the openvpn user account in the operating system with the command below. It removes the password from the account, and by default in a Linux operating system, an account without a password cannot be used to log in at all.

Disable the openvpn bootstrap user account:

passwd -d openvpn

To undo this action or to reset the password use this command:

passwd openvpn

We highly recommend installing an NTP client service in the operating system that the Access Server is installed on. This Network Time Protocol will contact public time servers on the Internet to get the current date and time, which are required for Google Authenticator to function properly, and corrects any time drift that can occur on the server. Especially cloud-based virtual machines are susceptible to time drift. A deviation of 30 seconds can already be a problem when it comes to Google Authenticator. Usually these programs come preconfigured and require little to no configuration.

To install an NTP client on Ubuntu/Debian systems:

apt-get install ntp

To install an NTP client on Red Hat/CentOS systems:

yum install ntp

Selecting TLS level for the OpenVPN daemons

The default for OpenVPN daemons on the Access Server in the past has been to use TLS 1.0. Later support was added to use TLS 1.1 and TLS 1.2 on the OpenVPN protocol. Older clients however may not know how to deal with this. For example an OpenVPN client from December 2014 will not be able to connect to an OpenVPN server that requires TLS 1.1 or TLS 1.2. Also, if you have your server set to TLS 1.0 on the OpenVPN daemons now and you have OpenVPN connection profiles and client software installed on a large number of clients, it is recommend to stay with TLS 1.0 and not to upgrade it to TLS 1.1 or TLS 1.2. Likewise the reverse is true if for some reason you downgrade from TLS 1.1 or 1.2 down to 1.0. The reason for this is that connection profiles can be either configured for the old method where TLS 1.0 is assumed, or can be configured for the new method where a minimum version of TLS is configured in the connection profile and it then expects that version or higher to be present. In other words, switching it between TLS 1.0 and TLS 1.1/1.2 will require that some clients need a new copy of the connection profile or need to be updated or reinstalled. It is important to be aware of these consequences before changing the setting.

As of OpenVPN Access Server 2.1.12 the default OpenVPN daemons TLS setting is 1.2. During upgrades from older version the previous setting is maintained to avoid breaking existing setups. The minimum TLS level setting for the OpenVPN daemons can be configured in the Admin UI in the “SSL/TLS Settings" page. Below are the commands to reconfigure this on the command line.

Set minimum allowed TLS level to 1.0 (legacy):

./sacli --key "vpn.server.tls_version_min" --value "1.0" ConfigPut

Set minimum allowed TLS level to 1.1:

./sacli --key "vpn.server.tls_version_min" --value "1.1" ConfigPut

Set minimum allowed TLS level to 1.2 (the default):

./sacli --key "vpn.server.tls_version_min" --value "1.2" ConfigPut

Disable use of client certificates

Using unique client certificates and private keys is a major underpinning of the security of the OpenVPN protocol. Each user account is given a unique public key and private key and these uniquely identify the client to the server and have an important role in encryption and decryption of traffic. It is enabled by default and managed automatically by the OpenVPN Access Server. We recommend that you leave this option enabled and that you do not disable it. However, in rare cases, for example within networks that are secure already, it can be desirable to get rid of any overhead and use the Access Server program purely for the VPN tunneling functions without bothering with unique certificates for the users. If this is what you want to do then it is indeed possible to disable the use of client certificates. In such a case simple user name and password authentication is used instead. But please do be aware of the security implications as this lowers the security of the OpenVPN protocol significantly.
With client certificates disabled, the Access Server will no longer use the certificates database file. The Access Server still does need access to specific certificates and keys in there to be able to handle encryption and decryption, and for basic functionality. Therefore it is necessary to copy the required files out of the certificates database file and into the configuration database. This can be done with the following commands.

cd /usr/local/openvpn_as/scripts
mkdir -p server-certs
./sacli -o server-certs GetServer
pushd server-certs
../confdba -mk external_pki.ca_crt --value_file ca.crt
../confdba -mk external_pki.server_crt --value_file server.crt
../confdba -mk external_pki.server_key --value_file server.key
../confdba -mk external_pki.ta_key --value_file ta.key
../confdba -mk external_pki.dh_pem --value_file dh*.pem

Next edit the as.conf file and add the following options:

nano /usr/local/openvpn_as/etc/as.conf

In this file go all the way to the bottom and then add this line:


And then restart the OpenVPN Access Server service:

service openvpnas restart

Now the Access Server will function without client certificates. Any connection profiles generated by the Access Server now will not include the public key or private key for a client. Connections are now only possible by using user name and password authentication.