LAN remote access

Hi community,

I’d like to setup a headless Qubes box that can be accessed via VNC or RDP or some other remote access protocol but can’t find much (if any) documentation on remote access for Qubes. Is something like this even possible?

Kind regards,

J

qubes-remote-desktop

SystemD services for creating VNC server session in dom0 or any qube.

https://github.com/QubesOS-contrib/qubes-remote-desktop

I tried this just now on 4.0.4 and am getting an error about not being able to verify “/var/lib/qubes/dom0-update/packages/qubes-remote-desktop-4.0.3-1.fc25.x86_64”

I did install the qubes-contrib and used the --clean flag.
I also tried updating --clean qubes-core-dom0-linux and qubes-rpm-oxide.

No luck so far.

My goal is to create a few “how to” videos for Qubes. I wanted to install OBS-Studio in dom0, but could not. Using VNC to another box with OBS-studio would achieve the same result.

Thank you for any assistance or ideas.

As a first-timer jumping into the new release, this was the first thing I did-- consider it a hack to “install” Qubes on my unsupported laptop[1].

The networking wasn’t that complicated in retrospect, but it was definitely a lot to take in on top of, well, all of the Qubes. A lot of the threads that come up when you search for “Remote Access” are inconclusive or dismissive, so I wanted to record what I did as of v4.2.1 (March 2024).

Disclaimer: Opening a port to dom0 is obviously a major pot-hole on the slippery slope of trading security for convenience. Don’t do this if you’ve legitimately been drawn to Qubes for it’s security posture.

I hit this thread (ours, this one, right here) pretty quickly, and dove for qubes-remote-desktop via qubes-contrib.

sudo qubes-dom0-update qubes-repo-contrib
sudo qubes-dom0-update qubes-remote-desktop

That, uh, didn’t work. The URL format seems to have changed over at https://contrib.qubes-os.org/, and when I patched /etc to use the current paths, qubes-remote-desktop wasn’t in the repo. I adjusted the paths and version numbers to pull from the v4.1 repo, and that got me my unit files.

qubes-remote-desktop doesn’t seem to have been made with dom0 in mind, so I got a lot of help with the networking from @AWhite and @apparatus’ discussion on out-bound dom0 ports; just had to flip the direction around and, uhm, get qvm-run and socat to co-operate in a vaguely robust manner[2]. Maybe because I ditched their systemd .socket unit? And I’m pretty sure some of these nft attributes are extraneous. But without further ado:

The Code
# sys-net:/rw/config/qubes-firewall-user-script
if nft add chain qubes custom-dnat-dom0 '{ type nat hook prerouting priority filter +1; policy accept; }'; then
  nft add rule qubes custom-dnat-dom0 iif == "ens6" ip saddr 192.168.0.0/24 tcp dport 5900 ct state new,established,related counter dnat {{SYS_FIREWALL_IP}}
  nft add rule qubes custom-forward iif == "ens6" ip saddr 192.168.0.0/24 ip daddr {{SYS_FIREWALL_IP}} ct state new,established,related counter accept
fi
# sys-firewall:/rw/config/qubes-firewall-user-script
if nft add chain qubes custom-dnat-dom0 '{ type nat hook prerouting priority filter +1; policy accept; }'; then
  nft add rule qubes custom-dnat-dom0 iif == "eth0" ip saddr 192.168.0.0/24 tcp dport 5900 ct state new,established,related counter redirect to :5900
  nft add rule qubes custom-input iif == "eth0" ip saddr 192.168.0.0/24 tcp dport 5900 ct state new,established,related counter accept
fi
# dom0:/home/{{USER}}/run.sh
cat << 'EOF' | sudo tee /etc/systemd/system/custom-dnat-dom0@.service
[Unit]
Description=custom-dnat-dom0
After=qubes-x0vncserver@%i.service
PartOf=qubes-x0vncserver@%i.service

[Service]
SyslogIdentifier=custom-dnat-dom0@%i
User=%i
Group=%i
Type=exec

ExecStart=bash -c \
  "while true; do \
     /usr/bin/socat \
       EXEC:\"'qvm-run --pass-io sys-firewall \
         socat tcp-listen:5900,keepalive stdio'\" \
       tcp:localhost:5900; \
     qvm-run --pass-io sys-firewall \
       pkill -f 'socat tcp-listen:5900.\* stdio'; \
   done"
ExecStopPost=qvm-run --pass-io sys-firewall \
  pkill -f 'socat tcp-listen:5900.* stdio'

# XXX: x0vncserver doesn't wait until it's listening to fork.
ExecStartPre=/bin/sleep 2

[Install]
WantedBy=qubes-x0vncserver@%i.service
EOF

sudo systemctl daemon-reload
sudo systemctl enable custom-dnat-dom0@{{USER}}
sudo systemctl enable --now qubes-x0vncserver@{{USER}}

If I were going to do any more work on/like this, I’d come back to these notes:

  • This thread suggests qubes-remote-support, and possibly future developments in GuiVM+VNC support.
  • A lot of people seem to be using x2go over SSH for this.
  • It’s obvious from this example that the networking could be greatly simplified once I grok policies.
  • Didn’t discover qvm-connect-tcp or this util until I was done, but it was a better learning experience that way.
  • Some pains were taken to not modify qubes-remote-desktop’s existing unit files. An ideal re-packaging would probably tie into Qubes’ existing framework for RPC Services and support ad-hoc Qube, Protocol, and Access configurations.
  • could vnc do 2FA (both auth & pass-through)?

1: ie. I know this isn’t ideal in several ways, and that there exist suggestions such as forwarding only the display.
2: I believe qvm-run closes std{in,out} on EOF such that we can’t continue to read from it, and that it was leaving orphaned processed in sys-firewall when the Qube-side socat was configured to fork. Doesn’t seem designed for procedural use, and it doesn’t help that socat’s not a perfect citizen of the command-line either.