Installing a signed SSL certificate

The web services secure the connection between the web browser and the web server using an SSL certificate. When you install the Access Server, it generates a self-signed certificate so that the web server can at least start up and be used. This produces the inevitable warnings in the web browser like “Unable to verify authenticity” or other such ominous messages. In this particular these messages are expected and in order to make a connection to the web services initially you will have to bypass this warning message. But ideally you would next assign an FQDN (Fully Qualified Domain Name) to your Access Server installation and set up the required DNS record for this. Once you have an FQDN and DNS record correctly configured you can generate your own private key and use it to create a CSR (Certificate Signing Request) which you can send to a trusted party to get it validated and signed. Once that is done you can install the signed certificate, private key, and intermediary file, and the web interface will then be automatically trusted and show a green padlock icon in most web browsers to indicate that the connection is trusted and secure. To explain everything about how SSL certificates work however would be too lengthy to put here, and the documentation here on this page is centered around the command line options, so we’ll restrict ourselves here to the steps to accomplish the task of importing an already validated and signed certificate, private key, and intermediary bundle file. This can also be done via the Admin UI in the “Web Server” page, but below are the commands to achieve the same via the command line.

When the Access Server is first installed, it generates self-signed certificates and saves these in a directory on the server. The directory where it saves these is /usr/local/openvpn_as/etc/web-ssl/. The command it uses to generate the initial self-signed certificates is as follows.

./certool -d ../etc/web-ssl --type ca --unique --cn "OpenVPN Web CA"
./certool -d ../etc/web-ssl --type server --remove_csr --sn_off --serial 1 --name server --cn <FQDN>

It is technically possible to replace the files in that directory with your own private key, certificate, and intermediary bundle file, but this is not recommended. Instead what you should do is use the configuration keys that were designed to hold these files. If the configuration keys exist they will be used for the web services instead. If the configuration keys do not exist (the default) then the self-signed certificates found in the web-ssl directory will be used instead by default. Consider the files in the web-ssl folder as a fallback in case the certificates loading into the configuration database are broken and you have to wipe these from the database. So to correctly replace the private key, certificate, and intermediary bundle file, use the commands below to place them into the configuration database keys meant for this purposes.

If you have already replaced these self-signed certificates with your own certificate files, and now discover you should have used the configuration database instead, you can use the sacli GetActiveWebCerts function to import the files in the /etc/web-ssl/ subfolder to configuration database key values. At least then you have the values properly stored in the configuration database as they should be.

Convert /etc/web-ssl files to configuration database key values:

./sacli --import GetActiveWebCerts

It is important to note that .p12 or .pfx format certificates are not accepted. You need the certificates to be in PEM type format, the same type used by Apache, Apache2, Nginx, and other such software. It is however possible to use a conversion tool to convert from .pfx to PEM type. for this purpose we recommend the DigiCert Certificate Utility for Windows.

Store contents of “private.key” file into the configuration database:

./sacli --key "cs.priv_key" --value_file "private.key" ConfigPut

Store contents of “” file into the configuration database:

./sacli --key "cs.cert" --value_file "" ConfigPut

Store contents of “intermediary_bundle.pem” file into the configuration database:

./sacli --key "cs.ca_bundle" --value_file "intermediary_bundle.pem" ConfigPut

In almost all cases you will have received additional files that provide the links in the chain of trust between your signed certificate and the root authority known in your web browser as a trusted party. Usually people buy certificates signed by the intermediary certificate authority between the trusted root authority and yourself; the company you are getting your certificates signed by. In very rare cases your certificate is signed directly by the root authority and then you do not need to provide intermediary files. If you have received more than one intermediary file, you can create a new text files and paste one after the other into the new file and save it and import it.

To restart the Access Server web service to start using the new certificates use this command:

./sacli start

To remove the keys so it falls back to the self-signed certificates in the web-ssl directory:

./sacli --key "cs.priv_key" ConfigDel
./sacli --key "cs.cert" ConfigDel
./sacli --key "cs.ca_bundle" ConfigDel
./sacli start

To verify if the web SSL certificates have been installed correctly we recommend using online tools such as the DigiCert SSL Installation Diagnostics Tool and Qualys SSL Labs SSL Server Test to be sure the installation has been done correctly. Additionally we recommend taking a look at the results to see if you need to tighten security by adjusting the TLS settings and web server cipher suite string, both of which are documented here on this page.

Branding – change logo on web interface

