Remote Desktop using RDP and VNC

       2259 words, 11 minutes

My initial questionning was on the opportunity to run a desktop environment using virtual machines provided by the OpenBSD vmd(8). But vmd(8) doesn’t feature graphics, as of OpenBSD 7.5. Let’s see if this can be achieved anyway.

The only way I know to get graphics out of a headless serial machine is by using some specialized network protocols: VNC or RDP .

What’s nice is that it could also apply to any (Cloud) VPS. And also to any rack server or headless home servers.

Note that if you’re using virtualization platforms such as Hyper-V, vSphere, Proxmox or even bhyve, you already have access to the graphics in some way. Still, you could use RDP and/or VNC with those if you like it better.

Hosting platforms

As I said, the original idea was to see if it’s possible to get a graphical desktop using virtual machines in OpenBSD vmd(8). Spoiler Alert: it is… but… it can be quite slow. More on this in the last paragraph.

I finally decided to test and compare 3 kinds of configurations to expose RDP and VNC:

RDP, VNC and graphical software were either run natively on the hardware or inside virtual machines provided by the hypervisor running on those hardware. Each VM was configured with 1 vCPU and 1GB of RAM.

I tested the following deployment options:

Remote Desktop server software

I have biaises when it comes to selecting the software to use.

  1. A client has to be available for OpenBSD.
  2. I don’t really seek for multimedia performance.
    If audio is available, that’s great.
    If video is accelerated, excellent but I can live without it.
    I do not play games.
  3. I’d rather use a limited number of different software.
  4. I don’t want proprietary, non-free software.

RDP (xrdp) on Debian GNU/Linux 12

The system is installed using the text installer and selecting only SSH server and standard system utilities ; no desktop environment or graphical tools. Once the installation is finished and access can be granted using SSH, xrdp can be installed.

By default, only xrdp and xorgxrdp are available in the repository. To be able to use audio on the remote desktop, backports repository need to be enabled to install pipewire-module-xrdp.

# cat >> /etc/apt/sources.list
deb http://deb.debian.org/debian/ bookworm-backports main non-free-firmware contrib non-free
^D

# apt update
# apt install xrdp pipewire-module-xrdp

Only xterm is installed and enabled yet. Installing Xfce and configuring the unprivileged user environment is faily simple.

# apt install xfce4 xfce4-goodies

$ echo 'exec /usr/bin/startxfce4' > ~/.xsession

Everything is now ready to use the remote connection.

RDP (xrdp) on Slackware Linux 15.0

The system is installed using full mode, as recommended by the documentation. Once done, create an unprivileged user (using “adduser”) and enable SSH for easier remote maintenance access. By default, the OS boots in text mode (init 3) ; no need to change this.

xrdp and xorgxrdp are available via SlackBuilds. GVFS is only required if you want to share the local storage via RDP.

# wget https://slackbuilds.org/slackbuilds/15.0/system/xrdp.tar.gz
# tar xzf xrdp.tar.gz
# cd xrdp
# wget https://github.com/neutrinolabs/xrdp/releases/download/v0.9.12/xrdp-0.9.12.tar.gz
# ./xrdp.SlackBuild
USE_GVFS=YES ./xrdp.SlackBuild
# installpkg /tmp/xrdp-0.9.12-x86_64-2_SBo.tgz

# wget https://slackbuilds.org/slackbuilds/15.0/system/xorgxrdp.tar.gz
# tar xzf xorgxrdp.tar.gz
# cd xorgxrdp
# wget https://github.com/neutrinolabs/xorgxrdp/archive/v0.2.12/xorgxrdp-0.2.12.tar.gz
# ./xorgxrdp.SlackBuild
# installpkg /tmp/xorgxrdp-0.2.12-x86_64-2_SBo.tgz

# cat > /etc/X11/Xwrapper.config
allowed_users = anybody
^D

To have the daemon start at boot time, a few extras commands are required.

# chmod +x /etc/rc.d/rc.xrdp
# /etc/rc.d/rc.xrdp start

# cat >> /etc/rc.d/rc.local
[ -x /etc/rc.d/rc.xrdp ] && /etc/rc.d/rc.xrdp start
^D

Audio redirection is not available yet. To enable it, an extra xrdp module is required. That module is not available in SlackBuilds so one has to get the sources and compile it. Furthemore, it requires the PulseAudio sources from the current Slackware release.

# cd ~
# mkdir pulseaudio && cd pulseaudio
# wget -r -nd -np i\
  https://ftp.lip6.fr/pub/linux/distributions/slackware/slackware64-15.0/source/l/pulseaudio/
# rm index*
# chmod +x pulseaudio.SlackBuild
# ./pulseaudio.SlackBuild

# cd ~
# git clone https://github.com/neutrinolabs/pulseaudio-module-xrdp.git
# cd pulseaudio-module-xrdp
# ./bootstrap && ./configure PULSE_DIR=/tmp/pulseaudio-15.0
# make
# make install
(...)
Libraries have been installed in:
   /usr/lib64/pulse-15.0/modules
