Changing the guacamole MySQL User Password

From an SSH shell execute the following commands to change the MySQL user password:

mysql -u root -h localhost -p'<root password>'
USE guacamole;
SET PASSWORD FOR 'guacamole'@'localhost' = PASSWORD('<new password>');

Now modify /etc/guacamole/guacamole.properties ensuring you update the value for “mysql-password: <password>”

# MySQL properties
mysql-hostname: localhost
mysql-port: 3306
mysql-database: guacamole
mysql-username: guacamole
mysql-password: <password>

Finally restart tomcat8

systemctl restart tomcat8

Creating an SMB / CIFS Share on Ubuntu 16.04 LTS

As part of my KVM/QEMU setup I needed to be able to copy media from a Windows PC to a Linux Ubuntu Server, for ease I wanted to do this via SMB/ CIFS – I was also using NFS for linux <> linux file sharing, so opted to use the same bind mount point for both NFS and SMBD.

Relevant /etc/fstab entries as below:

# Physical drive mount point
/dev/sdb1 /mnt/media1 ext4 defaults 0 2

# Media1; NFS/ SMBD mountpoint
/mnt/media1 /export/media1 none bind 0 0

Install smbd on Ubuntu server:

apt-get install samba
cp /etc/samba/smb.conf ~
vi /etc/samba/smb.conf

Create a samba login for your user account – in my case, my linux user account was “chris” – you will use this to access the share form your windows client (expect a prompt for username/ password when you browse to the share):

sudo smbpasswd -a chris

Configure smbd – modify paths/ username accordingly:

vi /etc/samba/smbd.conf
# add this to the bottom of the file

[Media]
comment = My Share
path = /export/media1
browsable = yes
valid users = chris
read only = no
create mask = 0755

Finally, start SMBD and set to start automatically on boot – once started, you should be able to browse to “\\<IP/DNS Name of Ubuntu Server>”

# start smbd
service smbd restart

# enable smbd on boot
systemctl enable smbd

Creating and Managing VMs in Ubuntu Server 16.10

I recently bought and setup a Asrock DeskMini with a i5 6400 (will take any desktop S1151 65W CPU), 16GB RAM and an SSDs to act as a KVM/ QEMU host at home. At some point I’ll share the end-to-end setup, but for now suffice to say I am really happy with this very flexible and tiny box of computing power!

I did however want to share some useful VM setup and management commands I have been using, some useful background information:

  • Host O/S Ubuntu Server 16.10 – with “Virtual Machine host” option select at install time.
  • Network configuration as below
apt-get install -y bridge-utils

cat /etc/network/interfaces

 # The loopback network interface
 auto lo
 iface lo inet loopback

 # The primary network interface
 auto br0
 iface br0 inet static
             address 192.168.1.240
             netmask 255.255.255.0
             broadcast 192.168.1.255
             gateway 192.168.1.1
             dns-nameserver 192.168.1.1
             bridge_ports enp0s31f6
             bridge_stp off
             bridge_fd 0
  • Storage layout as below:
 sdb
 ├─sdb4 /var/kvm/images
 ├─sdb2 [SWAP]
 ├─sdb3 part /
 └─sdb1 part /boot/efi

Install virtinst:

apt-get install virtinst

Create directories to store vhd files and iso files used for installing VMs

mkdir -p /var/kvm/images/vm
mkdir -p /var/kvm/images/iso

 

Creating New Virtual Machines

Ubuntu Server 16.04 LTS (from an ISO)

First download Ubuntu server 16.04 LTS ISO:

cd /var/kvm/images/iso
wget http://releases.ubuntu.com/16.04.1/ubuntu-16.04.1-server-amd64.iso

Create the virtual machine – requires the use of sudo – this machine will have 4 vCPUs, 4GB RAM and a 32GB vhd.

virt-install \
 --virt-type=kvm \
 --hvm \
 --name vlinux1 \
 --ram 4096 \
 --disk path=/var/kvm/images/vm/vlinux1.qcow2,size=32,bus=virtio,format=qcow2 \
 --vcpus=4 \
 --os-type linux \
 --os-variant ubuntu16.04 \
 --network bridge=br0 \
 --graphics vnc,listen=0.0.0.0 \
 --noautoconsole \
 --console pty,target_type=serial \
 --cdrom /var/kvm/images/iso/ubuntu-16.04.1-server-amd64.iso

