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!
UPDATE: See revised post.
The Qubes operating system aims to be reasonably secure through isolation.
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.
To get the most out of this post, readers should already be familiar with Qubes and the difference between template vs. application VMs.
Prepare the Template VM
I made a clone of Qubes’ fedora-25
template called f25-media
(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 f25-media
template.
Inter-VM networking
The screenshare
VM is hosting VNC, other VMs will display apps
there, so those app VMs need a network connection to screenshare
.
By default, Qubes prevents such networking, so we need to explicitly
enable it.
You can allow this inter-vm network traffic by following the official instructions.
I chose another
approach
which I think is simpler. I created a VM called inter-vm-proxy
. In
/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 screenshare
app VM…
ip="10.137.0.33" # Change this to the IP address of `screenshare` app VM.
iptables -I INPUT -s $ip/24 -j ACCEPT
Configure 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
from it.
Screenshare VM Window Manager
The 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 dwm
.
sudo dnf install libX11-devel libXft-devel libXinerama-devel
Next, compile and install dwm
. It will be installed in /usr/local
,
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
vncserver Configuration
Edit ~/.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.)
Also edit ~/.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
TigerVnc.)
Test
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 screenshare
VM…
[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
xhost +
.
Finally, Screenshare
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!
Share this post
Twitter
Facebook
Reddit
LinkedIn
StumbleUpon
Email