(...)
 /usr/bin/mkdir -p '/usr/libexec/pulseaudio-module-xrdp'
 /usr/bin/ginstall -c load_pa_modules.sh '/usr/libexec/pulseaudio-module-xrdp'
 /usr/bin/mkdir -p '/etc/xdg/autostart'
 /usr/bin/ginstall -c -m 644 pulseaudio-xrdp.desktop '/etc/xdg/autostart'
(...)

# ls $(pkg-config --variable=modlibexecdir libpulse) | grep xrdp
module-xrdp-sink.la*
module-xrdp-sink.so*
module-xrdp-source.la*
module-xrdp-source.so*

# /etc/rc.d/rc.xrdp restart

The full Slackware install provides Xfce so the user only has to enable it with a dedicated command.

$ xrdp-xwmconfig

Everything is now ready to use the remote connection.

RDP (xrdp) on FreeBSD 14.1

FreeBSD is installed with the default settings. When the system is installed and has rebooted, it can be accessed from SSH.

xrdp is available as a binary package and can be installed and enabled using the system tool.

# pkg install xrdp

# cat >> /etc/rc.conf
xrdp_enable="YES"
xrdp_sesman_enable="YES"
^D

# service xrdp-sesman start
# service xrdp start

As stated in the installation message

To enable audio redirection, install the following port/packages to meet your environment.

# pkg install pipewire-module-xrdp pulseaudio-module-xrdp
# service xrdp restart

If it was not done during install, create an unprivileged user, using the adduser command. I also tend to install bash for those users.

# pkg install bash-static
# adduser
(...)

No desktop environment is available yet. For the example, I installed Xfce.

# pkg install xorg xfce

# cat >> /etc/rc.conf
dbus_enable="YES"
^D
# service dbus start

# su - joel

$ cat > ~/startwm.sh
#!/usr/local/bin/bash
source /etc/profile
source ~/.profile
export LANG=fr_FR.UTF-8
exec startxfce4
^D

$ chmod +x startwm.sh

Everything is now ready to use the remote connection.

VNC (TigerVNC) on Debian GNU/Linux 12

The system is installed using the text installer and selecting only SSH server and standard system utilities ; no desktop environment or graphical tools. Once the installation is finished and access can be granted using SSH, TigerVNC can be installed.

# apt install tigervnc-standalone-server

Only xterm is installed and enabled yet. So install Xfce (for example) and configure the unprivileged user environment.

# apt install xfce4 xfce4-goodies

$ vncpasswd

$ cat > ~/.vnc/xstartup
#!/bin/sh
exec /usr/bin/startxfce4
^D
$ chmod +x ~/.vnc/xstartup

$ cat > ~/.vnc/config
geometry=1280x1024
^D

To have VNC being started after each boot sequence, a command is added to the user’s crontab.

$ crontab -e
(...)
@reboot vncserver -localhost no :1

Everything is now ready to use the remote connection.

VNC (TigerVNC) on Slackware Linux 15.0

The system is installed using full mode, as recommended by the documentation. Once done, create an unprivileged user (using “adduser”) and enable SSH for easier remote maintenance access. By default, the OS boots in text mode (init 3) ; no need to change this.

TigerVNC is available as a package.

# slackpkg install tigervnc

The full Slackware install provides Xfce so the user only has to enable it in the VNC configuration.

$ vncpasswd

$ cat > ~/.vnc/xstartup
#!/bin/sh
exec /usr/bin/startxfce4
^D
$ chmod +x ~/.vnc/xstartup

$ cat > ~/.vnc/config
geometry=1280x1024
^D

To have VNC being started after each boot sequence, a command is added to the user’s crontab.

$ crontab -e
(...)
@reboot vncserver -localhost no :1

Everything is now ready to use the remote connection.

VNC (TigerVNC) on OpenBSD

OpenBSD is installed as usual. During installation, only SSH is enabled ; not the X Window System. Once installed and SSH access is available, TigerVNC and the desktop environment can be installed.

# pkg_add tigervnc xfce-extras

# rcctl enable apmd messagebus
# rcctl start apmd messagebus

Xfce is enabled for VNC by issuing a few commands as an unprivileged user.

$ vncpasswd

$ cat > ~/.vnc/xstartup
export LC_ALL=fr_FR.UTF-8
if [ -x /usr/local/bin/dbus-launch -a -z "${DBUS_SESSION_BUS_ADDRESS}" ]; then
    eval `dbus-launch --sh-syntax --exit-with-x11`
fi
exec /usr/local/bin/startxfce4
^D
$ chmod +x ~/.vnc/xstartup

$ cat > ~/.vnc/config
geometry=1280x1024
^D

To have VNC start at each boot, add a command to the user’s crontab.

$ crontab -e
@reboot /usr/local/bin/vncserver :1

Notes on other Linux distros

There don’t seem to be a default Remote Desktop feature on Linux Mint 21.3 Cinnamon. The forum recommends RustDesk, NoMachine, X2Go or TigerVNC. I guess xrdp could be installed the same way as on Debian.

