Ubuntu Linux and OpenVPN Client, using UFW to force traffic via VPN tunnel interface

First, you’ll need to obtain your “.ovpn” configuration file from your VPN provider. Find and replace <config file> with the name of the file excluding the file extension.

There are two stages to this guide:

  1. VPN Client Connection/ Configuration
  2. UFW Firewall Configuration (to ensure traffic can only use VPN and prevent DNS Leak)

If you are using docker containers be sure to check the considerations at the end of this article.

VPN Client Connection/ Configuration

Prepare the configuration file:

# Disable IPv6
echo "#disable ipv6" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# Move config file to /etc/openvpn
mv <config file>.ovpn /etc/openvpn/<config file>.conf

# Create .secrets file
echo '<username>' >> /etc/openvpn/.secrets
echo '<password>' >> /etc/openvpn/.secrets
chmod 600 /etc/openvpn/.secrets

# Modify config file
vi <config file>.conf

# Ensure you have no other auth-user-pass lines defined
auth-user-pass .secrets

# Add redirect-gateway to force traffic down TUN interface

# Add DNS server update script execution to config file
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

# Save/close config file

We’ll now configure OpenVPN client to automatically connect to this VPN interface on startup:

# Edit /etc/default/openvpn, un-comment AUTOSTART="all" then save/close 
vi /etc/default/openvpn

# Start / enable openvpn service at boot
sudo systemctl start openvpn
sudo systemctl enable openvpn

Confirm the VPN tunnel is up and public IP is that of the VPN provider:

# Look for a tun0 interface, if found you are connected!

# Check public IP is "hidden"/ different vs. machine not on the VPN
curl ipinfo.io/ip

UFW Firewall Configuration

We’ll configure UFW to allow only allow outbound traffic to the VPN provider (“tun0” in this example) interface.

First we must enable forwarding:

vi /etc/default/ufw

Next we’ll configure the necessary UFW rules to facilitate the outbound traffic to the VPN provider, but block everything else. You’ll need to change:

  • <VPN Server IP> to IPv4 address as-per the “remote xx.xx.xx.xx” line in your OpenVPN configuration file.
  • <port> to the remote OpenVPN port  (usually 1194 or 443)
  • <LAN subnet> to network/subnet that represents your network – i.e.
# Defaults
ufw default deny incoming
ufw default deny outgoing

# Allow SSH from local LAN
ufw allow from <LAN subnet> to any port 22

# UFW rule to ensure we only hit the VPN
ufw allow out to <VPN server IP> port <port>
ufw allow out to <LAN subnet>
ufw allow out on tun0

# Enable the firewall
ufw enable

If DNS lookups on the client fail you’ve missed the configuration lines from your OpenVPN configuration file, as above, you want to force DNS lookups over the VPN otherwise you’re leaking DNS requests, reducing the privacy value of your VPN.

# Add DNS server update script execution to config file 
script-security 2 
up /etc/openvpn/update-resolv-conf 
down /etc/openvpn/update-resolv-conf

Considerations when using Docker Containers

If you want your docker containers to sit behind the VPN, ensure you use the–net=host” argument. As per: https://docs.docker.com/engine/userguide/networking/default_network/container-communication/

Docker’s forward rules permit all external source IPs by default.

By default containers will use the docker0 interface and thus when your VPN goes down, they will still have external/ internet access. This statement only applies when using the default docker0 interface, not when binding the container to the “host” interface.

My experience shows that the default docker forward rule associated with the docker0 interface  overrides any UFW rule (i.e. as defined above).

You can test container connectivity using the commands below:

# Test there is NO connectivity from container when VPN is down
systemctl stop openvpn
docker exec -it <container_name> /bin/bash

# Test this IS connectivity from container when VPN is up
systemctl start openvpn
docker exec -it <container_name> /bin/bash

Running guacamole from a Docker Container on Ubuntu 16.04 LTS / 16.10

Updated Feb 2017 to reflect guacamole/guacd and guacamole/guacamole Docker images, rather than the glyptond images.

I’ve been looking at how I can move some/ all of my QEMU virtualised workloads to docker containers – the main drivers behind this being:

  • Reducing the administrative overhead of updating an additional operating system
  • Reducing the compute overhead of running an additional operating system on top of the host O/S

I also looked at whether this solution wold run in a docker-enabled Ubuntu 16.04 LXD container and, whilst the mysql and guacamole images downloded, the guacd image failed with an “operation not permitted error” meaning I was unable to use the image inside an LXD container.

I use Apache guacamole for remote access to my infrastructure and, on finding there were guacamole containers for the client and server elements, I thought I would look to move this workload from a dedicated Ubuntu Server 16.04 LTS Virtual Machine to a docker container.

This guide assumes you have installed docker as outlined here: http://www.cb-net.co.uk/linux/installing-docker-on-ubuntu-16-04-lts-16-10/

Downloading / Deploying the Container

Be sure to define/ update the commands below with:

  • A new mysql root user password (find and replace <root password> )
  • A new mysql guacamole user password (find and replace <guac user password> )

We will now create/ configure and start three containers:

  1. A mysql database instance: guac-mysql
  2. A guacamole-server container: guacd
  3. A guacamole-client container: guacamole
# Pull the guacamole (and related) docker images
sudo docker pull guacamole/guacd
sudo docker pull guacamole/guacamole
sudo docker pull mysql 

# Create script to prepare MySQL Database
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql

# Make a scripts folder to pass-through to container
mkdir /tmp/scripts
cp initdb.sql /tmp/scripts

