NOTE: The setting described below have security implications. See https://groups.google.com/d/msg/qubes-users/3amtMOIBTgI/rXLXmbM5AAAJ for discussion. At the moment, I am not recommending this approach. I’ll update here if I am able to improve on it. Caveat emptor!
One example of isolation: one Qubes virtual machine runs the windowing environment, while other VMs run applications displayed in that environment. This separation from the X11 environment means that an application, like skype or bluejeans, cannot share this screen. This is by design, and is a good example of the security that makes me a fan of Qubes.
Sometimes, however, I want to screenshare. This post describes how it can be done in Qubes (4.x).
The strategy is to run a virtual network computing (VNC) desktop. The applications we explicitly display there can be screenshared.
Prepare the Template VM
I made a clone of Qubes’
fedora-25 template called
(because I’ve installed codecs and applications to display various
media formats). I use that template for the VM which runs the VNC
server. So to start, install the VNC software there.
[user@f25-media ~]$ sudo dnf install tigervnc tigervnc-server
Prepare the Screenshare App VM
I set up a VM dedicated to running
vncserver. The idea is to be
able to share apps running in more than on app VM, in a single screen
sharing session. If you only ever need to screenshare from a single
app VM, you could instead just run
vncserver there, and skip some of
the configuration described here..
I called this app VM
screenshare and based it on the
screenshare VM is hosting VNC, other VMs will display apps
there, so those app VMs need a network connection to
By default, Qubes prevents such networking, so we need to explicitly
You can allow this inter-vm network traffic by following the official instructions.
I chose another
which I think is simpler. I created a VM called
/rw/config/qubes-firewall-user-script I set up these rules…
intervm_internalnet="10.137.0.32" # Change this to the IP address of `inter-vm-proxy` VM. iptables -I FORWARD 1 -i vif+ -o vif+ -s $intervm_internalnet/24 -d $intervm_internalnet/24 -m state --state NEW -p tcp -m tcp -j ACCEPT iptables -I FORWARD 1 -i vif+ -o vif+ -s $intervm_internalnet/24 -d $intervm_internalnet/24 -p udp -m udp -j ACCEPT
Note, you’ll also need to accept incoming connections on the
screenshare VM. Use a similar approach in
/rw/config/qubes-firewall-user-script, this time on
ip="10.137.0.33" # Change this to the IP address of `screenshare` app VM. iptables -I INPUT -s $ip/24 -j ACCEPT
screenshare VM to use
inter-vm-proxy for networking.
Also, before you need to screenshare from other app VMs, configure
them to use
inter-vm-proxy, too! While this may seem like an extra
step, I think of it as additional security. Unless I configure an app
VM to use
inter-vm-proxy network, I won’t accidentally screenshare
Screenshare VM Window Manager
screenshare VM needs a window manager for the VNC environment.
I decided to try
dwm from suckless. It
has a reputation for being lightweight, which I’m more than OK with,
for this purpose.
First install dependencies. Note this can be done on the
screenshare VM (as opposed to the template VM). We won’t need these
again after compiling
sudo dnf install libX11-devel libXft-devel libXinerama-devel
Next, compile and install
dwm. It will be installed in
which lives in
screenshare app VM, not the template.
[user@screenshare ~]$ git clone https://git.suckless.org/dwm [user@screenshare ~]$ cd dwm [user@screenshare ~]$ make [user@screenshare ~]$ sudo make install
~/.vnc/config to make
vncserver easier to start on the command line:
securitytypes=none alwaysshared listen=tcp
(I’m counting on Qubes’ firewall to keep the environment reasonably secure, despite the insecure settings shown here.)
~/.vnc/xstartup. Here’s what I ended up with:
#!/bin/sh # Use `xhost +` to allow Qubes app VMs to access this vnc session. xhost + # The following from the dwm README. while xsetroot -name "`date` `uptime | sed 's/.*,//'`" do sleep 1 done & exec dwm
Then run the VNC server and viewer…
[user@screenshare ~]$ vncserver [user@screenshare ~]$ vncviewer :1
(If you prefer to enable
vncserver as a service that starts
automatically, the ArchWiki comes through with a detailed HOWTO for
Perform two quick tests to make sure the VNC environment is OK. First
from the machine where
vncserver is running…
[user@screenshare ~]$ DISPLAY=:1 xterm
Next from another app VM. Change the IP address shown below to be your
[user@another-vm ~]$ DIPLAY=10.137.0.33:1 xterm
If the first test works, but the second does not, you’ll need to
troubleshoot the inter-vm firewall settings, and make sure you’ve run
Now use the
$DISPLAY environment to start up applications that you
want to share in a conference. For example, start a browser:
[user@another-vm ~]$ DISPLAY=10.137.0.33:1 firefox
In that browser, navigate to a conference website and join a meeting. Screensharing should work, and only the windows displayed in the VNC environment will be visible in the screenshare.
Thanks to Qubes, you’ve isolated the shared windows from others securely visible only to you!