| |
| |
| <!DOCTYPE html> |
| <html class="writer-html5" lang="en" > |
| <head> |
| <meta charset="utf-8" /> |
| |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| |
| <title>Proxying Guacamole — Apache Guacamole Manual v1.4.0</title> |
| |
| |
| |
| <link rel="stylesheet" href="_static/css/theme.css" type="text/css" /> |
| <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> |
| <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> |
| <link rel="stylesheet" href="_static/css/theme.css" type="text/css" /> |
| <link rel="stylesheet" href="_static/tabs.css" type="text/css" /> |
| <link rel="stylesheet" href="_static/gug.css" type="text/css" /> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <!--[if lt IE 9]> |
| <script src="_static/js/html5shiv.min.js"></script> |
| <![endif]--> |
| |
| |
| <script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script> |
| <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script> |
| <script src="_static/jquery.js"></script> |
| <script src="_static/underscore.js"></script> |
| <script src="_static/doctools.js"></script> |
| <script src="_static/tabs.js"></script> |
| |
| <script type="text/javascript" src="_static/js/theme.js"></script> |
| |
| |
| <link rel="index" title="Index" href="genindex.html" /> |
| <link rel="search" title="Search" href="search.html" /> |
| <link rel="next" title="Configuring Guacamole" href="configuring-guacamole.html" /> |
| <link rel="prev" title="Installing Guacamole with Docker" href="guacamole-docker.html" /> |
| </head> |
| |
| <body class="wy-body-for-nav"> |
| |
| |
| <div class="wy-grid-for-nav"> |
| |
| <nav data-toggle="wy-nav-shift" class="wy-nav-side"> |
| <div class="wy-side-scroll"> |
| <div class="wy-side-nav-search" > |
| |
| |
| |
| <a href="index.html" class="icon icon-home"> Apache Guacamole |
| |
| |
| |
| </a> |
| |
| |
| |
| |
| <div class="version"> |
| 1.4.0 |
| </div> |
| |
| |
| |
| |
| <div role="search"> |
| <form id="rtd-search-form" class="wy-form" action="search.html" method="get"> |
| <input type="text" name="q" placeholder="Search docs" /> |
| <input type="hidden" name="check_keywords" value="yes" /> |
| <input type="hidden" name="area" value="default" /> |
| </form> |
| </div> |
| |
| |
| </div> |
| |
| |
| <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation"> |
| |
| |
| |
| |
| |
| |
| <p class="caption" role="heading"><span class="caption-text">Overview</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="introduction.html">Introduction</a></li> |
| </ul> |
| <p class="caption" role="heading"><span class="caption-text">User's Guide</span></p> |
| <ul class="current"> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-architecture.html">Implementation and architecture</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="installing-guacamole.html">Installing Guacamole natively</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-docker.html">Installing Guacamole with Docker</a></li> |
| <li class="toctree-l1 current"><a class="current reference internal" href="#">Proxying Guacamole</a><ul> |
| <li class="toctree-l2"><a class="reference internal" href="#preparing-your-servlet-container">Preparing your servlet container</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#setting-up-the-remote-ip-valve">Setting up the Remote IP Valve</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="#nginx">Nginx</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#proxying-with-nginx">Proxying Guacamole</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#changing-the-path">Changing the path</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#adjusting-file-upload-limits">Adjusting file upload limits</a></li> |
| </ul> |
| </li> |
| <li class="toctree-l2"><a class="reference internal" href="#apache-and-mod-proxy">Apache and mod_proxy</a><ul> |
| <li class="toctree-l3"><a class="reference internal" href="#proxying-with-apache">Proxying Guacamole</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#proxying-the-websocket-tunnel">Proxying the WebSocket tunnel</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#changing-path-with-apache">Changing the path</a></li> |
| <li class="toctree-l3"><a class="reference internal" href="#disabling-logging-of-tunnel-requests">Disabling logging of tunnel requests</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="toctree-l1"><a class="reference internal" href="configuring-guacamole.html">Configuring Guacamole</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="jdbc-auth.html">Database authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="ldap-auth.html">LDAP authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="duo-auth.html">Duo two-factor authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="totp-auth.html">TOTP two-factor authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="header-auth.html">HTTP header authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="json-auth.html">Encrypted JSON authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="cas-auth.html">CAS Authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="openid-auth.html">OpenID Connect Authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="saml-auth.html">SAML Authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="radius-auth.html">RADIUS Authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="adhoc-connections.html">Ad-hoc Connections</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="using-guacamole.html">Using Guacamole</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="administration.html">Administration</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="troubleshooting.html">Troubleshooting</a></li> |
| </ul> |
| <p class="caption" role="heading"><span class="caption-text">Developer's Guide</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-protocol.html">The Guacamole protocol</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="libguac.html">libguac</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-common.html">guacamole-common</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-common-js.html">guacamole-common-js</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="guacamole-ext.html">guacamole-ext</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="custom-protocols.html">Adding new protocols</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="custom-auth.html">Custom authentication</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="event-listeners.html">Event listeners</a></li> |
| <li class="toctree-l1"><a class="reference internal" href="writing-you-own-guacamole-app.html">Writing your own Guacamole application</a></li> |
| </ul> |
| <p class="caption" role="heading"><span class="caption-text">Appendices</span></p> |
| <ul> |
| <li class="toctree-l1"><a class="reference internal" href="protocol-reference.html">Guacamole protocol reference</a></li> |
| </ul> |
| |
| |
| |
| </div> |
| |
| </div> |
| </nav> |
| |
| <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"> |
| |
| |
| <nav class="wy-nav-top" aria-label="top navigation"> |
| |
| <i data-toggle="wy-nav-top" class="fa fa-bars"></i> |
| <a href="index.html">Apache Guacamole</a> |
| |
| </nav> |
| |
| |
| <div class="wy-nav-content"> |
| |
| <div class="rst-content"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <div role="navigation" aria-label="breadcrumbs navigation"> |
| |
| <ul class="wy-breadcrumbs"> |
| |
| <li><a href="index.html" class="icon icon-home"></a> »</li> |
| |
| <li>Proxying Guacamole</li> |
| |
| |
| <li class="wy-breadcrumbs-aside"> |
| |
| |
| <a href="_sources/reverse-proxy.md.txt" rel="nofollow"> View page source</a> |
| |
| |
| </li> |
| |
| </ul> |
| |
| |
| <hr/> |
| </div> |
| <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> |
| <div itemprop="articleBody"> |
| |
| <div class="section" id="proxying-guacamole"> |
| <h1>Proxying Guacamole<a class="headerlink" href="#proxying-guacamole" title="Permalink to this headline">¶</a></h1> |
| <p>Like most web applications, Guacamole can be placed behind a reverse proxy. For |
| production deployments of Guacamole, this is <em>highly recommended</em>. It provides |
| flexibility and, if your proxy is properly configured for SSL, encryption.</p> |
| <p>Proxying isolates privileged operations within native applications that can |
| safely drop those privileges when no longer needed, using Java only for |
| unprivileged tasks. On Linux and UNIX systems, a process must be running with |
| root privileges to listen on any port under 1024, including the standard HTTP |
| and HTTPS ports (80 and 443 respectively). If the servlet container instead |
| listens on a higher port, such as the default port 8080, it can run as a |
| reduced-privilege user, allowing the reverse proxy to bear the burden of root |
| privileges. As a native application, the reverse proxy can make system calls to |
| safely drop root privileges once the port is open; a Java application like |
| Tomcat cannot do this.</p> |
| <div class="section" id="preparing-your-servlet-container"> |
| <span id="preparing-servlet-container"></span><h2>Preparing your servlet container<a class="headerlink" href="#preparing-your-servlet-container" title="Permalink to this headline">¶</a></h2> |
| <p>Your servlet container is most likely already configured to listen for HTTP |
| connections on port 8080 as this is the default. If this is the case, and you |
| can already access Guacamole over port 8080 from a web browser, you need not |
| make any further changes to its configuration.</p> |
| <p>If you <em>have</em> changed this, perhaps with the intent of proxying Guacamole over |
| AJP, <em>change it back</em>. Using Guacamole over AJP is unsupported as it is known |
| to cause problems, namely:</p> |
| <ol class="simple"> |
| <li><p>WebSocket will not work over AJP, forcing Guacamole to fallback to HTTP, |
| possibly resulting in reduced performance.</p></li> |
| <li><p>Apache 2.4.3 and older does not support the HTTP PATCH method over AJP, |
| preventing the Guacamole management interface from functioning properly.</p></li> |
| </ol> |
| <p>The connector entry within <code class="docutils literal notranslate"><span class="pre">conf/server.xml</span></code> should look like this:</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt"><Connector</span> <span class="na">port=</span><span class="s">"8080"</span> <span class="na">protocol=</span><span class="s">"HTTP/1.1"</span> |
| <span class="na">connectionTimeout=</span><span class="s">"20000"</span> |
| <span class="na">URIEncoding=</span><span class="s">"UTF-8"</span> |
| <span class="na">redirectPort=</span><span class="s">"8443"</span> <span class="nt">/></span> |
| </pre></div> |
| </div> |
| <p>Be sure to specify the <code class="docutils literal notranslate"><span class="pre">URIEncoding="UTF-8"</span></code> attribute as above to ensure that |
| connection names, user names, etc. are properly received by the web |
| application. If you will be creating connections that have Cyrillic, Chinese, |
| Japanese, or other non-Latin characters in their names or parameter values, |
| this attribute is required.</p> |
| <div class="section" id="setting-up-the-remote-ip-valve"> |
| <span id="tomcat-remote-ip"></span><h3>Setting up the Remote IP Valve<a class="headerlink" href="#setting-up-the-remote-ip-valve" title="Permalink to this headline">¶</a></h3> |
| <p>By default, when Tomcat is behind a reverse proxy, the remote IP address of the |
| client that it sees is that of the proxy rather than the original client. In |
| order to allow applications hosted within Tomcat, like Guacamole, to see the |
| actual IP address of the client, you have to configure both the reverse proxy |
| and Tomcat.</p> |
| <p>Because the remote IP address in Guacamole is used for auditing of user logins |
| and connections and could potentially be used for authentication, it is |
| important that you are either in direct control of the proxy server or you |
| explicitly trust it. Passing the remote IP address is done using the |
| <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code> header, and, as with most HTTP headers, attackers can attempt |
| to spoof this header in order to manipulate the behavior of the web server, |
| gain unauthorized access to the system, or attempt to disguise the host or IP |
| address they are coming from.</p> |
| <p>One final caveat: This may not work as expected if there are other upstream |
| proxy servers between your reverse proxy and the clients access Guacamole. |
| Other proxies or firewalls can mask the IP address of the client, and if the |
| configuration of those is not within your control you may end up with multiple |
| clients appearing to come from the same IP address or host. Make sure you take |
| this into account when configuring the system and looking at the data provided.</p> |
| <p>Configuring Tomcat to pass through the remote IP address provided by the |
| reverse proxy in the <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code> header requires the configuration of |
| what Tomcat calls a Valve. In this case, it is the |
| <a class="reference external" href="https://tomcat.apache.org/tomcat-8.5-doc/config/valve.html#Remote_IP_Valve"><code class="docutils literal notranslate"><span class="pre">RemoteIpValve</span></code></a> |
| and is configured in the <code class="docutils literal notranslate"><span class="pre">conf/server.xml</span></code> file, in the <code class="docutils literal notranslate"><span class="pre"><Host></span></code> section:</p> |
| <div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt"><Valve</span> <span class="na">className=</span><span class="s">"org.apache.catalina.valves.RemoteIpValve"</span> |
| <span class="na">internalProxies=</span><span class="s">"127.0.0.1"</span> |
| <span class="na">remoteIpHeader=</span><span class="s">"x-forwarded-for"</span> |
| <span class="na">remoteIpProxiesHeader=</span><span class="s">"x-forwarded-by"</span> |
| <span class="na">protocolHeader=</span><span class="s">"x-forwarded-proto"</span> <span class="nt">/></span> |
| </pre></div> |
| </div> |
| <p>The <code class="docutils literal notranslate"><span class="pre">internalProxies</span></code> value should be set to the IP address or addresses of any |
| and all reverse proxy servers that will be accessing this Tomcat instance |
| directly. Often it is run on the same system that runs Tomcat, but in other |
| cases (for example, when running Docker), it may be on a different |
| system/container and may need to be set to the actual IP address of the reverse |
| proxy system. Only proxy servers listed in the <code class="docutils literal notranslate"><span class="pre">internalProxies</span></code> or |
| <code class="docutils literal notranslate"><span class="pre">trustedProxies</span></code> parameters will be allowed to manipulate the remote IP address |
| information. The other parameters in this configuration line allow you to |
| control which headers coming from the proxy server(s) are used for various |
| remote host information. They are as follows:</p> |
| <dl class="simple myst"> |
| <dt><code class="docutils literal notranslate"><span class="pre">remoteIpHeader</span></code></dt><dd><p>The header that is queried to learn the client IP address of the client |
| that originated the request. The standard value is <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code>, but |
| can be configured to any header you like. The IP address in this header |
| will be available to Java applications in the <code class="docutils literal notranslate"><span class="pre">request.getRemoteAddr()</span></code> |
| method.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">remoteIpProxiesHeader</span></code></dt><dd><p>The header that is queried to learn the IP address of the proxy server |
| that forwarded the request. The default value is <code class="docutils literal notranslate"><span class="pre">X-Forwarded-By</span></code>, but can |
| be configured to any header that fits your environment. This value will |
| only be allowed by the valve if the proxy used is listed in the |
| <code class="docutils literal notranslate"><span class="pre">trustedProxies</span></code> parameter. Otherwise this header will not be available.</p> |
| </dd> |
| <dt><code class="docutils literal notranslate"><span class="pre">protocolHeader</span></code></dt><dd><p>The header that is queried to determine the protocol that the client used |
| to connect to the service. The default value is <code class="docutils literal notranslate"><span class="pre">X-Forwarded-Proto</span></code>, but |
| can be configured to fit your environment.</p> |
| </dd> |
| </dl> |
| <p>In addition to configuring Tomcat to properly handle these headers, you also |
| may need to configure your reverse proxy appropriately to send the headers. You |
| can find instructions for this in <a class="reference internal" href="#nginx"><span class="std std-ref">Nginx</span></a> - the Apache web server passes it |
| through by default.</p> |
| </div> |
| </div> |
| <div class="section" id="nginx"> |
| <span id="id1"></span><h2>Nginx<a class="headerlink" href="#nginx" title="Permalink to this headline">¶</a></h2> |
| <p>Nginx can be used as a reverse proxy, and supports WebSocket out-of-the-box |
| <a class="reference external" href="http://nginx.com/blog/websocket-nginx/">since version 1.3</a>. Both Apache and |
| Nginx require some additional configuration for proxying of WebSocket to work |
| properly.</p> |
| <div class="section" id="proxying-with-nginx"> |
| <span id="id2"></span><h3>Proxying Guacamole<a class="headerlink" href="#proxying-with-nginx" title="Permalink to this headline">¶</a></h3> |
| <p>Nginx does support WebSocket for proxying, but requires that the “Connection” |
| and “Upgrade” HTTP headers are set explicitly due to the nature of the |
| WebSocket protocol. From the Nginx documentation:</p> |
| <blockquote> |
| <div><p>NGINX supports WebSocket by allowing a tunnel to be set up between a client |
| and a back-end server. For NGINX to send the Upgrade request from the client |
| to the back-end server, Upgrade and Connection headers must be set |
| explicitly. …</p> |
| </div></blockquote> |
| <p>The proxy configuration belongs within a dedicated |
| <a class="reference external" href="http://nginx.org/en/docs/http/ngx_http_core_module.html#location%3E"><code class="docutils literal notranslate"><span class="pre">location</span></code></a> |
| block, declaring the backend hosting Guacamole and explicitly specifying the |
| “<code class="docutils literal notranslate"><span class="pre">Connection</span></code>” and “<code class="docutils literal notranslate"><span class="pre">Upgrade</span></code>” headers mentioned earlier:</p> |
| <div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="k">location</span> <span class="s">/guacamole/</span> <span class="p">{</span> |
| <span class="kn">proxy_pass</span> <span class="s">http://HOSTNAME:8080</span><span class="p">;</span> |
| <span class="kn">proxy_buffering</span> <span class="no">off</span><span class="p">;</span> |
| <span class="kn">proxy_http_version</span> <span class="mi">1</span><span class="s">.1</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Upgrade</span> <span class="nv">$http_upgrade</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Connection</span> <span class="nv">$http_connection</span><span class="p">;</span> |
| <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| <p>Here, <code class="docutils literal notranslate"><span class="pre">HOSTNAME</span></code> is the hostname or IP address of the machine hosting your |
| servlet container, and 8080 is the port that servlet container is configured to |
| use. You will need to replace these values with the correct values for your |
| server.</p> |
| <p>Related to the <code class="docutils literal notranslate"><span class="pre">RemoteIpValve</span></code> configuration for tomcat, documented in |
| <a class="reference internal" href="#tomcat-remote-ip"><span class="std std-ref">Setting up the Remote IP Valve</span></a>, the <code class="docutils literal notranslate"><span class="pre">proxy_set_header</span> <span class="pre">X-Forwarded-For</span> <span class="pre">$proxy_add_x_forwarded_for;</span></code> line is important if you want the |
| <code class="docutils literal notranslate"><span class="pre">X-Forwarded-For</span></code> header to be passed through to the web application server and |
| available to applications running inside it.</p> |
| <div class="admonition important"> |
| <p class="admonition-title">Important</p> |
| <p><em>Do not forget to specify “<code class="docutils literal notranslate"><span class="pre">proxy_buffering</span> <span class="pre">off</span></code>”.</em></p> |
| <p>Most proxies, including Nginx, will buffer all data sent over the connection, |
| waiting until the connection is closed before sending that data to the client. |
| As Guacamole’s HTTP tunnel relies on streaming data to the client over an open |
| connection, excessive buffering will effectively block Guacamole connections, |
| rendering Guacamole useless.</p> |
| <p><em>If the option “<code class="docutils literal notranslate"><span class="pre">proxy_buffering</span> <span class="pre">off</span></code>” is not specified, Guacamole may not |
| work</em>.</p> |
| </div> |
| </div> |
| <div class="section" id="changing-the-path"> |
| <span id="changing-path-with-nginx"></span><h3>Changing the path<a class="headerlink" href="#changing-the-path" title="Permalink to this headline">¶</a></h3> |
| <p>If you wish to serve Guacamole through Nginx under a path other than |
| <code class="docutils literal notranslate"><span class="pre">/guacamole/</span></code>, the easiest method is to simply rename the <code class="docutils literal notranslate"><span class="pre">.war</span></code> file. For |
| example, if intending to server Guacamole at <code class="docutils literal notranslate"><span class="pre">/new-path/</span></code>, you would:</p> |
| <ol> |
| <li><p>Rename <code class="docutils literal notranslate"><span class="pre">guacamole.war</span></code> to <code class="docutils literal notranslate"><span class="pre">new-path.war</span></code>.</p></li> |
| <li><p>Update the path within the Nginx configuration to reflect the new |
| path:</p> |
| <div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="hll"><span class="k">location</span> <span class="s">/new-path/</span> <span class="p">{</span> |
| </span> <span class="kn">proxy_pass</span> <span class="s">http://HOSTNAME:8080</span><span class="p">;</span> |
| <span class="kn">proxy_buffering</span> <span class="no">off</span><span class="p">;</span> |
| <span class="kn">proxy_http_version</span> <span class="mi">1</span><span class="s">.1</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Upgrade</span> <span class="nv">$http_upgrade</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Connection</span> <span class="nv">$http_connection</span><span class="p">;</span> |
| <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| </li> |
| </ol> |
| <p>Alternatively, the configuration can be altered slightly to handle requests at |
| a different location externally while still serving internal requests at |
| <code class="docutils literal notranslate"><span class="pre">/guacamole/</span></code>:</p> |
| <div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="hll"><span class="k">location</span> <span class="s">/new-path/</span> <span class="p">{</span> |
| </span><span class="hll"> <span class="kn">proxy_pass</span> <span class="s">http://HOSTNAME:8080/guacamole/</span><span class="p">;</span> |
| </span> <span class="kn">proxy_buffering</span> <span class="no">off</span><span class="p">;</span> |
| <span class="kn">proxy_http_version</span> <span class="mi">1</span><span class="s">.1</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Upgrade</span> <span class="nv">$http_upgrade</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Connection</span> <span class="nv">$http_connection</span><span class="p">;</span> |
| <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| </div> |
| <div class="section" id="adjusting-file-upload-limits"> |
| <span id="nginx-file-upload-size"></span><h3>Adjusting file upload limits<a class="headerlink" href="#adjusting-file-upload-limits" title="Permalink to this headline">¶</a></h3> |
| <p>When proxying Guacamole through Nginx, you may run into issues with the default |
| limitations that Nginx places on file uploads (1MB). The errors you receive can |
| be non-intuitive (permission denied, for example), but may be indicative of |
| these limits. The <code class="docutils literal notranslate"><span class="pre">client_max_body_size</span></code> parameter can be set within the |
| <code class="docutils literal notranslate"><span class="pre">location</span></code> block to configure the maximum file upload size:</p> |
| <div class="highlight-nginx notranslate"><div class="highlight"><pre><span></span><span class="k">location</span> <span class="s">/guacamole/</span> <span class="p">{</span> |
| <span class="kn">proxy_pass</span> <span class="s">http://HOSTNAME:8080</span><span class="p">;</span> |
| <span class="kn">proxy_buffering</span> <span class="no">off</span><span class="p">;</span> |
| <span class="kn">proxy_http_version</span> <span class="mi">1</span><span class="s">.1</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">X-Forwarded-For</span> <span class="nv">$proxy_add_x_forwarded_for</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Upgrade</span> <span class="nv">$http_upgrade</span><span class="p">;</span> |
| <span class="kn">proxy_set_header</span> <span class="s">Connection</span> <span class="nv">$http_connection</span><span class="p">;</span> |
| <span class="hll"> <span class="kn">client_max_body_size</span> <span class="s">1g</span><span class="p">;</span> |
| </span> <span class="kn">access_log</span> <span class="no">off</span><span class="p">;</span> |
| <span class="p">}</span> |
| </pre></div> |
| </div> |
| </div> |
| </div> |
| <div class="section" id="apache-and-mod-proxy"> |
| <span id="apache"></span><h2>Apache and mod_proxy<a class="headerlink" href="#apache-and-mod-proxy" title="Permalink to this headline">¶</a></h2> |
| <p>Apache supports reverse proxy configurations through |
| <a class="reference external" href="http://httpd.apache.org/docs/2.4/mod/mod_proxy.html">mod_proxy</a>. Apache 2.4.5 |
| and later also support proxying of WebSocket through a sub-module called |
| <a class="reference external" href="http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html">mod_proxy_wstunnel</a>. |
| Both of these modules will need to be enabled for proxying of Guacamole to work |
| properly.</p> |
| <p>Lacking mod_proxy_wstunnel, it is still possible to proxy Guacamole, but |
| Guacamole will be unable to use WebSocket. It will instead fallback to using |
| the HTTP tunnel, resulting in reduced performance.</p> |
| <div class="section" id="proxying-with-apache"> |
| <span id="id3"></span><h3>Proxying Guacamole<a class="headerlink" href="#proxying-with-apache" title="Permalink to this headline">¶</a></h3> |
| <p>Configuring Apache to proxy HTTP requests requires using the <code class="docutils literal notranslate"><span class="pre">ProxyPass</span></code> and |
| <code class="docutils literal notranslate"><span class="pre">ProxyPassReverse</span></code> directives, which are provided by the mod_proxy module. |
| These directives describe how HTTP traffic should be routed to the web server |
| behind the proxy:</p> |
| <div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="nt"><Location</span> <span class="s">/guacamole/</span><span class="nt">></span> |
| <span class="nb">Order</span> allow,deny |
| <span class="nb">Allow</span> from <span class="k">all</span> |
| <span class="nb">ProxyPass</span> http://HOSTNAME:8080/guacamole/ flushpackets=on |
| <span class="nb">ProxyPassReverse</span> http://HOSTNAME:8080/guacamole/ |
| <span class="nt"></Location></span> |
| </pre></div> |
| </div> |
| <p>Here, <code class="docutils literal notranslate"><span class="pre">HOSTNAME</span></code> is the hostname or IP address of the machine hosting your |
| servlet container, and <code class="docutils literal notranslate"><span class="pre">8080</span></code> is the port that servlet container is configured |
| to use. You will need to replace these values with the correct values for your |
| server.</p> |
| <div class="admonition important"> |
| <p class="admonition-title">Important</p> |
| <p><em>Do not forget the <code class="docutils literal notranslate"><span class="pre">flushpackets=on</span></code> option.</em></p> |
| <p>Most proxies, including mod_proxy, will buffer all data sent over the |
| connection, waiting until the connection is closed before sending that data to |
| the client. As Guacamole’s HTTP tunnel relies on streaming data to the client |
| over an open connection, excessive buffering will effectively block Guacamole |
| connections, rendering Guacamole useless.</p> |
| <p><em>If the option <code class="docutils literal notranslate"><span class="pre">flushpackets=on</span></code> is not specified, Guacamole may not work</em>.</p> |
| </div> |
| </div> |
| <div class="section" id="proxying-the-websocket-tunnel"> |
| <span id="websocket-and-apache"></span><h3>Proxying the WebSocket tunnel<a class="headerlink" href="#proxying-the-websocket-tunnel" title="Permalink to this headline">¶</a></h3> |
| <p>Apache will not automatically proxy WebSocket connections, but you can proxy |
| them separately with Apache 2.4.5 and later using mod_proxy_wstunnel. After |
| enabling mod_proxy_wstunnel a secondary <code class="docutils literal notranslate"><span class="pre">Location</span></code> section can be added which |
| explicitly proxies the Guacamole WebSocket tunnel, located at |
| <code class="docutils literal notranslate"><span class="pre">/guacamole/websocket-tunnel</span></code>:</p> |
| <div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="nt"><Location</span> <span class="s">/guacamole/</span><span class="nt">></span> |
| <span class="nb">Order</span> allow,deny |
| <span class="nb">Allow</span> from <span class="k">all</span> |
| <span class="nb">ProxyPass</span> http://HOSTNAME:8080/guacamole/ flushpackets=on |
| <span class="nb">ProxyPassReverse</span> http://HOSTNAME:8080/guacamole/ |
| <span class="nt"></Location></span> |
| |
| <span class="hll"><span class="nt"><Location</span> <span class="s">/guacamole/websocket-tunnel</span><span class="nt">></span> |
| </span><span class="hll"> <span class="nb">Order</span> allow,deny |
| </span><span class="hll"> <span class="nb">Allow</span> from <span class="k">all</span> |
| </span><span class="hll"> <span class="nb">ProxyPass</span> ws://HOSTNAME:8080/guacamole/websocket-tunnel |
| </span><span class="hll"> <span class="nb">ProxyPassReverse</span> ws://HOSTNAME:8080/guacamole/websocket-tunnel |
| </span><span class="hll"><span class="nt"></Location></span> |
| </span></pre></div> |
| </div> |
| <p>Lacking this, Guacamole will still work by using normal HTTP, but network |
| latency will be more pronounced with respect to user input, and performance may |
| be lower.</p> |
| <div class="admonition important"> |
| <p class="admonition-title">Important</p> |
| <p><strong>The <code class="docutils literal notranslate"><span class="pre">Location</span></code> section for <code class="docutils literal notranslate"><span class="pre">/guacamole/websocket-tunnel</span></code> must be placed after |
| the <code class="docutils literal notranslate"><span class="pre">Location</span></code> section for the rest of Guacamole.</strong></p> |
| <p>Apache evaluates all Location sections, giving priority to the last section |
| that matches. If the <code class="docutils literal notranslate"><span class="pre">/guacamole/websocket-tunnel</span></code> section comes first, the |
| section for <code class="docutils literal notranslate"><span class="pre">/guacamole/</span></code> will match instead, and WebSocket will not be proxied |
| correctly.</p> |
| </div> |
| </div> |
| <div class="section" id="changing-path-with-apache"> |
| <span id="id4"></span><h3>Changing the path<a class="headerlink" href="#changing-path-with-apache" title="Permalink to this headline">¶</a></h3> |
| <p>If you wish to serve Guacamole through Apache under a path other than |
| <code class="docutils literal notranslate"><span class="pre">/guacamole/</span></code>, the easiest method is to simply rename the <code class="docutils literal notranslate"><span class="pre">.war</span></code> file. For |
| example, if intending to server Guacamole at <code class="docutils literal notranslate"><span class="pre">/new-path/</span></code>, you would:</p> |
| <ol> |
| <li><p>Rename <code class="docutils literal notranslate"><span class="pre">guacamole.war</span></code> to <code class="docutils literal notranslate"><span class="pre">new-path.war</span></code>.</p></li> |
| <li><p>Update the paths within the Apache configuration to reflect the new path:</p> |
| <div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="hll"><span class="nt"><Location</span> <span class="s">/new-path/</span><span class="nt">></span> |
| </span> <span class="nb">Order</span> allow,deny |
| <span class="nb">Allow</span> from <span class="k">all</span> |
| <span class="hll"> <span class="nb">ProxyPass</span> http://HOSTNAME:8080/new-path/ flushpackets=on |
| </span><span class="hll"> <span class="nb">ProxyPassReverse</span> http://HOSTNAME:8080/new-path/ |
| </span><span class="nt"></Location></span> |
| |
| <span class="hll"><span class="nt"><Location</span> <span class="s">/new-path/websocket-tunnel</span><span class="nt">></span> |
| </span> <span class="nb">Order</span> allow,deny |
| <span class="nb">Allow</span> from <span class="k">all</span> |
| <span class="hll"> <span class="nb">ProxyPass</span> ws://HOSTNAME:8080/new-path/websocket-tunnel |
| </span><span class="hll"> <span class="nb">ProxyPassReverse</span> ws://HOSTNAME:8080/new-path/websocket-tunnel |
| </span><span class="nt"></Location></span> |
| </pre></div> |
| </div> |
| </li> |
| </ol> |
| <p>Alternatively, the configuration can be altered slightly to handle requests at |
| a different location externally while still serving internal requests at |
| <code class="docutils literal notranslate"><span class="pre">/guacamole/</span></code>:</p> |
| <div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="hll"><span class="nt"><Location</span> <span class="s">/new-path/</span><span class="nt">></span> |
| </span> <span class="nb">Order</span> allow,deny |
| <span class="nb">Allow</span> from <span class="k">all</span> |
| <span class="nb">ProxyPass</span> http://HOSTNAME:8080/guacamole/ flushpackets=on |
| <span class="nb">ProxyPassReverse</span> http://HOSTNAME:8080/guacamole/ |
| <span class="nt"></Location></span> |
| |
| <span class="hll"><span class="nt"><Location</span> <span class="s">/new-path/websocket-tunnel</span><span class="nt">></span> |
| </span> <span class="nb">Order</span> allow,deny |
| <span class="nb">Allow</span> from <span class="k">all</span> |
| <span class="nb">ProxyPass</span> ws://HOSTNAME:8080/guacamole/websocket-tunnel |
| <span class="nb">ProxyPassReverse</span> ws://HOSTNAME:8080/guacamole/websocket-tunnel |
| <span class="nt"></Location></span> |
| </pre></div> |
| </div> |
| </div> |
| <div class="section" id="disabling-logging-of-tunnel-requests"> |
| <span id="disable-tunnel-logging"></span><h3>Disabling logging of tunnel requests<a class="headerlink" href="#disabling-logging-of-tunnel-requests" title="Permalink to this headline">¶</a></h3> |
| <p>If WebSocket is unavailable, Guacamole will fallback to using an HTTP-based |
| tunnel. The Guacamole HTTP tunnel works by transferring a continuous stream of |
| data over multiple short-lived streams, each associated with a separate HTTP |
| request. By default, Apache will log each of these requests, resulting in a |
| rather bloated access log.</p> |
| <p>There is little value in a log file filled with identical tunnel requests, so |
| it is recommended to explicitly disable logging of those requests. Apache does |
| provide a means of matching URL patterns and setting environment variables |
| based on whether the URL matches. Logging can then be restricted to requests |
| which lack this environment variable:</p> |
| <div class="highlight-apache notranslate"><div class="highlight"><pre><span></span><span class="nb">SetEnvIf</span> Request_URI <span class="s2">"^/guacamole/tunnel"</span> dontlog |
| <span class="nb">CustomLog</span> <span class="sx">/var/log/apache2/guac.log</span> common env=!dontlog |
| </pre></div> |
| </div> |
| <p>Note that if you are serving Guacamole under a path different from |
| <code class="docutils literal notranslate"><span class="pre">/guacamole/</span></code>, you will need to change the value of <code class="docutils literal notranslate"><span class="pre">Request_URI</span></code> above |
| accordingly.</p> |
| </div> |
| </div> |
| </div> |
| |
| |
| </div> |
| |
| </div> |
| <footer> |
| <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation"> |
| <a href="configuring-guacamole.html" class="btn btn-neutral float-right" title="Configuring Guacamole" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> |
| <a href="guacamole-docker.html" class="btn btn-neutral float-left" title="Installing Guacamole with Docker" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> |
| </div> |
| |
| <hr/> |
| |
| <div role="contentinfo"> |
| <p>Copyright © 2021 <a href="http://www.apache.org/">The Apache Software Foundation</a>, |
| Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>. |
| Apache Guacamole, Guacamole, Apache, the Apache feather logo, and the Apache Guacamole project logo are |
| trademarks of The Apache Software Foundation.</p> |
| |
| </div> |
| |
| |
| |
| Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a |
| |
| <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> |
| |
| provided by <a href="https://readthedocs.org">Read the Docs</a>. |
| |
| </footer> |
| </div> |
| </div> |
| |
| </section> |
| |
| </div> |
| |
| |
| <script type="text/javascript"> |
| jQuery(function () { |
| SphinxRtdTheme.Navigation.enable(true); |
| }); |
| </script> |
| |
| |
| |
| |
| |
| |
| <!-- Google Analytics --> |
| <script type="text/javascript"> |
| (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ |
| (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), |
| m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) |
| })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); |
| |
| ga('create', 'UA-75289145-1', 'auto'); |
| ga('send', 'pageview'); |
| </script> |
| </body> |
| </html> |