How to manually configure Keeper Connection Manager SSL termination using NGINX
SSL termination is the recommended method of encrypting communication between users’ browsers and Guacamole, and involves configuring a reverse proxy like Nginx or Apache to handle strictly the SSL/TLS portion of the conversation with the Tomcat instance hosting Guacamole, handling encrypted HTTP externally while passing unencrypted HTTP to Tomcat internally.
If Nginx has been configured for SSL/TLS, there should be a server
section within this configuration that defines the certificate and private key used by Nginx, and which requires Nginx to listen on the standard HTTPS port (443). To proxy Guacamole through Nginx such that Guacamole communication is encrypted, a new location
section will need to be added within this server
section:
where “HOSTNAME” is the hostname or IP address of the internal Guacamole server. This can also be replaced with "http://127.0.0.1:8080" in most cases.
While a typical proxy configuration for Nginx may only specify the proxy_pass and proxy_http_version directives, Guacamole requires additional configuration due to the nature of the application:
proxy_buffering off
disables buffering of packets sent to/from Guacamole. By default, Nginx will buffer communication between itself and the browser, effectively disrupting the stream of events and updates required for remote desktop. Without disabling buffering, the Guacamole connection will at best be slow, and at worst not function at all.
The X-Forwarded-For header must be explicitly set to ensure that the IP addresses logged by Guacamole are correct. Without explicitly adding this header (and configuring Tomcat to trust this header), all connections will appear to come from the NGINX server.
The Upgrade and Connection headers are required parts of the WebSocket protocol. If omitted, WebSocket will not function correctly, and Guacamole will fall back to HTTP streaming, which is less efficient.
After the above changes have been made, NGINX must be reloaded to force rereading of its configuration files:
If you are using SELinux (the default on both CentOS and RHEL), you must also configure SELinux to allow HTTPD implementations like Nginx to establish network connections:
If Guacamole is not accessible through NGINX after the service has been reloaded, check the NGINX logs and/or journalctl to verify that the syntax of your configuration changes is correct. Such errors will result in NGINX refusing to reload its configuration, or refusing to start up entirely. If you do not see any errors from NGINX, verify that you have configured SELinux to allow NGINX to connect to the network and check the SELinux audit logs (/var/log/audit/audit.log
) for AVC denials.
X-Forwarded-For
" from NGINX (manual deployment only)This section applies only if you have manually deployed Guacamole under your own version of Tomcat. This will usually only be the case if:
You have chosen to manually deploy Guacamole under your own install of Apache Tomcat or JBoss, rather than use the provided version of Tomcat.
You are maintaining a deployment of Glyptodon Enterprise that was originally installed before the 2.5 release (2021-09-16).
If you deployed Guacamole automatically (the default and recommended method), this has already been configured for you within the bundled version of Tomcat.
For the client address sent by NGINX via "X-Forwarded-For
" to be correctly trusted as the true client address, you will need to add a "RemoteIpValve
" entry within /etc/tomcat/server.xml
. If this is not specified, the client address will be logged as the address of the internal proxy, which is not usually desirable.
The easiest way to add the required entry is to copy the example server.xml
file provided with the kcm
package, replacing the old /etc/tomcat/server.xml
:
The example server.xml file defines:
A single HTTP connector listening on port 8080.
A RemoteIpValve
with all settings at their default values.
By default, the RemoteIpValve
will trust "X-Forwarded-For
" from all private networks (10.0.0.0/8
, 172.16.0.0/12
, 192.168.0.0/16
, 169.254.0.0/16
, and both IPv4 and IPv6 localhost). If you need this range to be narrowed, or if you have already made manual edits to server.xml
, you will need to make these changes manually.
If editing server.xml
manually (rather than using the example server.xml
), a <Valve>
which trusts "X-Forwarded-For
" from most common private addresses would be specified as:
This <Valve>
must be added within the relevant <Host>
section. In most cases, the easiest place to add this is simply toward the end of the server.xml
file:
If needed, this can be narrowed by providing your own value for the internalProxies
attribute specifies a regular expression which matches the IP addresses of any proxies whose "X-Forwarded-For
" headers should be trusted. For example, to trust only "X-Forwarded-For
" received from localhost:
Applying the updated Tomcat configuration
Once an appropriate RemoteIpValve
has been specified, Tomcat must be restarted to force rereading of server.xml
:
Detailed configuration instructions for SSL Termination with Nginx
Nginx is not directly available within the CentOS or RHEL repositories, but is available within the EPEL repository. The EPEL repository must be enabled first before Nginx can be installed:
Once EPEL has been enabled, Nginx can be installed by installing the "nginx" package. Installing this package will install a version of Nginx that is newer than version 1.3 and thus is explicitly supported by Keeper Connection Manager:
As with other standard CentOS / RHEL packages providing a service, the Nginx service will not be started by default after the "nginx" package is installed. It must be started manually, and then configured to automatically start if the system is rebooted:
By default, Nginx will listen on port 80 and handle only unencrypted HTTP connections, serving the static contents of /usr/share/nginx/html
. The rest of this document will cover reconfiguring Nginx such that it serves only HTTPS (using HTTP only to redirect browsers back to HTTPS), with a placeholder for the minimal additional configuration needed to provide SSL termination. The resulting configuration will be used instead of Nginx' default configuration, and will be split up across two modular files:
/etc/nginx/conf.d/redirect-http.conf
Configures Nginx to respond to all HTTP requests with an HTTP 301 ("Moved Permanently") redirect to the same resource under HTTPS.
/etc/nginx/conf.d/guacamole.conf
Configures Nginx to accept HTTPS connections using a specified certificate and private key. Once SSL configuration is complete, this file will also configure Nginx to proxy HTTPS connections to Guacamole such that HTTP is used only internally (SSL termination).
The main configuration file for Nginx, /etc/nginx/nginx.conf
, contains a server
block which serves the contents of /usr/share/nginx/html
over HTTP:
The contents of this server
block will conflict with the HTTP redirect that will need to be created, and should be commented-out or removed. Comment out every line with a # at the beginning:
With the conflicting server
block removed, create a new file, /etc/nginx/conf.d/redirect-http.conf
, to contain the new server block and redirect. The server
block required is fairly straightforward. Rather than serve static content, it instructs Nginx to issue an HTTP 301 redirect ("Moved Permanently") for all requests, informing the browser that whatever they are requesting can instead be found at the same location using HTTPS:
To apply the new configuration, simply reload Nginx:
To configure Nginx to accept HTTPS connections, you must obtain an SSL certificate for the domain associated with your server. There are two primary ways of doing this:
Let's Encrypt: A non-profit certificate authority that provides automated certificate issuance and renewal. Let's Encrypt certificates are free.
Obtaining a certificate from a certificate authority: Several commercial certificate authorities exist, many of which are also domain registrars. Unlike Let's Encrypt, obtaining a certificate from a commercial certificate authority will usually cost money.
The Let's Encrypt service uses a utility called "certbot" to automatically retrieve a certificate after the Let's Encrypt service has remotely verified that you control your domain. This utility is provided within the CentOS / RHEL repositories and must first be installed:
The Let's Encrypt service will verify that you control your domain be reaching back over the internet, attempting to establish an HTTP connection with your server at the domain provided and reading the contents of the .well-known/
directory within the web root. This directory will be created and populated automatically by certbot when it runs, but the /etc/nginx/conf.d/redirect-http.conf
file created earlier will not allow this directory to be read due to the nature of the HTTPS redirect. The server
block within redirect-http.conf
must first be edited to add a location which functions as an exception to this redirect, allowing Let's Encrypt to remotely access .well-known/
:
To apply the new configuration, reload Nginx:
The certbot tool can then be used to automatically retrieve a certificate for your domain. For example, if your Guacamole server is running at "remote.example.com", you can obtain a certificate from Let's Encrypt by running:
The resulting certificate and private key will then be stored within a subdirectory of /etc/letsencrypt/live/
with the same name as your domain. To apply the certificate and additionally host content via HTTPS, a new configuration file needs to be created: /etc/nginx/conf.d/guacamole.conf
. Similar to the HTTP redirect, this file will contain a server block that defines how Nginx should serve HTTPS connections:
Let's Encrypt certificates are intentionally short-lived, expiring after 90 days. To ensure that a new certificate is retrieved, it is recommended that certbot run daily. This can be achieved by creating a script within /etc/cron.daily
called /etc/cron.daily/certbot
containing the following:
Be sure to grant execute permission on the script so that the cron service will be able to execute it:
The certbot tool will then be automatically invoked at least once per day, renewing the certificate and reloading Nginx as needed.
With Nginx now deployed with a proper SSL certificate, the final step in providing SSL termination for Guacamole is to configure Nginx as a reverse proxy for Guacamole. This process involves adding a location
block within the Nginx server block for HTTPS, in this case the /etc/nginx/conf.d/guacamole.conf
configuration file that was just created. Documentation is provided for the full content and meaning of the required location
block, which should be added in the space noted by the "Location block pointing to Tomcat will go here" placeholder comments above.
Optional NGINX Client Certificate configuration for advanced protection
To implement device-based access security with Keeper Connection Manager, this can be accomplished using NGINX client certificates. A client certificate is installed into the web browser of your user's approved devices, and the server will only accept communication from a device with the client certificate installed.
The steps to activate this advanced level of protection is described in the steps below.
(1) Create a Certificate Authority (CA) Key
Generate a CA Key with a strong auto-generated passphrase. Make sure to store the passphrase in your Keeper vault.
(2) Create a CA Certificate
A certificate is created with the CA Key. When answering the questions, you can leave the Common Name and Email empty. Save the information that you entered for Country, State, Locality, and Organization, because you may need these later when renewing the certificate.
Side Note: to analyze the certificate parameters, you can run the below command.
(3) Create a Client Key
For the end-user devices, a client key must be generated. You can decide if you would like to generate one key for all devices, or each user can generate their own key and request a certificate. The process is up to you. Generate a client key with a strong auto-generated passphrase. Make sure to store the passphrase in your Keeper vault.
(4) Create a CSR
For each Client Key, generate a CSR to create a signed certificate.
(5) Sign the CSR with the CA Key
You'll need to enter the CA passphrase from Step 1 to sign the request.
At this point, you now have a signed Client Certificate (client.crt).
(6) Convert the Client Certificate to PKCS#12
To import the certificate into a web browser, a pfx file in PKCS#12 is typically required. Generate the client.pfx file using the command below. A passphrase will be required. This passphrase will be provided to each of the users who need to install the certificate, so it should be used specifically for this purpose.
(7) Add to NGINX Config
Add the below line to your Keeper Connection Manager NGINX configuration file to block access without a certificate. Make sure to upload the CA certificate to the folder path designated.
In the Location block, add this section to send the user a 403 error if the client cert is not installed:
Make sure that the ca.crt file is located in a folder that NGINX can access.
After updating the configuration, restart NGINX.
(8) Test the configuration
Before installing the client certificate on the user's machine, load up the Keeper Connection Manager login screen to ensure that a 403 error is sent:
(9) Install the Client Certificate
For each end-user client device that will need access to Keeper Connection Manager, you will need to install the client certificate into the user's browser or machine. The installation of client certificates varies by platform.
On Windows
Double-click or right-click the client certificate (client.pfx) from Step 6 and enter the client certificate passphrase.
Restart the browser.
The next time Keeper Connection Manager is loaded, you can approve the certificate.
On Mac OS - Chrome
Import the client.pfx file by double-clicking or loading into the Keychain login Certificates section. In the "Trust" section of the certificate, mark as Always Trust.
Restart the browser and load the Keeper Connection Manager login screen to select the certificate.
On Mac OS - Firefox
Open Firefox > Preferences > search for Certificates and select Your Certificates tab. Click "Import" and select the client.pfx certificate file. Complete the import.
After successful import, the Keeper Connection Manager login screen will load.
After setting up the client certificate configuration, the following errors are common.
If NGINX fails to start, journalctl -xe
might show something like "Permission denied:fopen('/path/to/ca.crt','r'). This might occur if the folder permissions and file permissions are not set properly.
If the folder and file permissions are set properly and you're still receiving this error, the restorecon
command will repair the SELinux security context for the file: