Debian 8.6, Proxy guacamole via Apache2 using HTTPS and Fail2Ban

In my previous article I explained how to install guacamole on Debian 8.6, in this article I cover how to publish this over https using Apache2, as well as using fail2ban and ufw in an attempt to protect the service.

First, install required pre-reqs:

apt-get install apache2 libapache2-mod-proxy-html

Now, we will modify the tomcat8 config

vi /etc/tomcat8/server.xml

Uncomment and modify the AJP/1.3 line accordingly:

 <Connector port="8009" protocol="AJP/1.3"
    URIEncoding="UTF-8"
    redirectPort="8443" />

Now restart tomcat8:

systemctl restart tomcat8.service

Now for Apache2 configuration. Firstly you’ll need to enable the following modules using a2enmod:

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
a2enmod log_config
a2enmod ssl

Now for SSL configuration; generate your private key and CSR (yo can then process these with an external, third-part CA such as StartSSL – which is free.

openssl req -newkey rsa:2048 -keyout guac.key -out guac.csr

I’m now assuming you now have the following files:

  1. Root certificate bundle for your CA (.crt from third-part CA)
  2. Public key for your certificate (.crt from third-part CA)
  3. Private key for your certificate (.key file form OpenSSL command)

We’ll now copy these files to /etc/apache2/ssl:

mkdir /etc/apache2/ssl
cp 1_root_bundle.crt /etc/apache2/ssl
cp 2_guacamole.domain.com.crt /etc/apache2/ssl
cp guac.key /etc/apache2/ssl

Note, your .key file (private key) likely has a passphrase, you’ll want to remove this otherwise you’ll have to manually enter this when Apache2 loads:

openssl rsa -in guac.key -out guac-nopass.key

Now, protect those files!

chmod 600 /etc/apache2/ssl/*

Create a root directory for the new HTTPS site and enable mod_ssl:

mkdir /srv/www-guacamole

Now, we’ll configure the site definition in Apache2

vi /etc/apache2/sites-available/guacamole.conf

Contents as below – make sure you change the URL in bold – note the HTTPS definition uses IP address, not hostname. See this URL for more details, but by using hostname you will receive the following errors:

SSL received a record that exceeded the maximum permissible length. Error code: SSL_ERROR_RX_RECORD_TOO_LONG remote client

<VirtualHost guacamole.domain.com:80>
    ServerName guacamole.domain.com:80
    # Redirect traffic from 80 to 443, and also from / to /guacamole/
    Redirect permanent / https://guacamole.domain.com/guacamole/
    Redirect permanent /guacamole https://guacamole.domain.com/guacamole/
</VirtualHost>
<VirtualHost 192.168.1.249:443>

    # Redirect traffic from / to /guacamole/        
    Redirect permanent / https://guacamole.domain.com/guacamole/
    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3
    SSLCertificateFile /etc/apache2/ssl/2_guacamole.domain.com.crt
    SSLCertificateKeyFile /etc/apache2/ssl/guac.key
    SSLCertificateChainFile /etc/apache2/ssl/1_root_bundle.crt
    SSLCipherSuite ALL:!DH:!EXPORT:!RC4:+HIGH:+MEDIUM:!LOW:!aNULL:!eNULL
    ServerName guacamole.domain.com:443
    DocumentRoot /srv/www-guacamole	
    <Location /guacamole/>
        Order allow,deny
        Allow from all
        ProxyPass http://localhost:8080/guacamole/ max=20 flushpackets=on
        ProxyPassReverse http://localhost:8080/guacamole/
        SetEnvIf Request_URI "^/guacamole/tunnel" dontlog
    </Location>
    <Location /guacamole/websocket-tunnel>
        Order allow,deny
        Allow from all
        ProxyPass ws://localhost:8080/guacamole/websocket-tunnel
        ProxyPassReverse ws://localhost:8080/guacamole/websocket-tunnel
    </Location>
</VirtualHost>
CustomLog /var/log/apache2/guac.log common env=!dontlog

Next we need to enable this site using a2ensite:

a2ensite guacamole.conf

Now, restart Apache2:

systemctl restart apache2

Next, configure Apache2 to load on boot:

systemctl enable apache2

You’ll now be able to access your guacamole instance by using the URL: https://<your chosen url>

Now for the fail2ban installation and configuration – first download and install fail2ban:

cd ~
git clone https://github.com/fail2ban/fail2ban
cd fail2ban
python setup.py install
cp files/debian-initd /etc/init.d/fail2ban
systemctl daemon-reload
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

No we’ll enable the guacamole by editing /etc/fail2ban/jail.local

vi /etc/fail2ban/jail.local

# Add a new line "enabled = true" under [guacamole]
[guacamole]
enabled = true
port     = http,https
logpath  = /var/log/tomcat*/catalina.out

# Now save and close /etc/fail2ban/jail.local

# Prevent local network from banning - change as per your setup
sed -i "s|ignoreip = 127.0.0.1/8 ::1|ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24|" /etc/fail2ban/jail.local

Lastly for fail2ban config, we need to adjust the regexthat detects failures – as per this site (where I found this fix!).

vi /etc/fail2ban/filter.d/guacamole.conf

# change this incorrect regex: failregex = ^.*\nWARNING: Authentication attempt from <HOST> for user "[^"]*" failed\.$ to this:

failregex = \bAuthentication attempt from \[<HOST>(?:,.*)?\] for user ".*" failed\.

Now, enable fail2ban to start on boot

systemctl enable fail2ban

Home straight now… ufw config. The commands below are specifically designed for the solution outlined in this post – please review and consider rules that apply to your environment. If you lose access to your server it’s not my fault!

# Install Uncomplicated Firewall
apt-get install ufw

# Allow HTTPS from 192.168.1.0/24 to guacamole/apache2 server
ufw allow from 192.168.1.0/24 to 192.168.1.249 port 443
# Allow HTTP from local LAN (for redirect only)
ufw allow from 192.168.1.0/24 to 192.168.1.249 port 80
# Enable Firewall
ufw enable