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 / Ubuntu 16.x

I’d now recommend using this updated guide to deploy guacamole using Docker images. This is *much* easier, and by default you’ll get the latest version.

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|PATCH)$) {
 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
apt-get install python-minimal
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

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

 

 

Debian 8.6, Jessie, Installing Guacamole

Apache Guacamole is a clientless remote desktop gateway. It supports standard protocols like VNC, RDP, and SSH.

Client-less… yes! Guacamole uses HTML5 to do its stuff, so no client needed. I’ve used this to serve-out my X11rdp-enabled Debian 8.6 client (running guacamole itself) – but you could use this to front a variety of different clients.

This guide covers the steps needed to deploy v0.9.10 on Debian 8.6, Jessie; running 0.9.9? Check out this guide on how to upgrade to 0.9.10.

Lastly, if you want to use MySQL for the back-end – rather than XML files – see this guide: http://www.cb-net.co.uk/linux/guacamole-0-9-10-automated-install-with-mysql-on-debian-8-6/

# 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 openjdk-7-jre openjdk-7-jdk java-common
# 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 /etc/guacamole/extensions 
mkdir /etc/guacamole/lib

# 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/

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

# 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
echo GUACAMOLE_HOME=/etc/guacamole >> /etc/default/tomcat8

# Create /etc/guacamole/guacamole.properties
touch /etc/guacamole/guacamole.properties 
ln -s /etc/guacamole/guacamole.properties /usr/share/tomcat8/.guacamole/

Create /etc/guacamole/guacamole.properties using the command:

vi /etc/guacamole/guacamole.properties

Now edit the file and enter the following lines – for more information on this file click here.

guacd-hostname: localhost
guacd-port:    4822
user-mapping:    /etc/guacamole/user-mapping.xml
auth-provider:    net.sourceforge.guacamole.net.basic.BasicFileAuthenticationProvider

 

Create /etc/guacamole/user-mapping.xml using the command:

touch /etc/guacamole/user-mapping.xml

Edit these lines prior to adding them to user-mapping.xml – you will want to change username, password (used to login to guacamole), protocol, target host etc. For more information on options / protocols / usernames / passwords etc see here.

This example is for a Windows 10 client with NLA enabled (the default configuration). You have to use two username/passwords in this example:

  1. The logon credentials for guacamole itself via http://<hostname>/guacamole/ – denoted username1/password1
  2. The pre-authentication (NLA) credentials for the target RDP client (windows credentials) – denoted username2/password2
<user-mapping>
  <authorize username="username1" password="password1">
   <connection name="WIN-10-RDP">
	<protocol>rdp</protocol>
	<param name="hostname">192.168.1.5</param> 
	<param name="username">username2</param>
	<param name="password">password2</param> 
	<param name="security">nla</param>
        <param name="ignore-cert">true</param>
   </connection>
  </authorize>
</user-mapping>

Alternatively, disable the NLA requirement on your Windows 10 client and set security to “tls” – you can then remove the connection specific username/password. When you connect via RDP you’ll then be prompted for credentials.

Another example, a Debian 8.6 x11rdp client – note the credentials here are those used to login to guacamole itself via http://<hostname>/guacamole/ – denoted username1/password1

<user-mapping>
	<authorize username="username1" password="password1">
		<connection name="DEBIAN-RDP">
			<protocol>rdp</protocol>
			<param name="hostname">localhost</param>
			<param name="port">3389</param>
		</connection>
	</authorize>
</user-mapping>

Once last example, an SSH client (see note about username/password above):

<user-mapping>
	<authorize username="username1" password="password1">
		<connection name="DEBIAN-SSH">
			<protocol>ssh</protocol>
			<param name="hostname">localhost</param>
		</connection>
	</authorize>
</user-mapping>

 

If you forget the freerdp fix above, you will get errors such as those below relating to missing freerdp plugins:

LoadLibraryA: /usr/lib/x86_64-linux-gnu/freerdp/guacdr-client.so: cannot open shared object file: No such file or directory
guacd[7143]: WARNING:    Failed to load guacdr plugin. Drive redirection and printing will not work. Sound MAY not work.
LoadLibraryA: /usr/lib/x86_64-linux-gnu/freerdp/guacsnd-client.so: cannot open shared object file: No such file or directory
guacd[7143]: WARNING:    Failed to load guacsnd alongside guacdr plugin. Sound will not work. Drive redirection and printing MAY not work.

 

Start tomcat8 and guacamole-server:

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

Enable tomcat8 and guacd on startup:

systemctl enable tomcat8
systemctl enable guacd

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

Not working? Stop guacd using the command:

systemctl stop guacd

Now, from the a terminal, start guacd with debug output enabled:

/usr/local/sbin/guacd -f -L debug

You can now try and connect to guacamole / a client and view debug information such as security / hostname / authentication failures.

Be sure to checkout my posts on how to proxy and secure guacamole either:

Also worth reviewing my post on using a mysql back-end as opposed to the user-mapping.xml file. This makes management and configuration of guacamole a lot easier, IMO.

Getting x11rdp working on Debian 8, Jessie, with the help of X11RDP-o-Matic

Note: there is currently a bug that stops X11RDP installation on Debian 8.7: https://github.com/scarygliders/X11RDP-o-Matic/issues/81

I recently posted about using RDP to connect to Debian 8 clients via xrdp and, things were going well until I tried to redirect session sound and then started looking into the default xrdp configuration; it turns out that the default xrdp package leveraged vnc… yes, vnc. Surely there has to be a more effective way…?

This got my looking at x11rdp, which can provide native RDP connectivity with the following benefits:

  • Redirected sound
  • Redirected clipboard (copy paste between remote host and client)
  • Better visuals / performance (YMMV)
  • (to follow) use of Remote-FX for improved video playback etc.

I came across Kevin Cave’s X11RDP-o-Matic, however this did not support Debian 8, but it gave me 90% of what I needed.

After a while of trying to figure out what was causing the script to fail on Debian 8, I submitted a pull request to modify the “required packages” associated with the “–withjpeg” compile flag. Until this is committed, in some form, I have created a modified copy of the main script here.

All of the below is performed and tested on a vanilla Debian 8.6 machine , via a remote SSH console – your mileage may vary should your configuration not match.

Pre-flight checks / pre-requisites

You’ll need to ensure you’re running KDE or XFCE. This will not work with GNOME.

I’ve used sudo throughout this post, so install and add your non root user to the group (alternatively get all of my code snips and remove sudo!) – git is also used from the offset, so I have included this here.

apt-get install -y sudo git
adduser <user account> sudo

Log off and login again via SSH to refresh your groups, allowing sudo to work.

Now update your Debian install prior to continuing to build and install x11rdp.

apt-get update
apt-get dist-upgrade -y

Download and Execute X11RDP-o-Matic

# Download X11RDP-o-Matic 
git clone https://github.com/scarygliders/X11RDP-o-Matic
cd X11RDP-o-Matic

# Download modified X11rdp-o-matic.sh and chmod +x
wget https://www.dropbox.com/s/obrg90m4djhb2ct/DEV-X11rdp-o-matic.sh
chmod +x DEV-X11rdp-o-matic.sh

# Build and install x11rdp and xrdp packages - this will take a while!
sudo ./DEV-X11rdp-o-matic.sh --interactive --withjpeg --withsimplesound --withpulse --withkerberos --withpamuserpass --withfreerdp

Fix anomalous “.service” files 

Comment out “EnvironmentFile” line and changing the PIDFile location for:

  • /lib/systemd/system/xrdp.service
  • /lib/systemd/system/xrdp-sesman.service
sudo sed -i 's/EnvironmentFile/#EnvironmentFile/g' /lib/systemd/system/xrdp-sesman.service

sudo sed -i 's/PIDFile=\/var\/run\/xrdp.pid/PIDFile=\/run\/xrdp.pid/g' /lib/systemd/system/xrdp-sesman.service

sudo sed -i 's/EnvironmentFile/#EnvironmentFile/g' /lib/systemd/system/xrdp.service

sudo sed -i 's/PIDFile=\/var\/run\/xrdp-sesman.pid/PIDFile=\/run\/xrdp-sesman.pid/g' /lib/systemd/system/xrdp.service

Now, reload service definitions and enable / start services.

sudo systemctl daemon-reload
sudo systemctl enable xrdp-sesman
sudo systemctl enable xrdp
sudo systemctl start xrdp-sesman
sudo systemctl start xrdp

Generate xrdp rsakeys.ini

Now, generate xrdp rsakeys.ini, without this you’ll be unable to connect and get errors in event /var/log/xrdp-sesman.log  as below:

  • [ERROR] Listening socket is in wrong state we terminate listener
  • XRDP cannot read file: /etc/xrdp/rsakeys.ini (check permissions)
sudo xrdp-keygen xrdp auto 2048 

Build Debian 8 pulseaudio xrdp sink modules

You should download the version of pulseaudio nearest to that in your disto – check using:

pulseaudio --version

Now, download the pulseaudio source and configure – note you do not have to make / make install pulseaudio.

Be sure to change the version number (5.0, in bold, below) to match that from the command above.

sudo apt-get install -y libjson0-dev libsndfile1-dev libspeex-dev libspeexdsp-dev libcap-dev

cd /tmp
wget https://freedesktop.org/software/pulseaudio/releases/pulseaudio-5.0.tar.gz
tar -zxvf pulseaudio-5.0.tar.gz
cd /tmp/pulseaudio-5.0
./configure

Now, build the modules and copy them to /usr/lib/pulse-5.0/modules and, finally for the xrdp sink modules, call them to /etc/pulse/default.pa.

Again, watch the version numbers / paths as you may need to change these for your build.

cd ~/X11RDP-o-Matic/work/xrdp/sesman/chansrv/pulse/

# Change the patch here to match your path
sudo sed -i 's/PULSE_DIR = \/home\/lk\/pulseaudio-1.1/PULSE_DIR = \/tmp\/pulseaudio-5.0/g' Makefile

sudo make
sudo cp *.so /usr/lib/pulse-5.0/modules/

cd ~
sudo cp /etc/pulse/default.pa ~
sudo sed -i -e '$amodule-xrdp-sink.so' /etc/pulse/default.pa
sudo sed -i -e '$amodule-xrdp-source.so' /etc/pulse/default.pa

Build .xsession Files

We now need to call the RDPsesconfig.sh script contained within the X11RDP-o-Matic package. This will build the .xsession file for all users.

I’d stress that feedback (from comments below) and my own experience shows that Gnome will not work via x11rdp, or xrdp for that matter. KDE and XFCE both work.

cd ~/X11RDP-o-Matic/
sudo ./RDPsesconfig.sh

Optional Steps

Fix en-GB keyboard layout:

wget https://www.dropbox.com/s/rtxp19ts17k8qy8/km-0809.ini
cp km-0809.ini /etc/xrdp/

sed -i '/\[default_rdp_layouts\]/a rdp_layout_gb=0x00000809' /etc/xrdp/xrdp_keyboard.ini

sed -i '/\[default_layouts_map\]/a rdp_layout_gb=gb' /etc/xrdp/xrdp_keyboard.ini

Set background colour of logon prompt to be black, not very light/ luminescent blue:

sed -i 's/ls_top_window_bg_color=009cb5/ls_top_window_bg_color=000000/g' /etc/xrdp/xrdp.ini

You can also remove unnecessary session options from xrdp-sesman as outlined below.

sudo vi /etc/xrdp/xrdp.ini
# manually remove lines associated with [xrdp2] to just before ["Session manager"] ; be sure to leave any lines including/onwards from  ["Session manager"]

Finally

Reboot your system, you should be able connect to your target system via RDP, with clipboard, audio and improved performance.

References