# Create/ start mysql instance
docker run --name guac-mysql -v /tmp/scripts:/tmp/scripts -e MYSQL_ROOT_PASSWORD=<root password> -d mysql:latest 
history -c

# Create mysql db, user and prepare mysql instance for guacamole
docker exec -it guac-mysql /bin/bash

mysql -u root -p'<root password>'
CREATE USER 'guacamole' IDENTIFIED BY '<guac user password>';

cat /tmp/scripts/initdb.sql | mysql -u root -p'<root password>' guacamole
history -c

# Now ctrl-d to exit docker container shell

# Start guacd 
docker run --name guacd -d guacamole/guacd

# Start guacamole client
docker run --name guacamole --link guacd:guacd --link guac-mysql:mysql \
-e MYSQL_DATABASE='guacamole' \
-e MYSQL_USER='guacamole' \
-e MYSQL_PASSWORD='<guac user password>' \
-d -p 8080:8080 guacamole/guacamole

You can now browse to http://<docker host IP>:8080/guacamole/ and login using the credentials guacadmin/guacadmin.

Managing the Containers

Replace “guac-mysql” below with the other container names used above to manage guacd, guacamole or guac-mysql independently:

# Start a container
sudo docker start guac-mysql
# Stop a container
sudo docker stop guac-mysql
# Hard-stop a container
sudo docker kill guac-mysql
# Restart (and auto-update) a container
sudo docker restart guac-mysql
# List all running containers
sudo docker ps
# List all running AND non-running containers
sudo docker ps -a
# Remove a container
sudo docker rm guac-mysql
# Remove the mysql docker image
sudo docker rmi mysql
# Review logs for container
sudo docker logs -f guac-mysql

Running Plex from a Docker Container on Ubuntu 16.04 LTS / 16.10

Updated 24/12/16 : Plex now have an official Docker container, this guide has been updated to use this.

I’ve been looking at the merits of moving my Plex server workload from a dedicated KVM/QEMU virtual machine to a docker container on the host server itself. The reasons for doing this were as below:

  • Reducing the administrative overhead of updating an additional operating system
  • Reducing the compute overhead of running an additional operating system on top of the host O/S

An additional benefit of running Plex in this manner is that on restarting the container the latest version of Plex is automatically pulled and deployed, making update in future very, very simple.

This guide assumes you have installed docker as outlined here: http://www.cb-net.co.uk/linux/installing-docker-on-ubuntu-16-04-lts-16-10/

Downloading / Deploying the Container

To download and deploy the container you will need:

  • A storage location for Plex configuration directory (in this example /mnt/media1/config) – this will vary in size base don how large your library is.
  • A storage location that contains all media (in this example there are multiple “-v” definitions that represent paths to tv shows, movies etc. you can have as many of these as you want)
# Pull the linuxserver/plex docker image
sudo docker pull plexinc/pms-docker

# Get a Plex Claim Token by going to this URL and replace <CLAIM> below
# https://www.plex.tv/claim/

# Create a new linuxserver/plex docker container
docker create \
--name plex \
--net=host \
-e TZ=Europe/London \
-e PUID=1000 -e PGID=1000 \
-v <path to config>:/config \
-v <path to music>:/data/music \
-v <path to tv series>:/data/tvshows \
-v <path to movies>:/data/movies \
-v <path to home videos>:/data/homevideos \

# Configure docker container to always update
docker update --restart=always plex

# Start the plex container
docker start plex

You can now browse to http://<docker host IP>:32400 and login using you plex.tv account.

If you want to use the PlexPass version of Plex modify the server settings and restart the container using the command shown below.

Managing the Plex Container

# Start the plex container
sudo docker start plex
# Stop the plex container
sudo docker stop plex
# Hard-stop the plex container
sudo docker kill plex
# Restart (and auto-update) the plex container
sudo docker restart plex
# List all running containers
sudo docker ps
# List all running AND non-running containers
sudo docker ps -a
# Remove the plex container (note you can redploy and will not lose anything/ config wise)
sudo docker rm plex
# Remove the linuxserver/plex docker image
sudo docker rmi linuxserver/plex
# Review logs for plex container
sudo docker logs -f plex

Installing Docker on Ubuntu Server 16.04 LTS / 16.10

I’ve been looking at moving some of my application/ process workloads from KVM/ QEMU Virtual Machines to docker containers – simply to reduce unnecessary overhead and complexity.

Installing docker on Ubuntu Server 16.04 or 16.10 is surprisingly straight-forwards, it is also possible (from my experience) to run docker alongside KVM/QEMU on the host server, as well as running docker containers within KVM/QEMU virtual machines.

# Update host O/S
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates

# Create apt source for docker
sudo apt-key adv \
--keyserver hkp://ha.pool.sks-keyservers.net:80 \
--recv-keys 58118E89F3A912897C070ADBF76221572C52609D 
echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list

# Pre-reqs installation
sudo apt-get update
sudo apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual

# Install docker
sudo apt-get update
sudo apt-get install docker-engine
sudo service docker start

# UFW config
sudo ufw status

# If UFW enabled modify /etc/default/ufw
vi /etc/default/ufw

# Set docker to start on boot
sudo systemctl enable docker

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

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
             bridge_ports enp0s31f6
             bridge_stp off
             bridge_fd 0
  • Storage layout as below:
 ├─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= \
 --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=''/>

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"
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 \

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!

# 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 USER 'guacamole'@'localhost' IDENTIFIED BY '<password>';
 GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole.* TO 'guacamole'@'localhost';
# 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 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/

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!

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