Branding options are limited in the OpenVPN Access Server, and not present in the OpenVPN Connect Client products. But you can replace the logo you see when opening the client web service or the Admin UI’s login screens of the Access Server. Additionally a description text string can be placed on the Admin UI so that administrators can easily identify which server they’re working on when performing administrative tasks. When replacing the logo the best results are obtained with a picture of 340 pixels wide of file type PNG with transparent background (if any). JPEG is also supported but without transparency it may not look as good.
The file must be placed on the file system of the Access Server, you cannot reference an online picture. We recommend a program such as SCP or WinSCP to copy the file to a location on the file system of the Access Server. Most Linux operating systems nowadays want you to log on as a user with limited privileges and so you will most likely not be able to upload a picture directly to a folder in /usr/local/openvpn_as/. If you encounter this problem simply upload it in a directory like /tmp where the file will remain until you reboot the server. Then log on to the console or via an SSH session, obtain root privileges, and move the file from the /tmp directory to for example /usr/local/openvpn_as/etc/. The commands below are also assumed to be done as root user.

Use nano or another text editor to open the as.conf file for editing:

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

Locate the sa.company_name variable and add the extra logo variable as follows:

sa.company_name=OpenVPN Inc.

Save and exit the file. Then restart the OpenVPN Access Server:

service openvpnas restart

Your Access Server’s web interface should now show the logo. If it still shows the old logo you may need to refresh the web page forcibly or empty the browser cache. If the Access Server doesn’t start up anymore after editing these parameters, then most likely a mistake in the filename or location has been made. You can correct the settings or undo the changes and restart the Access Server again to restore functionality.

Web server identification string

It is possible to change the “Server” HTTP header that the Access Server’s built-in web server uses to identify itself to clients (browsers). This way an automated scan attempting to determine the web server software used and attempt to use exploits on it may be confused and not be able to determine what software is being used. This adds very little security in reality, or perhaps security through obscurity, but some security scan programs can ‘fail’ on this and therefore we have made it possible to customize this identification string.

To set a custom web server name:

./sacli --key "cs.web_server_name" --value "HAL9000" ConfigPut
./sacli start

Web session timeout

By default, whenever you authenticate to the CWS (Client Web Service) or the AWS (Admin Web Service, or Admin UI) your session will remain active for a limited time. As long as you stay active on the web interface by navigating or refreshing pages, or submitting changes, you will remain logged on, but the inactivity threshold is by default at 30 minutes. If you do nothing for 30 minutes your session will be ended after 30 minutes. This setting can be altered to any value in seconds. So for example if you wanted to set a timeout of 10 minutes, you would set it to 600 (60*10). Default value is assumed by the server to be 1800 (30 minutes) if the configuration key sa.session_expire doesn’t exist.

See what the current setting is (if nothing shows it’s the default of 1800 seconds):

./sacli ConfigQuery | grep -i "sa.session_expire"

To set the web session inactivity timeout to 5 minutes:

./sacli --key "sa.session_expire" --value "300" ConfigPut
./sacli start

To remove the key so it resets to its default of 30 minutes:

./sacli --key "sa.session_expire" ConfigDel
./sacli start

Selecting the SSL/TLS library

In the past SSLv2 and SSLv3 were widely used, and this existed before TLS was created. Nowadays TLS is the standard and SSL is deprecated due to security flaws. Commonly people still refer to it as SSL even though we mostly use TLS now. You can for example buy SSL certificates online, and the open source library that implements SSL and TLS is still called OpenSSL, but we use the TLS functions of the library instead in most cases. OpenSSL is the library that is used by OpenVPN as well for handshaking, encryption, and decryption. An alternative library is called PolarSSL/mbed TLS and is supported by the OpenVPN Access Server as well. The main reason the support was added was because on mobile platforms such as iOS and Android, initially only PolarSSL was available. Since support was added in the OpenVPN codebase, Access Server added the choice which library to use.

The reason PolarSSL/mbed TLS is mentioned in this way is because the project was originally called PolarSSL but is renamed to mbed TLS. Older versions of OpenVPN or OpenVPN Access Server may still have the old name compiled into it and so we mentioned both so people understand it’s the same thing.

By default the library OpenSSL is selected and that is the recommended library to use on the server. Clients that use PolarSSL/mbed TLS are able to connect to an Access Server using OpenSSL, and vice versa an Access Server using PolarSSL/mbed TLS can accept connections from an OpenSSL based OpenVPN client. Sometimes companies due to internal security regulations must use a specific library. The library can be chosen from the “SSL/TLS Settings” page in the Admin UI of the Access Server. The chosen library file will be used for OpenVPN tunnels as well as the web services. From the command line the commands below can be used to set the SSL/TLS library file.