Complete the installation using TightVNC (or another VNC client) to connect via <kvmhostip>:59000

Once completed, the virtual machine will shutdown. Once shutdown the VNC graphics will no longer function, even when you restart the mahcine.

You can configure persistent VNC-based graphics by modifying the XML file associated with the virtual machine – stored under /etc/libvirt/qemu/

vi /etc/libvirt/qemu/vlinux1.xml

# Now remove all lines relating to <graphics> and replace with single line as below:

<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'/>

When you start the machine, you’ll be able to reconnect via VNC. The port number automatically increments for every VM configured like this – based on the order in which the machines start up/ are started up.

 

Managing Virtual Machines

Use virsh to manage and configure VMs – examples below – all require the use of sudo.

# List powered-on / running virtual machines
virsh list --all

# Start / power-on virtual machine "vlinux1"
virsh start vlinux1

# Reset virtual machine "vlinux1"
 virsh reset vlinux1

# Hard power-off virtual machine "vlinux1"
virsh destory vlinux1

# Shutdown virtual machine "vlinux1"
 virsh shutdown vlinux1

# Remove from inventory virtual machine "vlinux1"
 virsh undefine vlinux1

# Set power-on at host start-up for virtual machine "vlinux1"
 virsh autostart vlinux1

# Display VM information for virtual machine "vlinux1"
virsh dominfo vlinux1

 

Debian Linux 8 – Installing KDE Plasma 5.x Graphical Desktop

Plasma is, in my opinion, one of the best looking graphical desktops for Linux, for more information on KDE Plasma itself see here: https://www.kde.org/workspaces/plasmadesktop/

Note that deploying plasma on Debian 8.x requires that you move from the “stable” branch to “testing” branch. What does this mean? See here: https://wiki.debian.org/DebianTesting

Be sure to fully review what will be installed / removed as part of this upgrade. Rollback will be very “challenging!”

# First upgrade to non-stable "testing" variant of Debian Linux
sudo cp /etc/apt/sources.list ~/
sudo sed -i -e 's/jessie/testing/g' /etc/apt/sources.list
sudo apt-get update
sudo apt-get upgrade
sudo reboot

# Upgrade any remaining packages
sudo apt-get update
sudo apt-get dist-upgrade
sudp reboot

# Install plasma desktop, when prompted for desktop environment selection, choose "sddm"
sudo apt-get install plasma-desktop sddm
sudo reboot

# Cleanup unused packages
sudo apt-get autoremove

I’ve tested and can confirm that, unlike Gnome, Plasma 5.x works when using x11rdp to connect remotely.

Guacamole RDP en-gb Keyboard Mapping

Disclaimer – I have copied this solution straight out of the following https://glyptodon.org/jira/browse/GUAC-1031

Like me, you may want to add the en-gb keyboard mapping to guacamole’s RDP capability so that your @ and “” key-combinations work as expected! To do this you need to perform the following, prior to running “make” during the installation of guacamole-server.

Already installed guacaole-server? You can recompile and install “over the top” of your current guacamole-server – just be sure to run “make clean” before executing “make” and “make install”.

# Crate a new en-gb Keyboard Mapping File
vi ~/incubator-guacamole-server/src/protocols/rdp/keymaps/en_gb_qwerty.keymap

parent "base"
name "en-gb-qwerty"
freerdp "KBD_UNITED_KINGDOM"
 
map -altgr -shift 0x29 0x02..0x0D ~ "`1234567890-="
map -altgr -shift 0x10..0x1B ~ "qwertyuiop[]"
map -altgr -shift 0x1E..0x28 0x2B ~ "asdfghjkl;'#"
map -altgr -shift 0x56 0x2C..0x35 ~ "\zxcvbnm,./"
 
map -altgr +shift 0x29 0x02..0x0D ~ "¬!"£$%^&*()_+"
map -altgr +shift 0x10..0x1B ~ "QWERTYUIOP{}"
map -altgr +shift 0x1E..0x28 0x2B ~ "ASDFGHJKL:@~"
map -altgr +shift 0x56 0x2C..0x35 ~ "|ZXCVBNM<>?"
 
