Creating reasonably secure remote administration for Qubes OS
This guide will help you create an authenticated service for managing Qubes OS remotely
By design it will be:
- Encrypted
- Authenticated (with a key)
- Over Tor
- Works behind NAT/CGNAT
- No open ports required
- Accessible from any computer with a Tor Browser / Tails / Whonix
Qubes OS security is based on dom0 being inaccessible and airgapped. Remote administration is against Qubes OS philosophy and reduces the security of your entire system to that of Tor’s Onion services authentication and your whonix-workstation-vm’s security. Anyone with a key will be able to access (and therefore compromise) your machine. Compromising a whonix-workstation-vm means compromising the entire machine. Incorrectly configuring this server can and will make your computer vulnerable to unauthorized remote access. This setup aims to provide the most secure way of controlling Qubes OS remotely; however, if you are not comfortable with this level of risk, reconsider remote administration in favor of physical access.
Setup looks like this:
┌─────────────────────────────────────────────────────────────────────────────┐
│ Remote User │
│ (Tor Browser / Tails / Whonix with authentication key) │
└──────────────────────┬──────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Tor Network │
│ (Hidden Onion Service v3 with client authentication) │
└──────────────────────┬──────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ sys-whonix │
│ (Tor gateway VM - routes onion service to workstation) │
└──────────────────────┬──────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ whonix-workstation-vm │
│ (Firewall configured to accept & forward connections) │
└──────────────────────┬──────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ dom0 │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ noVNC frontend (port 6080) │ │
│ │ └─ Websockify proxy to x11vnc │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ x11vnc backend (port 5900) │ │
│ │ └─ Captures display :0 │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Data flow: Remote User → Tor → sys-whonix → whonix-workstation-vm → dom0 (noVNC → x11vnc)
We will need to:
- Setup a VNC service on dom0
- Setup a noVNC frontend so that the VNC service can be accessed over browser
- Setup qubes.ConnectTCP policy to allow forwarding of requests from whonix-workstation-vm to dom0
- Configure sys-whonix to create a hidden onion service with key authentication and to route requests to whonix-workstation-vm
- Configure whonix-workstation-vm firewall to accept these requests and route them to dom0
And to use:
- Extract hidden service .onion hostname and access key
- Configure the key to be used in Tor browser
- Connect to our remote administration website
First of all, let’s break this complex task into 2 parts:
- making a VNC service available and running on our machine, and only then
- making it available remotely
Making a VNC service available on your machine
We will have a backend service (the one actually supplying the VNC data) on localhost, and then we will use noVNC, which will give us frontend part that will allow you to access this service without using any tools other than your browser. Sounds simple enough.
Package installation
I’ve tried to use tigervnc at first, but it causes all sorts of problems and even caused a softlock once, so use x11vnc instead
Next commands should be run in dom0
sudo qubes-dom0-update x11vnc novnc python3-websockify
x11vnc will be the backend, and novnc with python3-websockify will make a frontend service
Backend configuration
Create the following file
sudo nano /etc/systemd/system/x11vnc.service
With the following contents
[Unit]
Description=x11vnc server
After=network.target
Wants=multi-user.target
[Service]
Type=simple
ExecStart=x11vnc -display :0 -nopw -forever -wait 100 -defer 100 -nap -solid -nodpms -nosel
User=user
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
It runs backend x11vnc server with arguments for optimization of the connection on slow networks. Using -nopw (no password) is fine here, because we will use Onion services authentication instead. Launch it and configure to run at boot with
sudo systemctl enable --now x11vnc
Frontend configuration
Create the following file
sudo nano /etc/systemd/system/novnc.service
With the following contents (replace yourusername with your dom0 username)
[Unit]
Description=noVNC WebSocket Proxy
After=network.target x11vnc.service
Wants=x11vnc.service
[Service]
Type=simple
User=yourusername
ExecStart=/usr/bin/websockify --web /usr/share/novnc/ localhost:6080 localhost:5900
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
This will take connection from x11vnc server and make it available to use over browser at port 6080
Run it and also enable it to run at boot with the following:
sudo systemctl enable --now novnc
Check if it runs
sudo systemctl status novnc
Once your service is accessible and working at http://127.0.0.1:6080 , we can proceed further into exposing it securely.
Making our VNC server accessible remotely
Firstly, we need to route our vnc connection from dom0 to whonix-workstation-vm
Open Qubes Policy Editor in dom0
Create a new policy file named 30-user
Add the following rule
qubes.ConnectTCP +6080 vncvm @adminvm allow
(it assumes your whonix-workstation-vm is named vncvm, replace with your own name if it’s different) 4. Save this policy file
Then open a terminal in vncvm and add the following line to /rw/config/rc.local file:
qvm-connect-tcp 6080:@adminvm:6080
This will enable routing of packets from dom0’s 6080 port to vncvm’s 6080 port at boot.
Then you can check if it works by opening a browser other than TorBrowser and visiting localhost:6080
Once you have that working, it’s time to configure tor to open you a .onion authenticated service.
In whonix, whonix-workstation only uses tor connection that is actually configured in sys-whonix, so to open up a port you will need to configure sys-whonix to open up a service and route packets from tor network to your whonix-workstation-vm, and then to accept these by configuring whonix-workstation-vm firewall. Both of these steps are explained in the official whonix documentation below. Please read it carefully and execute steps as described, prefer copying commands to avoid typos:
https://www.whonix.org/wiki/Onion_Services#Hidden_Webserver
Instead of creating your own configuration, in sys-whonix, let sudo anon-auth-autogen generate the config for you, then edit 43_hidden_service_hs_authgen.conf in /usr/local/etc/torrc.d (you will need root privileges)
The contents will have to be something like this
HiddenServiceDir /var/lib/tor/hidden_service
HiddenServicePort 80 10.137.0.X:6080
HiddenServiceVersion 3
Where 10.137.0.X should be replaced with the IP of your VM. You can find this in the settings of whonix-workstation-vm
Then don’t forget to use anon-server-to-client-install in sys-whonix to configure 1.auth_private key to enable you access to your new website (relevant instructions can also be found on whonix wiki). Then visit your website and your keys will be used automatically.