> For the complete documentation index, see [llms.txt](https://newdocs.keeper.io/kcm-linux-rpm-method/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://newdocs.keeper.io/kcm-linux-rpm-method/security/ssl-termination-with-apache.md).

# SSL Termination with Apache

{% hint style="info" %}
**This documentation assumes that you already have an instance of Apache properly configured for SSL/TLS**, including the necessary private key and certificate, and that Guacamole has already been installed using Keeper Connection Manager. If you do not already have an instance of Apache ready, please set up an instance of Apache before proceeding. If you do not already have Guacamole installed, please see the [installation instructions.](/kcm-linux-rpm-method/installation.md)
{% endhint %}

SSL termination is the recommended method of encrypting communication between users’ browsers and Guacamole, and involves configuring a reverse proxy like[ Nginx](/kcm-linux-rpm-method/security/ssl-termination-with-nginx.md) or[ Apache](/kcm-linux-rpm-method/security/ssl-termination-with-apache.md) 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.

### Proxying Guacamole through Apache <a href="#id-.settingupsslterminationwithapachev2.x-proxyingguacamolethroughapache" id="id-.settingupsslterminationwithapachev2.x-proxyingguacamolethroughapache"></a>

If Apache has been configured for SSL/TLS, there should be a `<VirtualHost>` section within this configuration that defines the certificate and private key used by Apache, and which requires Apache to listen on the standard HTTPS port (443). To proxy Guacamole through Apache such that Guacamole communication is encrypted, two additional `<Location>` sections will need to be added within this `<VirtualHost>` section:

```
<Location />
    Order allow,deny
    Allow from all
    ProxyPass http://HOSTNAME:8080/ flushpackets=on
    ProxyPassReverse http://HOSTNAME:8080/
</Location>

<Location /websocket-tunnel>
    Order allow,deny
    Allow from all
    ProxyPass ws://HOSTNAME:8080/websocket-tunnel
    ProxyPassReverse ws://HOSTNAME:8080/websocket-tunnel
</Location>
```

where “HOSTNAME” is the hostname or IP address of the internal Guacamole server.

These `<Location>` sections configure proxying of the HTTP and WebSocket protocols respectively. Apache handles the HTTP and WebSocket protocols separately, and thus requires separate configuration for the portion of the web application which uses WebSocket. Both sections are required for Guacamole to work correctly behind Apache, and **the** [**mod\_proxy\_wstunnel**](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) **module must be installed and enabled**.

Of particular importance is the `flushpackets=on` option within the ProxyPass directive used for HTTP in front of Guacamole. This option disables buffering of packets sent to/from Guacamole. By default, Apache 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.

#### Applying the updated Apache configuration <a href="#id-.settingupsslterminationwithapachev2.x-applyingtheupdatedapacheconfiguration" id="id-.settingupsslterminationwithapachev2.x-applyingtheupdatedapacheconfiguration"></a>

After the above changes have been made, Apache must be reloaded to force rereading of its configuration files:

```
$ sudo systemctl reload httpd
```

If you are using SELinux (the default on both CentOS and RHEL), you must also configure SELinux to allow HTTPD implementations like Apache to establish network connections:

```
$ sudo setsebool -P httpd_can_network_connect 1
```

If Guacamole is not accessible through Apache after the service has been reloaded, check the Apache logs and/or journalctl to verify that the syntax of your configuration changes is correct. Such errors will result in Apache refusing to reload its configuration, or refusing to start up entirely. If you do not see any errors from Apache, verify that you have configured SELinux to allow Apache to connect to the network and check the SELinux audit logs (`/var/log/audit/audit.log`) for [AVC denials](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security-enhanced_linux/chap-security-enhanced_linux-troubleshooting).

### Configuring Tomcat to trust "`X-Forwarded-For`" from Apache **(manual deployment only)** <a href="#id-.settingupsslterminationwithapachev2.x-remoteipvalveconfiguringtomcattotrust-x-forwarded-for-from" id="id-.settingupsslterminationwithapachev2.x-remoteipvalveconfiguringtomcattotrust-x-forwarded-for-from"></a>

{% hint style="warning" %}
**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](https://newdocs.keeper.io/kcm-linux-rpm-method/security/pages/ZqnMdyCaG68yVINbbLIh#id-.changelogv2.x-2.52.5version2.5) (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.
{% endhint %}

For the client address sent by Apache via "`X-Forwarded-For`" to be correctly trusted as the true client address, you will need to add a "[`RemoteIpValve`](https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_IP_Valve)" 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.

{% tabs %}
{% tab title="Using the provided example server.xml" %}
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`:

```
$ sudo cp /opt/keeper/share/guacamole/server.xml /etc/tomcat/
```

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.
{% endtab %}

{% tab title="Editing server.xml 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:

```
<Valve className="org.apache.catalina.valves.RemoteIpValve"/>
```

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:

```
        ...

        <Valve className="org.apache.catalina.valves.RemoteIpValve"/>

      </Host>
    </Engine>
  </Service>
</Server>
```

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:

```
<Valve className="org.apache.catalina.valves.RemoteIpValve"
       internalProxies="127\.\d{1,3}\.\d{1,3}\.\d{1,3}|0:0:0:0:0:0:0:1|::1"/>
```

{% endtab %}
{% endtabs %}

Applying the updated Tomcat configuration

Once an appropriate `RemoteIpValve` has been specified, Tomcat must be restarted to force rereading of `server.xml`:

```
$ sudo systemctl restart tomcat
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://newdocs.keeper.io/kcm-linux-rpm-method/security/ssl-termination-with-apache.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