# Keys requiring AltGr
#
map +altgr -shift 0x29 ~ "¦"


# Add to make file, so that it is included
vi ~/incubator-guacamole-server/src/protocols/rdp/Makefile.am

# Modify this section so that it looks as-below
rdp_keymaps = \
 keymaps/base.keymap \
 keymaps/failsafe.keymap \
 keymaps/de_de_qwertz.keymap \
 keymaps/en_us_qwerty.keymap \
 keymaps/fr_fr_azerty.keymap \
 keymaps/it_it_qwerty.keymap \
 keymaps/ja_jp_qwerty.keymap \
 keymaps/sv_se_qwerty.keymap \
 keymaps/en_gb_qwerty.keymap

You can now run make and make install / continue with the deployment as outlined in my other posts.

Guacamole 0.9.10-incubating; Install with MySQL on Debian 8.6

Use the script below to deploy required-prereqs and install mysql, tomcat8 and guacamole on your target Debian 8.6 client – be sure to change any references of “<password>” to suit your environment.

I have tested this on both Debian 8.6 and Ubuntu 16.04; this is intended for use on a fresh OS, with no prior versions of mysql, tomcat or guacamole. Your run this at your own risk!

# Set blank mysql root password for unattended install of mysql
debconf-set-selections <<< 'mysql-server mysql-server/root_password password'
debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password'

# Install Guacamole server pre-reqs including MySQL
apt-get install -y libjpeg-dev libcairo2-dev libossp-uuid-dev libpng12-dev libfreerdp-dev libssh2-1-dev libssh-dev libwebp-dev libpulse-dev libavcodec-dev libavutil-dev libswscale-dev libpango1.0-dev libvncserver-dev maven tomcat8 tomcat8-admin tomcat8-user default-jdk default-jre java-common mysql-server libtool dh-autoreconf git libvorbis-dev

# Secure your mysql deployment - follow the defaults, but set a secure password as it is currently blank!
mysql_secure_installation

# Prepare the database and user needed for guacamole, you'll need your root <password> for a new MySQL user named "guacamole"
mysql -u root -p<password>
 CREATE DATABASE guacamole;
 CREATE USER 'guacamole'@'localhost' IDENTIFIED BY '<password>';
 GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole.* TO 'guacamole'@'localhost';
 FLUSH PRIVILEGES;
 quit
 
# Download and install guacamole server
cd ~
git clone https://github.com/apache/incubator-guacamole-server
cd incubator-guacamole-server
autoreconf -fi
./configure --with-init-dir=/etc/init.d
make
make install
mkdir -p /etc/guacamole/extensions 
mkdir -p /etc/guacamole/lib

# Download and package guacamole client
cd ~
git clone https://github.com/apache/incubator-guacamole-client
cd incubator-guacamole-client
mvn package

# MySQL Database Preparation
cd ~/incubator-guacamole-client/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql
cat schema/*.sql | mysql -u root -p guacamole

# Copy MySQL guacamole extension to /etc/guacamole/extensions/
cp ~/incubator-guacamole-client/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/target/guacamole-auth-jdbc-mysql-0.9.10-incubating.jar /etc/guacamole/extensions/

# Download and deploy MySQL Connector-J to /etc/guacamole/lib/
cd ~
wget https://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz
tar -zxvf mysql-connector-java-5.1.40.tar.gz
cd mysql-connector-java-5.1.40
cp mysql-connector-java-5.1.40-bin.jar /etc/guacamole/lib/

# TomCat WebApp and guacamole environment deployment
cd ~/incubator-guacamole-client/guacamole/target
cp guacamole-0.9.10-incubating.war /etc/guacamole/guacamole.war 
ln -s /etc/guacamole/guacamole.war /var/lib/tomcat8/webapps/
mkdir /usr/share/tomcat8/.guacamole
touch /etc/guacamole/guacamole.properties
ln -s /etc/guacamole/guacamole.properties /usr/share/tomcat8/.guacamole/
echo GUACAMOLE_HOME=/etc/guacamole >> /etc/default/tomcat8

# Create guacamole.properties 
### Change the <password> here!
echo '# MySQL properties' > guacamole.properties
echo 'mysql-hostname: localhost' >> guacamole.properties
echo 'mysql-port: 3306' >> guacamole.properties
echo 'mysql-database: guacamole' >> guacamole.properties
echo 'mysql-username: guacamole' >> guacamole.properties
echo 'mysql-password: <password> >> guacamole.properties

# Resolve freerdp directory issues present when running guacamole on Debian 8.6
mkdir /usr/lib/x86_64-linux-gnu/freerdp
ln -s /usr/local/lib/freerdp/guac* /usr/lib/x86_64-linux-gnu/freerdp/

ldconfig
systemctl daemon-reload

systemctl start tomcat8
/etc/init.d/guacd start

systemctl enable tomcat8
systemctl enable guacd

You can now browse to guacamole using the following URL and credentials guacadmin/guacadmin – note the trailing slash on the URL, without this you will get a HTTP 404 error!
http://localhost:8080/guacamole/

Take a look at my nginx reverse proxy guide for guacamole.

Ugrading Gucamole 0.9.9 to 0.9.10-incubating

Use the process below to upgrade your guacamole deployment, backed by a mysql database from version 0.9.9 to 0.9.10-incubating. ***If you have an older version this guide is not for you.***

All commands tested on Debian 8.6, Jessie – be sure to check the following post for any related pre-reqs/ libraries:

Guacamole 0.9.10-incubating; Install with MySQL on Debian 8.6

Firstly stop all guacamole related services:

systemctl stop tomcat8
systemctl stop guacd

Upgrade the client, extensions and database:

# Compile the client
cd ~
git clone https://github.com/apache/incubator-guacamole-client
cd incubator-guacamole-client
mvn package

# MySQL Database Upgrade Process ### From 0.9.9 ONLY ###
cd ~/incubator-guacamole-client/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade
cat upgrade-pre-0.9.10.sql | mysql -u root -p guacamole

# TomCat WebApp Upgrade Process
cd ~/incubator-guacamole-client/guacamole/target
rm /var/lib/tomcat8/webapps/guacamole.war
rm -r /var/lib/tomcat8/webapps/guacamole
rm /etc/guacamole/guacamole.war
cp guacamole-0.9.10-incubating.war /etc/guacamole/guacamole.war 
ln -s /etc/guacamole/guacamole.war /var/lib/tomcat8/webapps/

# MySQL Extension Upgrade Process
rm /etc/guacamole/extensions/guacamole-auth-jdbc-mysql*
cp ~/incubator-guacamole-client/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/target/guacamole-auth-jdbc-mysql-0.9.10-incubating.jar /etc/guacamole/extensions/

Now upgrade server component:

# Server Upgrade
cd ~
git clone https://github.com/apache/incubator-guacamole-server
cd incubator-guacamole-server
autoreconf -fi
./configure --with-init-dir=/etc/init.d
make
make install

# Reload libraries and service files
ldconfig
systemctl daemon-reload

Finally, restart all services – you should now be able to resume using guacamole.

systemctl start guacd
systemctl restart tomcat8

Plex and the Privacy VPN Conundrum ; nginx to the rescue!

As an advocate in Internet Privacy I use a VPN configured on my router to obfuscate my browsing habits. My one bugbear with this solution has always been that Plex doesn’t work (well / if at all) in this scenario, and even when it does it’s slower due to the additional encryption / hops the VPN adds to the mix.

I’ve read countless “solutions” to this, for me, this is one of the easier – albeit you need to have either a VM to hand or a spare low-power x86 device and your own custom domain.

I recently started using nginx to proxy guacamole, on a dedicated, VPN-bypassed client. This got me thinking… could I proxy my remote Plex server (that was behind the VPN) via a dedicated VM running nginx? The answer, of course, was yes.

The example deployment / configuration below was completed on a Debian 8.6 Jessie install however, once you have nginx installed the configuration steps will be the same.

I’ve tested this solution with the Android Plex App, as well as the Plex Web App – no issues found to date!

First, lets install nginx and configure it to run on boot:

apt-get install -y curl

touch /etc/apt/sources.list.d/nginx.list

echo 'deb http://nginx.org/packages/debian/ jessie nginx' >> /etc/apt/sources.list.d/nginx.list

echo 'deb-src http://nginx.org/packages/debian/ jessie nginx' >> /etc/apt/sources.list.d/nginx.list

curl http://nginx.org/keys/nginx_signing.key | apt-key add -

apt-get update
apt-get install -y nginx

/etc/init.d/nginx start
systemctl enable nginx

We will harden the nginx server as we progress through the configuration. Firstly, lets block malicious agents – this is uniform across both HTTP and HTTPS configurations:

vi /etc/nginx/blockuseragents.rules

Contents of this file below:

map $http_user_agent $blockedagent {
default 0;
~*malicious 1;
~*bot 1;
~*backdoor 1;
~*crawler 1;
~*bandit 1;
}

SSL Configuration (needs an SSL certificate, try StartSSL – it’s free!)

Honestly – there is no good reason not to deploy an HTTPS-enabled reverse proxy. StartSSL certificates are free for personal use. Without this you’d be sending your Plex account username and password across the internet unencrypted.

*** Using these instructions, you do not need to add these certificates to plex itself.***

First, let’s address weak Diffie-Hellman (DH) key exchange parameters:

cd /etc/nginx/ssl
# This will take *an age* to complete
openssl dhparam -out dhparams.pem 4096

Now we’ll create the nginx .conf file for your server as below, be sure to change the relevant servername.

vi /etc/nginx/conf.d/domain.com.conf

Contents as below – be sure to review relevant SSL certificate files required in order to start nginx, these will vary by third-party CA.

include /etc/nginx/blockuseragents.rules;

# Hardening as-per https://gist.github.com/plentz/6737338
server_tokens off;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31622400; includeSubDomains; preload";

# Define upstream Plex server location - change this for your env
upstream plex-upstream {
 # change plex-server.example.com:32400 to the hostname:port of your plex server.
 # this can be "localhost:32400", for instance, if Plex is running on the same server as nginx.
 server 192.168.1.250:32400;
}

# Redirect http traffic for plex.domain.com to https - LAN only
server {
 if ($blockedagent) {
 return 403;
 }
 if ($request_method !~ ^(GET|HEAD|POST)$) {
 return 444;
 }
 listen 80;
 server_name plex.domain.com;
 return 301 https://$server_name$request_uri;
}

# Plex Reverse Proxy HTTPS server
server {
 if ($blockedagent) {
 return 403;
 }
 if ($request_method !~ ^(GET|HEAD|POST|PUT)$) {
 return 444;
 }
 listen 443 ssl;
 server_name
 tv
 plex
 plex.domain.com;

 ssl_dhparam /etc/nginx/ssl/dhparams.pem;
 ssl_certificate /etc/nginx/ssl/1_www.plex.domain.com_bundle.crt;
 ssl_certificate_key /etc/nginx/ssl/plex_ssl.key;
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_prefer_server_ciphers on;
 ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

 # Hardening as-per https://gist.github.com/plentz/6737338
 ssl_session_cache shared:SSL:50m;
 ssl_session_timeout 5m;
 resolver 8.8.8.8;
 ssl_stapling on;
 ssl_trusted_certificate /etc/nginx/ssl/1_plex.domain.com_bundle.crt;

 # As-per https://forums.plex.tv/discussion/224138/proper-reverse-proxy-for-nginx
 large_client_header_buffers 4 8k;

 # set some headers and proxy stuff.
 proxy_set_header Host $http_host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $scheme;
 proxy_redirect off;
 proxy_buffering off;

 location /:/websockets/notifications {
 # if a request to / comes in, 301 redirect to the main plex page.
 # but only if it doesn't contain the X-Plex-Device-Name header
 # this fixes a bug where you get permission issues when accessing the web dashboard
 if ($http_x_plex_device_name = '') {
 rewrite ^/$ https://$http_host/web/index.html;
 }

 # As-per https://forums.plex.tv/discussion/224138/proper-reverse-proxy-for-nginx
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
 proxy_read_timeout 86400;

 # proxy request to plex server
 proxy_pass http://plex-upstream;
 }
 location / {
 proxy_pass http://plex-upstream;
 }
}

Install, configure and enable ufw:

# Install Uncomplicated Firewall
apt-get install ufw

# Allow HTTPS from anywhere
ufw allow https
# Allow HTTP from anywhere - change LAN IP address range and server IP
ufw allow from 192.168.1.0/24 to 192.168.1.248 port 80
# Allow HTTPS
ufw allow https

For added security you can rate-limit new connections on port 443 – this *may* help reduce the chances of a brute force attack against your plex login page:

# Add just above the COMMIT line in this file /etc/ufw/before.rules
# Rate-limiting for HTTPS connections
vi /etc/ufw/before.rules
-A ufw-before-input -p tcp --dport 443 -i eth0 -m state --state NEW -m recent --set
-A ufw-before-input -p tcp --dport 443 -i eth0 -m state --state NEW -m recent --update --seconds 2 --hitcount 20 -j DROP

You’ll then need to do one of two things:

  1. Install a dynamic dns client on your linux box and configure an appropriate A record
  2. Use dynamicdns on your router and configure an appropriate A record

When done, create a CNAME entry in your personal domain name that points to the dynamic DNS A record. I.e. if you used the config file above, and had a dynamic DNS A record of “myrouter.dyndns.com” and your personal domain is “domain.com” then your CNAME would be:

plex.domain.com pointing to myrouter.dyndns.com

Test your SSL config using the following free service: https://www.ssllabs.com/ssltest/

Finally, within Plex, under Settings | Server | Network (Show Advanced) ensure you populate the “Custom server access URLs” with (using URL from example config above – change as-per your environment/ needs):

https://plex.domain.com

Debian 8.6, Proxy guacamole via NGINX using HTTPS and Fail2Ban

Slight variation on the proxying guacamole via Apache2 post (much content is the same) but this is post will guide you through proxying guacamole via nginx, fail2ban and ufw config for guacamole.

In my previous article I explained how to install guacamole on Debian 8.6.

First, install nginx using official nginx reporsitory (will enable you to use a more recent, thus more secure version):

apt-get install curl

touch /etc/apt/sources.list.d/nginx.list

echo 'deb http://nginx.org/packages/debian/ jessie nginx' >> /etc/apt/sources.list.d/nginx.list

echo 'deb-src http://nginx.org/packages/debian/ jessie nginx' >> /etc/apt/sources.list.d/nginx.list

curl http://nginx.org/keys/nginx_signing.key | apt-key add -

apt-get update
apt-get install -y nginx

mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
# This will take *an age* to complete 
openssl dhparam -out dhparams.pem 4096

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 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)

Now, copy these files to /etc/apache2/ssl.

You may need to combine the root_bundle and your specific FWDN certificate – an example command to do this is below:

cat 2_guacamole.domain.com.crt 1_root_bundle.crt >> /etc/nginx/ssl/guac-bundle.crt

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 ngnix loads:

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

Now, protect those files!

chmod 600 /etc/nginx/ssl/*

Now, we’ll configure the site definition in nginx – change the file name to match your environment:

vi /etc/nginx/conf.d/guacamole.domain.com.conf

Contents as below – make sure you change the text in bold to match your setup:

server {
 listen 80;
 server_name guacamole.domain.com;
 return 301 https://$server_name$request_uri;
}

# Guacamole Reverse Proxy HTTPS Server
server {
 if ($blockedagent) {
 return 403;
 }
 if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE)$) {
 return 444;
 }
 listen 443 ssl;
 server_name guacamole.domain.com;
 rewrite_log on;
 ssl_dhparam /etc/nginx/ssl/dhparams.pem;
 ssl_certificate /etc/nginx/ssl/1_guacamole.domain.com_bundle.crt;
 ssl_certificate_key /etc/nginx/ssl/guacamole.key;
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_prefer_server_ciphers on;
 ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";

 # Hardening as-per https://gist.github.com/plentz/6737338
 ssl_session_cache shared:SSL:50m;
 ssl_session_timeout 5m;
 resolver 8.8.8.8;
 ssl_stapling on;
 ssl_trusted_certificate /etc/nginx/ssl/1_guacamole.domain.com_bundle.crt;

 location / {
 proxy_pass http://127.0.0.1:8080/guacamole/;
 proxy_redirect off;
 proxy_buffering off;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection $http_connection;
 proxy_cookie_path /guacamole/ /;
 access_log off;
 }
}

Now, start nginx:

/etc/init.d/nginx start

Next, configure Apache2 to load on boot:

systemctl enable nginx

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,8080
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

/etc/init.d/fail2ban restart
systemctl enable fail2ban

Home straight now… ufw config. The commands below are specifically designed for the solution outlined in this post where the LAN is 192.168.1.0/24 and the guacamole server is 192.168.1.249 – 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

Debian 8.6, guacamole; install and configure mysql back-end

In previous posts I have covered a basic installation of guacamole, using a user-mapping.xml file to define users and connections, I have also covered how to publish guacamole using apache2 over HTTPS whist protecting your deployment with fail2ban and ufw.

In this post I outline the steps required to move your guacamole installation to a mysql back-end.

First, lets install and configure mysql – you’ll need a root password and a password for the “guacamole” mysql user:

# Install mysql server
apt-get install mysql-server

# you'll be prompted for a root user account password
<password>
    
# review /etc/mysql/my.cnf for bindings, by default mysql will listen on 127.0.0.1 only.
vi /etc/mysql/my.cnf

# secure your mysql deployment
mysql_secure_installation

# prepare the database and user needed for guacamole
mysql -u root -p
    CREATE DATABASE guacamole;
    CREATE USER 'guacamole'@'localhost' IDENTIFIED BY '<password>';
    GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole.* TO 'guacamole'@'localhost';
    FLUSH PRIVILEGES;
    quit

Download and deploy the mysql extension for guacamole (this must match the version of guacamole-client you are using):

cd ~
wget http://netix.dl.sourceforge.net/project/guacamole/current/extensions/guacamole-auth-jdbc-0.9.9.tar.gz
tar -zxvf guacamole-auth-jdbc-0.9.9.tar.gz
cd ~/guacamole-auth-jdbc-0.9.9/mysql
cp *.jar /etc/guacamole/extensions/
cd..

Now prepare the guacmole database using the supplied scripts:

cd ~/guacamole-auth-jdbc-0.9.9/mysql
cat schema/*.sql | mysql -u root -p guacamole

Next, download and deploy the mysql java connection library:

cd ~
wget https://cdn.mysql.com//Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz
tar -zxvf mysql-connector-java-5.1.40.tar.gz
cd mysql-connector-java-5.1.40
cp mysql-connector-java-5.1.40-bin.jar /etc/guacamole/lib/

Finally, you can clear the contents of your guacamole.properties file and add only the lines below, be sure to change the mysql user password accordingly – note you will need to recreate you user mappings via the guacamole admin console.

vi /etc/guacamole/guacamole.properties

# MySQL properties
mysql-hostname: localhost
mysql-port: 3306
mysql-database: guacamole
mysql-username: guacamole
mysql-password: <password>

Now restart tomcat8 (using “systemctl restart tomcat8” and browse to your guacamole deployment – you should be able to login using the credentials guacamole / guacamole.

As an aside, I did run into an issue where, having built the guacamole-client via git clone, I was unable to login using guacamole / guacamole credentials.

I was able to find an error in catalina.out:

cat /var/log/tomcat8/catalina.out | grep guacamole-auth-jdbc-mysql-0.9.9.jar

ERROR o.a.g.extension.ExtensionModule – Extension “guacamole-auth-jdbc-mysql-0.9.9.jar” could not be loaded: Authentication provider class cannot be loaded (wrong version of API?)

My solution was to stop tomcat8, remove the guacamole.war file, guacamole tomcat8 directory and then re-dploy the guacamole client, using the commands below:

# stop tomcat8
systemctl stop tomcat8

# remove guacamole files/ directoryrm /var/lib/tomcat8/webapps/guacamole.war
rm -r /var/lib/tomcat8/webapps/guacamole/

# download the pre-built guacamole-client
wget -O guacamole.war http://downloads.sourceforge.net/project/guacamole/current/binary/guacamole-0.9.9.war

# deploy and create symlink under tomcat8
cp /guacamole/target/guacamole.war /etc/guacamole/
ln -s /etc/guacamole/guacamole.war /var/lib/tomcat8/webapps/

# start tomcat8
systemctl start tomcat8