Please note though that in Access Server 2.5 and higher, the name polarssl was changed to mbedtls. So if you use an older Access Server use the old polarssl name, and on Access Server 2.5 and higher use mbedtls. This is because both are still the same project but the project has changed their name.

Set the library specifically to OpenSSL:

./sacli --key "sa.ssl_lib" --value "openssl" ConfigPut
./sacli start

Set the library specifically to mbedTLS (on Acces Server 2.5 and higher):

./sacli --key "sa.ssl_lib" --value "mbedtls" ConfigPut
./sacli start

Set the library specifically to polarssl (on Acces Servers older than 2.5):

./sacli --key "sa.ssl_lib" --value "polarssl" ConfigPut
./sacli start

Remove the configuration key to assume the default (OpenSSL):

./sacli --key "sa.ssl_lib" ConfigDel
./sacli start

To verify that your Access Server is really using the selected library for its OpenVPN daemons check the file /var/log/openvpnas.log for the line that specifies which version of OpenVPN is being used. The Access Server comes bundled with a binary that is compiled with OpenSSL, and a binary that is compiled with PolarSSL/mbed TLS. When the server starts up it will mention the startup line for the OpenVPN daemons in the log file. Note that if you log to syslog you should check syslog instead of the log file.

For example these lines in the /var/log/openvpnas.log file when using OpenSSL:

[-] OVPN 0 OUT: '(date) OpenVPN (version here) x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [MH] [IPv6] built on (date)'
[-] OVPN 0 OUT: '(date) library versions: OpenSSL 1.0.2k 26 Jan 2017, LZO 2.08'

Or these lines in the /var/log/openvpnas.log file when using PolarSSL:

[-] OVPN 0 OUT: '(date) OpenVPN (version here) x86_64-pc-linux-gnu [SSL (PolarSSL/mbed TLS)] [LZO] [EPOLL] [MH] [IPv6] built on (date)'
[-] OVPN 0 OUT: '(date) library versions: PolarSSL 1.3.19, LZO 2.08'

To verify that the Access Server web server is using PolarSSL/mbed TLS, you can enable PolarSSL debugging:

./sacli --key "sa.polarssl_debuglevel" --value "1" ConfigPut
./sacli start

Now visit the web interface and check the log file output for results like these:

WEB OUT: '***** PolarSSL.Connection.recv status=699'
WEB OUT: '***** PolarSSL.Connection.send len=15920'

Since this debug level creates a lot of logging we recommend disabling it again after:

./sacli --key "as.polarssl_debuglevel" ConfigDel
./sacli start

Selecting a custom cipher suite string for the web server

The built-in web server uses SSL/TLS encryption between browser and web server. A number of encryption ciphers are allowed for use, this is listed in a so-called cipher suite string. This is a list of cipher groups or specific ciphers that can be used by connecting clients (browsers) to establish a secure connection. Some ciphers are more secure than others, and some ciphers have at some point in the past been compromised, and others are not as secure as we would like, but are necessary to maintain compatibility with older software like Windows XP or older web browsers. Security scanner programs will see these older ciphers and complain about them. We’ve made the cipher suite string a configurable setting that you can alter at will.

Documentation about what the cipher suite string can be made up of is found here:

The default cipher suite string in Access Server as of 2.0.14 is DEFAULT:!EXP:!PSK:!SRP:!LOW:!RC4.

If you use PolarSSL/mbed TLS the same settings and parameters still apply, but the name openssl_ciphersuites is a hold-over from when Access Server did not have PolarSSL/mbed TLS support and only supported OpenSSL. Please note though that some ciphers may not be available on PolarSSL/mbed TLS while they are available on OpenSSL and vice versa. There may be minor differences between the two libraries. Check documentation for the libraries for more information.

To see what the current string is set to (if nothing shows the default above applies):

./sacli ConfigQuery | grep -i "cs.openssl_ciphersuites"

To set a custom string that disables 3DES ciphers:

./sacli --key "cs.openssl_ciphersuites" --value 'DEFAULT:!EXP:!PSK:!SRP:!LOW:!RC4:!3DES' ConfigPut
./sacli start

A fairly high security setting which only works with modern browsers:

./sacli --key "cs.openssl_ciphersuites" --value 'EECDH+CHACHA20:EECDH+AES128:EECDH+AES256:!RSA:!3DES:!MD5' ConfigPut
./sacli start

You can verify which ciphers your web server supports with the nmap tool:

nmap --script ssl-enum-ciphers -p 443

To reset the string to default you can delete the configuration key:

./sacli --key "cs.openssl_ciphersuites" ConfigDel
./sacli start

Please note that use of single quotes instead of double quotes around the cipher suite string. If you use double quotes here you may get errors like “!RSA event not found”.

Selecting SSL and TLS levels on the web server

While currently the Access Server still supports SSL level encryption on the web server, we recommend that you do not use this. We have marked it as deprecated in the Admin UI and we have set the default to require a minimum of TLS 1.1 for the web server as of Access Server 2.1.12 for new installations. Upgrades retain the previous setting. If you find that your Access Server is configured to use SSL 3 or even SSL 2 we recommend that you change this to require a minimum of TLS 1.1 or higher as soon as possible. The reason for this is that SSL has been found to contain fundamental security flaws which will not be fixed anymore. Instead TLS replaces it and is more secure.

The TLS level for the web server can be configured in the Admin UI under “SSL/TLS Settings”. But it can also be set via the command line. PolarSSL/mbed TLS doesn’t support SSLv3 or SSLv3 on Access Server. But OpenSSL can still do SSLv3 if that is required for legacy purposes, but it is has some vulnerabilities that are unresolved. Our recommendation is that you use TLS 1.1 or higher. Do not touch the TLS level settings for the OpenVPN daemons unless you know what implications this can have for existing installations. We recommend that you read documentation about setting the TLS level on the OpenVPN daemons for that particular setting.

To see what the current TLS level is set to (if nothing is shown, TLS 1.1 applies as of AS 2.1.12):

./sacli ConfigQuery | grep -i "cs.tls_version_min"

To set it to require a minimum of TLS 1.0 or higher:

./sacli --key "cs.tls_version_min" --value "1.0" ConfigPut
./sacli start

To set it to require a minimum of TLS 1.1 or higher:

./sacli --key "cs.tls_version_min" --value "1.1" ConfigPut
./sacli start

To set it to require a minimum of TLS 1.2 or higher:

./sacli --key "cs.tls_version_min" --value "1.2" ConfigPut
./sacli start

A guide to set it to SSL 3 or even SSL 2 is not given here, as this is deprecated and will be removed entirely in a future version of Access Server, and is not secure. If you do need it, use the Admin UI to set it, for as long as it is still supported.

Set the interface and ports for the web services

The interface and port where web services listen can be set separately from the OpenVPN daemons that handle incoming VPN tunnel connections. By default the OpenVPN Access Server is set up with the web services listening on port TCP 943, and you can reach them there as well as at the default HTTPS port TCP 443. The reason for this ability to also listen on TCP 443 even though the web services are not listening on that port itself, is a function we call service forwarding or port forward. There is an OpenVPN TCP daemon by default on TCP port 443 that handles incoming OpenVPN tunnel connections, but that can also recognize web browser requests and forward them internally to the correct port (TCP 943) where the web services are listening. This way we can use the web interface on the standard HTTPS port and have Access Server respond to without having to specify a special port, and at the same time handle incoming VPN tunnel connections on this same port as well. The advantage of this is that there are public networks with restrictive firewalls that simply block all traffic except a few commonly used ports, like TCP 80 for HTTP traffic and TCP 443 for HTTPS traffic. In such a case a connection to the standard OpenVPN UDP port 1194 will fail, but the OpenVPN TCP daemon on port 443 will still be able to get you connected to your Access Server.

If for whatever reason you turn off or change the service forwarding settings, or alter the OpenVPN TCP daemon port, then this automatic internal redirection of browser requests on port TCP 443 will not work anymore. And if for example during maintenance you stop the OpenVPN daemons, you will also not be able to access the web services on the default HTTPS port anymore. In such a case you have to contact the web services directly at their default port TCP 943 in the web browser like so:

By default the web services and OpenVPN daemons listen on all interfaces. You can change this in the Admin UI in the Server Network Settings page. You can even set a different interface and port for the admin web UI and the client web UI. All of these settings are also available on the command. You can change the interface and ports where the OpenVPN daemons listen for incoming OpenVPN tunnel connections. The command line examples below show you how to change where the web services listen.

To set the interface name that the admin UI listens on:

./sacli --key "admin_ui.https.ip_address" --value <INTERFACE> ConfigPut
./sacli start

To set the TCP port that the admin UI listens on:

./sacli --key "admin_ui.https.port" --value <PORT_NUMBER> ConfigPut
./sacli start

To set the interface name that the client UI listens on:

./sacli --key "cs.https.ip_address" --value <INTERFACE> ConfigPut
./sacli start

To set the TCP port that the client UI listens on:

./sacli --key "cs.https.port" --value <PORT_NUMBER> ConfigPut
./sacli start

To restore the default so it listens to all interfaces on port TCP 943:

./sacli --key "admin_ui.https.ip_address" --value "all" ConfigPut
./sacli --key "admin_ui.https.port" --value "943" ConfigPut
./sacli --key "cs.https.ip_address" --value "all" ConfigPut
./sacli --key "cs.https.port" --value "943" ConfigPut
./sacli start

An important note when you set the admin UI and client UI on different interfaces or ports; when the admin UI is separated it no longer uses the /admin/ part in the URL. That is only used when the client UI and admin UI are both listening on the same interface and port, to keep them separate and reachable.

Change the web service forwarding settings

The OpenVPN TCP daemon and the web services are connected. This is done with service forwarding which internally redirects web browser requests made to the OpenVPN TCP daemon, which is running on the default HTTPS port TCP 443, to where the web services are actually running. Service forwarding can be disabled if you want to.

When you install the Access Server it is by default configured with an OpenVPN TCP daemon on port TCP 443, and with the web services on port TCP 943. The client UI and admin UI are by default on the same port, but separated by a slightly different URL (/admin/ for the Admin UI). To make things a little easier we have created an internal automatic redirection for web browsers requests that come in on the OpenVPN TCP daemon running on TCP 443, to point to where the web services run. If we didn’t do this then you would always have to manually specify the port to make a connection to the web services, whereas with service forwarding enabled the address is simply instead of with the port manually specified as

When you change the interface or port settings where the web services listen, but leave service forwarding enabled, you can still access the web services on the interface and port where the OpenVPN TCP daemon is listening. And if you change settings related to where the OpenVPN TCP daemon is listening, then you have to be aware that if you were contacting the web services through that daemon, then you may lose connection to the web services depending on how you configure things. But you can of course still reach the web services at the actual interface and port they are listening on.

An important note about the client UI: this web service is used for the server-locked connection profiles that come included by default in the OpenVPN Connect Client for Windows and Macintosh. If you make the client web UI completely unreachable for your users, by for example disabling service forwarding and blocking access to port TCP 943 where the web services run, then server-locked profiles will simply no longer work. Users will then get a message about the XML-RPC interface being unreachable and they can’t authenticate and connect. The solution here is to either keep the client UI reachable for your users or to have all users obtain a user-locked or auto-login type profile from the administrator of the server, and importing this file into the OpenVPN client program. It’s worth nothing that you can keep the client UI online and working with OpenVPN Connect Client’s server-locked profiles, while denying them the ability to login at the web page itself by restricting logins at the client UI to admin users only.

Disable service forwarding for admin UI, but leave it enabled for client UI only:

./sacli --key "vpn.server.port_share.enable" --value "true" ConfigPut
./sacli --key "vpn.server.port_share.service" --value "client" ConfigPut
./sacli start

Disable service forwarding for client UI, but leave it enabled for admin UI only:

./sacli --key "vpn.server.port_share.enable" --value "true" ConfigPut
./sacli --key "vpn.server.port_share.service" --value "admin" ConfigPut
./sacli start

Disable service forwarding for admin UI and client UI both:

./sacli --key "vpn.server.port_share.enable" --value "false" ConfigPut
./sacli --key "vpn.server.port_share.service" --value "custom" ConfigPut
./sacli start

Enable service forwarding for admin UI and client UI both (default)

./sacli --key "vpn.server.port_share.enable" --value "true" ConfigPut
./sacli --key "vpn.server.port_share.service" --value "admin+client" ConfigPut
./sacli start

An important note when you set the admin UI forwarding on but disable client UI forward. When the admin UI is separated this way from the client UI it no longer uses the /admin/ part in the URL. That is only used when the client UI and admin UI are both listening on the same interface and port, to keep them separate and reachable.

Configure a custom redirection – only works with IP addresses on the server itself, nothing external:

./sacli --key "vpn.server.port_share.enable" --value "true" ConfigPut
./sacli --key "vpn.server.port_share.service --value "custom" ConfigPut
./sacli --key "vpn.server.port_share.ip_address --value <LOCAL_IP> ConfigPut
./sacli --key "vpn.server.port_share.port --value <PORT> ConfigPut
./sacli start

Using the method above you can run for example the OpenVPN TCP daemon on port TCP 443, have the Access Server web services on its standard port TCP 943, and at the same time serve pages from an Apache2 or Nginx web server (or other SSL capable web server) through port TCP 443 via service forwarding. And technically, if you really wanted to for some reason, you can make service forwarding to an external address possible by using iptables to redirect a port on a local interface to an external system.

See this section on how to restore the web services interface and port settings as well as the service forwarding to defaults.