Objective
Learning how to share you desktop using the vnc protocol and the x11vnc application
Requirements
- Having the x11vnc package installed
Conventions
- # – requires given command to be executed with root privileges either
directly as a root user or by use ofsudo
command - $ – given command to be executed as a regular non-privileged user
Introduction
While ssh is a vital tool for every system administrator, being it the most used and secure protocol for remote administration, even capable to grant access to the X11 display server, via X11 forwarding, it is not the right tool to use when the desired target is to share an entire desktop session. In that case the vnc
protocol is our friend. By using it, we can completely control another machine, sharing even keyboard or mouse events.
Although many
implementations of the protocol exist on Gnu/Linux, and some of them are integrated with specific desktop environments, like vino/vinagre
in GNOME, in this tutorial we will focus on the use and the setup of the desktop-independent x11vnc
application.
Installation
The x11vnc
application should be already packaged and available in your favorite distribution repositories. Installing it on Fedora it’s just a matter of running:
$ sudo dnf install x11vnc
On Debian, or a Debian-based distribution, the command to use is:
$ sudo apt-get install x11vnc
x11vnc is also available in the Archlinux repositories. We can install it using pacman
:
$ sudo pacman -S x11vnc
Once installed, the program can be launched straight from the terminal, or via gui, using the desktop launcher that should be found in the applications menu.
Firewall setup
To be able to share our desktop session using the vnc protocol, we must setup the firewall so that it allows incoming connections on port 5900
which is the default vnc-server port. The exact action to perform depends on the firewall software we are using on our system. When using firewalld
we should run:
$ sudo firewall-cmd --add-service=vnc-server
As you can see, we didn’t actually specified the port to be allowed directly: instead, we used the service name directly, since it is by default associated with the port. Remember, when using firewalld
, if a zone is not specified with the --zone
option, the specified rules will be applied on the default one.
When using ufw
, the default firewall in Ubuntu, the command to be used is:
$ sudo ufw allow 5900/tcp
Furthermore, if we intend to allow vnc connection from machines outside of our local network, we should configure an allow rule for the same port in our router, and setup ip forwarding to our machine ip.
Getting familiar with x11vnc
The easiest way to start using x11vnc is to invoke the program in the terminal without any option. The program must be launched without administrator privileges:
$ x11vnc
By default x11vnc will use display :0
, however, this can be changed using the -display
option.
The first thing we will receive after running the above command is a warning about not using a password for the connection. That is expected, since we haven’t setup any yet. Running with this setup is very dangerous, since any computer with network access to our machine can potentially view and control our desktop. The first thing we need to do, then, is to setup the program so that it requires authentication when access is requested.
Restrict access with a password
There are basically three ways we can setup authentication using x11vnc, they correspond to the -passwd
, -storepasswd
, and -passwdfile
options. Let’s see briefly how they modify the behavior of the program.
The first method is represented by the use of the -passwd
option which let us provide a runtime, one-shot, plain-text password directly in the terminal: it will not be saved anywhere, and will just be used for the launched session.
The second method, is to use the -storepasswd
option: it accepts two optional arguments: pass
and file
, to specify respectively the password and the file in which it should be stored. However, if used with no arguments, it will prompt for the password interactively, and it will be stored in the ~/.vnc/passwd
file. Finally, if the option is used with just one argument, it will be interpreted as the file in which to store the password. Please notice that the file containing the password will not be encrypted, but just obfuscated with a fixed key, therefore only trusted user should be allowed to access it.
Once the password is saved, the program will exit. From that moment on, to launch a password-protected vnc session, the following command must be issued:
$ x11vnc -rfbauth /path/to/passfile
Where, by default, /path/to/passfile will correspond to ~/.vnc/passwd.
The third option we have is to use the -passwdfile
flag. By using it the password for the connection is set by reading the first line of an existing file, passed as the sole option argument. The behavior of the option can be further modified by prefixing the file argument. For example, if the filename is prefixed with rm:
, the file itself will be deleted after its content has been read by the program. When using the cmd:
prefix, instead, the string specified after the prefix will be interpreted as an external command, and its output will be used as the password. Other prefixes can be used with this option. For a complete reference you can consult the program’s manpage.
Provide a password for view-only sessions
It is possible to use x11vnc
so the created connection will run in view-only mode. This means that the connected clients will only be allowed to observe the shared session, but will not be able to interact with it. To run in this mode the program must be launched with the -viewonly
option. It’s possible to setup a password spefic for this kind of access, so to obtain a more grained setup. To obtain this result, the -viewpasswd
option must be used, providing the password as a string argument. This requires, however that a full-access password is also provided, using the -passwd
option we discussed above.
Secure the connection using an encrypted tunnel
By default, a vnc connection is not encrypted, and this can be a security risk. We can use different approaches to fix this. The first one would be to use a Vpn
(Virtual private network), the second to use an ssl tunnel and the third one to use ssh
.
While describing how to setup a vpn is out of the scope of this article, we will shortly see how to implement the other two options.
Use a ssl/tls tunnel
We can encrypt the vnc connection by using an ssl tunnel. To be able to accomplish this, we must use the -ssl
or -stunnel
options. The former requires x11vnc to be compiled with libssl
support. This option accepts one argument which is the certificate in pem
format to be used. If this argument is not provided and the openssl
utility is installed on our system, a new certificate will be generated and saved in ~/.vnc/certs/server.pem
.
The -ssltunnel
option, instead, relies on the use of an external program, stunnel
to provide an ssl connection. As -ssl, it also accepts a pem certificate as an argument. If it is not provided, a new one will be generated, and saved as mentioned above (this behavior can however be changed, for example using the string TMP
as argument – in this case a temporary certificate will be generated).
Notice that in both cases, the automatically generated certificate will be self-signed, therefore, although providing a secure connection it will not represent a protection from a man-in-the-middle attack. When generating the certificate, we will be asked if we want to provide a password to protect it, and if it’s the case we will be prompted to insert it.
Finally, to be able to use a ssl tunnel, the client application must support ssl.
Use an ssh tunnel
To use an ssh tunnel, we must start the vnc server using ssh, with this command (this assumes that the default port is used):
$ ssh -t -L 5900:localhost:5900 remote-machine 'x11vnc -localhost -display :0'
You are probably familiar with ssh, but let’s analyze this command. First of all we ran ssh with the -t
option, to allocate a pseudo-terminal, and with the -L
one, we basically said to forward port 5900
on our local (client) machine to the same port on the remote machine. As you can see, the x11vnc command is launched with the -localhost
option. What this basically does is to only allow connections from the same machine the server is running on. This option is also automatically used when using an ssl tunnel to avoid bypassing it. After that, we can start our vncviewer on the client:
$ vncviewer -PreferredEncoding=ZRLE localhost:0
Notice that we set the preferred encoding to ZRLE
, this should help performance over ssh.
Run in graphical mode
As said before, x11vnc
can also be used in graphical mode, using the desktop launcher. By default the program will show a window in which we can select which port to use, plus other options:
After we click on the “ok” button an icon will be showed in the system tray and a window with its properties will appear onscreen. On the left side some useful instructions will be displayed for a quick startup. From this interface we can also choose a session-spefic and view-only password:
Conclusions
While Vnc does not even come near to represent a substitute for ssh, it can be the right tool to use for some specific tasks. In this tutorial we saw the fundamental steps needed to configure and use the x11vnc
server. While many alternatives are available, x11vnc is a very simple and desktop-independent tool, that can be used anywhere.