Suggestion: in-Qubes DNS

I know that inter-Qubes communication bypassing qrexec is generally discouraged. However, it is still quite common when you want to run a network service on a headless Qube for any purpose. It would be nice if we could address another AppVM IP by name, not just by number. Of course, we can populate the /etc/hosts file in all templates as a quick and dirty solution, but I would like to do it more elegantly.

1 Like

The following can be done in a seperate sys-dns, in my personal setup the service runs in sys-net based on a minimal template with root access disabled:

> /rw/config/rc.local


# This script will be executed at every VM startup, you can place your own
# custom commands here. This includes overriding some configuration in /etc,
# starting services etc.

nmcli radio wifi off
systemctl start dnscrypt-proxy.service
sysctl -w net.ipv4.conf.all.route_localnet=1 
> /home/user/dns_crypt

#! /bin/bash

# must be run as root
iptables -I INPUT -i vif+ -p udp --dport 53 -d -j ACCEPT ;
rm /etc/NetworkManager/NetworkManager.conf ;
ln -s /home/user/NetworkManager.conf.dnscrypt /etc/NetworkManager/NetworkManager.conf ;
systemctl restart NetworkManager


> /home/user/NetworkManager.conf.dnscrypt




All three files are owned by root:root and chmod-ed to 744.

My sys-net uses fedora-35-minimal as it’s template, which I have tweaked like this:

# sudo dnf install qubes-core-agent-networking qubes-core-agent-network-manager NetworkManager-wifi network-manager-applet wireless-tools notification-daemon gnome-keyring polkit
# sudo dnf install @hardware-support (or specific driver)

and for setting up the dns-resolver:

# sudo dnf install dnscrypt-proxy
# sudo systemctl disable --now systemd-resolved
# sudo systemctl disable --now dnscrypt-proxy.service
# vi /etc/dnscrypt-proxy/dnscrypt-proxy.toml
# listen_addresses = ['']
# further tweaks like relays, captive portals, blocking domains possible

dnscrypt-proxy is fast, reliable and highly customizable. Traffic is encrypted, you can block ad- and tracking-server, and it can use relays so the dnscrypt-resolver does not know your IP.

A remark about security: if dnscrypt-proxy is vulnerable an attacker would still have to lurk the victim to request a malicious DNS answer or to poisen a DNS resolver (which one? :wink:) with malicious DNS answers. Let’s say a malicous TXT record for leads to a buffer overflow in dnscrypt-proxy and gave an attacker RCE on sys-dns or sys-net. As root on sys-dns or sys-net an attacker could spoof all DNS answers, i.e. for HSTS aside, the same applies if dnsmasq or unbound on your router was vulnerable.

PS: I tried to get the nmcli radio wifi off in my NetworkManager.conf, but did not succeed. Ideas and links welcomed.

PPS: it might be better to keep and disable systemd-resolved instead of removing it


It seems reasonable to run dnscrypt-proxy as non-root and let the service listen on :53000 instead of :53. I’m going to fix that and will update my post - as soon as I find some time. Should be the listening port and the iptables rule only.

edit: ok, this is actually a lot easier. Edit /etc/dnscrypt-proxy/dnscrypt-proxy.toml in the template (i.e. fedora-35-minimal) you use for sys-net or sys-dns and remove the comment ‘#’ in line 55 so it reads:

user_name ='nobody'

After listening sockets have been created, dnscrypt-proxy drops it’s privileges and continues to run as nobody. Redirecting traffic from :53 to :53000 is too messy for me, since I lack profound iptables skills. For changing ports it looks to me one has to DNAT the traffic.

1 Like