Introduction
The goal of this tutorial is to get rid of the public SSH and public RDP connections. By placing this all behind a very convenient HTML5 client, we can add a layer of security for accessing our cloud.
Guacamole also logs any remote access, so unauthorized access becomes much more traceable.
Note: For Let’s encrypt (option B) we need a domain name. If you don’t have one, you can skip this step and just execute option A.
Step 1 – Preparing the system
Start by spinning up a VPS in your desired Vultr zone. A 1024 MB
VPS will be enough, as Guacamole is not that demanding.
Enabling the private IP
Start by enabling the private network on the VPS. This is well-documented here
Preparing the firewall
First let’s harden the image a little bit. And let’s check if the image that has been provisioned has ufw
enabled.
root@vultr:~# ufw status
Status: inactive
By default it’s disabled, so we will need to add a few rules.
- Rule 1: ssh: TCP port 22
- Rule 2: http: TCP port 8080 (temporary testing rule for Guacamole)
Let’s start with configuring these ports.
ufw allow 22/tcp
ufw allow 8080/tcp
Next enable the firewall.
ufw enable
Don’t worry if you receive a warning. If you added port 22
, you will not face any issues.
root@vultr:~# ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
Once enabled, request the status of the firewall and we will see our port configuration.
ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
8080/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
8080/tcp (v6) ALLOW Anywhere (v6)
Step 2 – Installing Guacamole
Installing all dependencies
Before we start installing we need to update and upgrade the repo. With packages such as Tomcat
, which is Java based, there is a constant stream of discovered bugs and their associated bugfixes. It is usually a good idea to do this first instead of rushing directly into our installation.
apt-get update
apt-get -y upgrade
Next up is all the dependencies. Guacamole has quite a few of them. (A full list of dependencies and their function can be found here). Let’s continue by installing all of them.
apt-get -y install build-essential tomcat8 freerdp libcairo2-dev libjpeg-turbo8-dev libpng12-dev libossp-uuid-dev libavcodec-dev libavutil-dev libfreerdp-dev libpango1.0-dev libssh2-1-dev libtelnet-dev libvorbis-dev libwebp-dev mysql-server mysql-client mysql-common mysql-utilities libswscale-dev libvncserver-dev libpulse-dev libssl-dev
When the installer asks for a MySQL root password, provide one and be sure to take note of it. We will be using this password later on to create the Guacamole database.
Downloading Guacamole
Now that we have all of our dependencies, we can continue with downloading Guacamole. Guacamole itself comes mostly in a source form, and not a binary.
First we will move to the /tmp
folder to avoid cluttering other parts of the disk. Then download all of the source code.
There are four source/binary files to download:
guacamole-0.9.13-incubating.war
: This is the web application. AWAR
file is a zipped web package providing a single website hosted on a Tomcat websiteguacamole-server-0.9.13-incubating.tar.gz
: This file will provide the backendguacd
application. This creates the streams through RDP and SSH.guacamole-auth-jdbc-0.9.13-incubating.tar.gz
: We will be using a local MySQL database, so we need the associatedJDBC
connector.mysql-connector-java-5.1.43.tar.gz
: Without a database driver the JDBC connector does nothing. This file is provided by the MySQL team themselves.
Note: downloads resolved to the closest server.
cd /tmp
wget http://apache.belnet.be/incubator/guacamole/0.9.13-incubating/binary/guacamole-0.9.13-incubating.war
wget http://apache.cu.be/incubator/guacamole/0.9.13-incubating/source/guacamole-server-0.9.13-incubating.tar.gz
wget http://apache.cu.be/incubator/guacamole/0.9.13-incubating/binary/guacamole-auth-jdbc-0.9.13-incubating.tar.gz
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.43.tar.gz
Once we have downloaded all these files, extract the tar.gz
‘s.
tar -xzvf guacamole-server-0.9.13-incubating.tar.gz
tar -xzvf guacamole-auth-jdbc-0.9.13-incubating.tar.gz
tar -xzvf mysql-connector-java-5.1.43.tar.gz
Compiling Guacamole
Now that we have extracted all of the source code, let’s make a few guacamole
folders, these will be used by the guacamole application and its dependencies.
mkdir -p /etc/guacamole/lib
mkdir -p /etc/guacamole/extensions
Everything is ready for our new Guacamole binaries. We can now start the compilation and installation process. Move over to the extracted Guacamole Server folder.
cd /tmp/guacamole-server-0.9.13-incubating
Configure the application to also create an init.d
file for running it as a service later on.
./configure --with-init-dir=/etc/init.d
The command should end with a ‘yes’ on all libraries and protocols. If not, go back and check the apt-get command to make sure you didn’t miss any package.
------------------------------------------------
guacamole-server version 0.9.13-incubating
------------------------------------------------
Library status:
freerdp ............. yes
pango ............... yes
libavcodec .......... yes
libavutil ........... yes
libssh2 ............. yes
libssl .............. yes
libswscale .......... yes
libtelnet ........... yes
libVNCServer ........ yes
libvorbis ........... yes
libpulse ............ yes
libwebp ............. yes
Protocol support:
RDP ....... yes
SSH ....... yes
Telnet .... yes
VNC ....... yes
Services / tools:
guacd ...... yes
guacenc .... yes
Init scripts: /etc/init.d
Type "make" to compile guacamole-server.
Next up compile and install the Gucamole server.
make && make install
Once this all is done, run ldconfig
to rebuild the search path for libraries that have been added.
ldconfig
Proceed by using systemctl
to setup guacd
(Guacamole Daemon) to start on boot.
systemctl enable guacd
Guacamole binaries are now installed. Now we will get the web application ready for Tomcat.
Start by moving the war
file to the guacamole
folder we just created, once this is done create a logical link in the tomcat directory to point to our war
file.
cd /tmp
mv guacamole-0.9.13-incubating.war /etc/guacamole/guacamole.war
ln -s /etc/guacamole/guacamole.war /var/lib/tomcat8/webapps/
Then we need the mysql connector and JDBC. The JDBC driver is needed in the extensions
folder, the connector in the lib
folder.
cp mysql-connector-java-5.1.43/mysql-connector-java-5.1.43-bin.jar /etc/guacamole/lib/
cp guacamole-auth-jdbc-0.9.13-incubating/mysql/guacamole-auth-jdbc-mysql-0.9.13-incubating.jar /etc/guacamole/extensions/
Configuring Guacamole and Tomcat
Once the connector and JDBC are in place, we need to edit the tocamt8
file. This file contains a lot of tomcat8
settings, and in our case we need to add the GUACAMOLE_HOME
variable at the end of the file.
nano /etc/default/tomcat8
Append with the following.
GUACAMOLE_HOME=/etc/guacamole
Creating the database
Next up is creating the database. Guacamole stores its connection configuration in a database, not inside a file.
Login with the root password
you used during the installation.
mysql -u root -p
The first step is to create a database called ‘guacamole_db’.
create database guacamole_db;
Then run the create user
command. This will create a user with a password mysupersecretpassword
, this user will only be able to connect from localhost
.
create user 'guacamole_user'@'localhost' identified by "mysupersecretpassword";
Grant CRUD
operations to this user for the database guacamole_db
.
GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO 'guacamole_user'@'localhost';
Flush privileges and exit the shell.
flush privileges;
exit
Finish up by adding the Guacamole schema to our newly created database.
cat /tmp/guacamole-auth-jdbc-0.9.13-incubating/mysql/schema/*.sql | mysql -u root -p guacamole_db
Once this is done, we need to edit the guacamole.properties
file. This file contains our recently created MySQL server configuration.
nano /etc/guacamole/guacamole.properties
Append the MySQL connection details and credentials.
mysql-hostname: localhost
mysql-port: 3306
mysql-database: guacamole_db
mysql-username: guacamole_user
mysql-password: mysupersecretpassword
Finish up by creating a symbolic link to the tomcat share folder, as this is where the WAR
file will search these properties.
ln -s /etc/guacamole /usr/share/tomcat8/.guacamole
Testing the setup
End by restarting the tomcat8
server and start the guacd
server daemon.
service tomcat8 restart
service guacd start
You can verify by using the status command.
service tomcat8 status
service guacd status
Now you can browse to your VPS on port 8080
http://<yourpublicip>:8080/guacamole/
Use the username guacadmin
and the same password guacadmin
. This will grant you access to an empty Guacamole server.
Click in the top right corner on your username guacadmin
and select Settings
. Once you are in the settings page go to the Users
tab and select the user guacadmin
.
Now change your password to something else or create a new admin user and delete the default guacadmin
one.
Step 3 – Fine tuning and cleanup
These are the final steps: cleaning up after you are done.
Delete the downloaded source code and binaries from the /tmp
folder.
rm -rf /tmp/guacamole-*
rm -rf /tmp/mysql-connector-java-*
Also, make the Guacamole web application the default one. In the tomcat ecosystem the application that gets the ROOT
folder is the one that is started by default when you access the website.
Delete the old ROOT
placeholder.
rm -rf /var/lib/tomcat8/webapps/ROOT
And make a symbolic link for the guacamole server to be the ROOT
one.
ln -s /var/lib/tomcat8/webapps/guacamole /var/lib/tomcat8/webapps/ROOT
This requires a tomcat restart.
service tomcat8 restart
Step 4 (option A) – Running on HTTP only
- If you are not going to use Let’s Encrypt certificates and not use a DNS, execute the actions in this step and afterwards go directly to Step 6. – Option A
- If you want to create a more secure site and you have a DNS ready, you can skip this and go straight to option B (Step 5).
Edit the tomcat8/server.xml
file and change the connector port.
nano /etc/tomcat8/server.xml
Search for the Connector port
.
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
URIEncoding="UTF-8"
redirectPort="8443" />
And replace 8080
with 80
.
By default, tomcat doesn’t allow the binding of ports below 1024
. To enable this we need to tell tomcat8 to create authenticated binds.
Edit the default
file of tomcat8 and uncomment the AUTHBIND
line and use the option yes
nano /etc/default/tomcat8
AUTHBIND=yes
Once this is done, intall authbind
.
apt-get install authbind
Configure it so that port 80
can be claimed by tomcat8.
touch /etc/authbind/byport/80
chmod 500 /etc/authbind/byport/80
chown tomcat8 /etc/authbind/byport/80
Allow port 80
through the firewall and delete the rule for 8080
.
ufw allow 80/tcp
ufw delete allow 8080/tcp
Restart tomcat.
service tomcat8 restart
That’s it, now Guacamole should be running on port 80
.
Step 5 (option B) – Setting up Nginx
Installation and configuration of Nginx
Tomcat really isn’t one of the best and most robust applications to use with certbot
. Luckily Nginx is. We will just to proxy tomcat to Nginx. It uses the out-of-the-box functionality of certbot at the cost of sacrificing a little bit of RAM.
apt-get install nginx
Once installed, edit the default configuration.
nano /etc/nginx/sites-available/default
Delete all example configurations and add the following configuration.
server {
listen 0.0.0.0:80;
proxy_request_buffering off;
proxy_buffering off;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $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-Host $server_name;
}
}
This will create a proxy for the website running at 8080
. Restart Nginx, and enable it at boot.
systemctl restart nginx
systemctl enable nginx
Check if everything is working.
systemctl status nginx
Disable the testing port 8080
and allow traffic on port 80
.
ufw allow 80/tcp
ufw delete allow 8080/tcp
Installing Let’s Encrypt
Before we can use certbot
, we need to add the correct ppa
to the system containing our certbot packages.
add-apt-repository ppa:certbot/certbot
Press “ENTER
” to accept the configuration change.
Update apt
to gather the new packages.
apt-get update
Finally, install the Nginx module for assigning the certificates.
apt-get -y install python-certbot-nginx
Configure Nginx to use certificates
Configure the firewall to allow HTTPS
.
ufw allow 443/tcp
Before we can request new certificates, we need a DNS name.
nano /etc/nginx/sites-available/default
Add the following server_name
setting.
server_name rdp.example.com;
Change the configuration to reflect this new setting.
server {
server_name rdp.example.com;
listen 0.0.0.0:80;
proxy_request_buffering off;
proxy_buffering off;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $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-Host $server_name;
}
}
Check if all is working and restart Nginx.
nginx -t
service nginx restart
Now request a certificate with certbot.
certbot --nginx -d rdp.example.com
Provide your email and agree to the questions asked by the installer. (You can safely choose “No
” to sharing your email.)
Certbot will automatically ask what it needs to do with HTTPS
. We will be using option 2: redirect to HTTPS
.
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
The last thing we will be doing is updating the DH
parameters. These are, by default, a little bit weak for 2017 standards.
Create some new ones.
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
Next, add them to the default site in Nginx.
nano /etc/nginx/sites-available/default
Add them to the server configuration.
server {
server_name rdp.example.com;
listen 0.0.0.0:80;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
proxy_request_buffering off;
proxy_buffering off;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_redirect off;
proxy_set_header Host $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-Host $server_name;
}
}
Check for errors.
nginx -t
Apply the changes by restarting the server.
service nginx restart
Cleanup the old 8080
rule
ufw delete allow 8080/tcp
Note: if you should recieve a “502 Bad Gateway” you will need restart tomcat8.
service tomcat8 restart
Auto renew certificates
Let’s Encrypt certificates require renewal. We can create a cron job for this. Start by editing the crontab
.
crontab -e
Add the following line.
00 2 * * * /usr/bin/certbot renew --quiet
This will check at 2:00 AM if any certificates require a renewal and will renew them if they do.
Step 6 – Testing it all out
Go to your Guacamole server (either http://<ip>/
or https://rdp.example.com)
).
For this test, you will need two more instances: one Linux VM and another Windows Server 2012 R2 with a private IP enabled on both.
Adding the Windows RDP connection
Click the “username
” on the top right corner and go to “Settings
“. Then go to “Connections
” and select “New Connection
“.
Fill in following settings (you can leave the others default).
Name: Windows Server 2012 R2
Location: ROOT
Protocol: RDP
Maximum number of connections: 1
Maximum number of connections per user: 1
Parameters > Hostname: 10.99.0.12
Parameters > Port: 3389
Username: Administrator
Password: <password> (provided by Vultr)
Security mode: Any
Ignore server certificate: <checked>
Press “save
” and go back to the home screen.
Now you can click on the “Windows Server 2012 R2
” connection and it will RDP to this machine.
Adding the Linux SSH connection
Press “Ctrl+Shift+Alt
“. This will pop out the menu on the side. Here you can disconnect or perform other administrative tasks for Guacamole.
Click the username
on the top in the menu and go to “Settings
“. Then go to the “Connections
” tab and select “New Connection
“.
Fill in following settings (you can leave the others default).
Name: Linux
Location: ROOT
Protocol: SSH
Maximum number of connections: 5
Maximum number of connections per user: 2
Parameters > Hostname: 10.99.0.11
Parameters > Port: 22
Username: root
Password: <password> (provided by Vultr)
Press “save
” and go back to the home screen. Now you can click this newly created connection and be connected to your Linux server via SSH.
Conclusion
You now have a web RDP/SSH HTML5 gateway. Now you can firewall the public RDP and SSH access of your platform and access your environment from any modern browser.
For more information on what Guacamole can offer, there is a great video showing all of the possiblities of the platform here.
Want to contribute?
You could earn up to $300 by adding new articles
Suggest an update
Request an article