ZorinOS 17.1 and Pop!_OS 22.04 LTS ship with a Gnome Desktop. In the “Settings” window, go to the “Sharing” tab. Toggle the top switch to enable the sharing features. Click the “Remote Desktop” option to enable remote connections. By default, it uses RDP but you can “Enable Legacy VNC Protocol”. Enabling “Remote Control” does exactly that: it allows to take control of the screen. When it is disabled, you can only view the remote desktop content.

Pro Tip: Don’t forget to look at the “Authentication” section. The configured password is not the one you configured for your user desktop session… It has been generated randomly when Remote Desktop was enabled.

Remote Desktop client software

The client software used to test the overall performance and features were:

TigerVNC client invocation goes like this:

$ vncviewer ${HOSTIP}:1

rdesktop invocation goes like this:

$ rdesktop -g 1280x1024 -r disk:downloads=~/Downloads -r sound:local -r clipboard:PRIMARYCLIPBOARD $HOSTIP

Guacamole connections section (user-mapping.xml) looks like:

(...)
<connection name="Slackware RDP">
    <protocol>rdp</protocol>
    <param name="hostname">192.0.2.24</param>
    <param name="port">3389</param>
    <param name="security">tls</param>
    <param name="ignore-cert">true</param>
    <param name="username">changeme</param>
    <param name="password">changeme</param>
</connection>
<connection name="OpenBSD VNC">
    <protocol>vnc</protocol>
    <param name="hostname">192.0.2.49</param>
    <param name="port">5901</param>
    <param name="password">changeme</param>
</connection>
(...)

RDP client

There is no real difference between the various clients I tested. Only Guacamole seemed a bit more sluggish, no matter the Web browser or the OS.

Copy / Paste works between local and remote machines.

When configured, local shared folders were accessible R/W from the remote machines. For unknown reasons, on Slackware, I couldn’t access the files inside shared folders. On FreeBSD, the binary package is not compile with fuse support ; you have to enable FUSE_DESC and build from source.

Performance would vary depending on the hosting platform and client.
On hardware, it feels like you’re using USB and HDMI. Watching Big Buck Bunny @720p60 is even possible.
On KVM, the overall performance is ok. Remmina and rdesktop suffer from a few framedrops and sound desynchro while watching Big Buck Bunny @720p60. Windows Remote Desktop does not have issues. RD Client for iPadOS has loads of framedrops and audio artifacts.
On vmd(8), the Linux desktop is a bit laggy. Don’t expect to watch a video ; Big Buck Bunny @144p laggs a lot.

Note that you get no sound on Pop OS. From what I read, this is because the GNOME 42 version used in Ubuntu 22.04 is missing the feature. It seems to be available in GNOME 43. Also, rdesktop doesn’t work because of “CredSSP” errors ; but xfreerdp works ok.

VNC client

The overall performance is the same whatever client I used. None of those provide audio as it is not embedded in VNC ; on physical machines, you’ll get the sound out of the remote machine.

Copy / Paste works between local and remote machines.

AFAIK, there is no share folder feature available.

Performance mostly depends on the hosting platform.
On hardware, it feel like local USB/HDMI. There are still a few framedrops when watching Bug Buck Bunny @720p60 from YT on Firefox. The audio is renderred on the remote machine.
On KVM, it is a bit slower that on real hardware. There are loads of framedrops when watching the @720p60 video.
On vmd, OpenBSD is a bit faster than Linux. It is from slightly slower than physical to a bit sluggish. Framedrops happen on video even at @144p.

Web Client

Guacamole for OpenBSD was installed on a dedicated KVM virtual machine. Installation is quite simple:

# pkg_add guacamole-server guacamole

# more /usr/local/share/doc/pkg-readmes/guacamole

# ln -s /usr/local/share/guacamole/guacamole.war /var/tomcat/webapps/

# vi /etc/guacamole/user-mapping.xml

# rcctl enable messagebus guacd tomcat                                                                    
# rcctl restart messagebus guacd tomcat

Targeting the Web browser to http://serverip:8080/guacamole/, you can access any RDP, VNC or SSH connection you configured.

Performance is pretty limited. It is a bit better with LibreWolf on Windows than with Firefox on OpenBSD.
On hardware, watching Big Buck Bunny @720p60 has a few framedrops but you could watch it.
On KVM and vmd, the video can’t be rendered @480p without load of visual and audio artifacts.
On any platform, using a terminal and thunar is a bit sluggish but still useable.

Other clients

Because the Internet recommends other “new generation” tools, I gave a try to X2Go to access the Debian VM on vmd. OpenBSD has the x2goclient in ports. And well… the performance was even worse than using RDP.

The fact that is uses SSH is quite nice though.

Sum-up notes for self

Use either RDP or VNC depending on what’s enable on the desktop OS. RDP has the shared storage feature but this can be achieve using SSHFS when connecting using VNC.

For best performance, either use hardware or KVM platform. Keep vmd(8) for either OpenBSD or Linux server-like VMs.

Not really convinced with Guacamole. But it has the advantage of a centralized access point.