Learning how to share you desktop using the vnc protocol and the x11vnc application


  • Having the x11vnc package installed




  • # - requires given command to be executed with root privileges either directly as a root user or by use of sudo command
  • $ - given command to be executed as a regular non-privileged user


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.


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:

Select x11vnc port window
Select x11vnc port window

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:

x11vnc properties window
x11vnc properties window


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.

Comments and Discussions