DNScrypt-proxy qube. sys-dns with Encrypted DNS
1. Install dnscrypt-proxy in the fedora-xfce template:
sudo dnf install -y dnscrypt-proxy
sudo systemctl enable dnscrypt-proxy
2. Add dnscrypt-proxy configuration in fedora-xfce template:
This setup enables DNSCrypt with anonymized DNS (via relays), enforces DNSSEC, no-logging, and no-filter policies, and disables DoH and Oblivious DoH:
sudo tee /etc/dnscrypt-proxy/dnscrypt-proxy.toml << 'EOF'
server_names = []
listen_addresses = ['127.0.0.1:53', '0.0.0.0:53', '[::1]:53']
max_clients = 250
ipv4_servers = true
ipv6_servers = false
dnscrypt_servers = true
doh_servers = false
odoh_servers = false
require_dnssec = true
require_nolog = true
require_nofilter = true
disabled_server_names = ['scaleway', 'scaleway-ams']
force_tcp = false
timeout = 5000
keepalive = 30
cert_refresh_delay = 240
bootstrap_resolvers = ['9.9.9.11:53', '8.8.8.8:53']
ignore_system_dns = true
log_files_max_size = 10
log_files_max_age = 7
log_files_max_backups = 1
block_ipv6 = false
block_unqualified = true
block_undelegated = true
reject_ttl = 10
cache = true
cache_size = 4096
cache_min_ttl = 2400
cache_max_ttl = 86400
cache_neg_min_ttl = 60
cache_neg_max_ttl = 600
lb_strategy = 'wp2'
lb_estimator = true
[sources.public-resolvers]
urls = [
'https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md';,
'https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md';,
'https://cdn.jsdelivr.net/gh/DNSCrypt/dnscrypt-resolvers@master/v3/public-resolvers.md';
]
cache_file = 'public-resolvers.md'
minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
refresh_delay = 73
prefix = ''
[sources.relays]
urls = [
'https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/relays.md';,
'https://download.dnscrypt.info/resolvers-list/v3/relays.md';,
'https://cdn.jsdelivr.net/gh/DNSCrypt/dnscrypt-resolvers@master/v3/relays.md';
]
cache_file = 'relays.md'
minisign_key = 'RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3'
refresh_delay = 73
prefix = ''
[anonymized_dns]
routes = [
{ server_name='*', via=['anon-scaleway', 'anon-scaleway-ams', 'anon-kama', 'anon-tiarap'] }
]
skip_incompatible = true
EOF
Note: The 10.139.1.1 and 10.139.1.2 addresses are the standard Qubes OS DNS IPs assigned to downstream VMs. Binding to 0.0.0.0:53 ensures dnscrypt-proxy can accept queries on these interfaces.
3. Create and configure sys-dns qube:
Create fedora-based AppVM sys-dns and add option Provides network in Qube Manager (advansed settings)
The next commands are executed in the sys-dns terminal.
4. Disable systemd-resolved in sys-dns:
sudo tee /rw/config/rc.local << 'EOF'
#!/bin/bash
# Disable systemd-resolved to free up port 53
systemctl stop systemd-resolved 2>/dev/null
systemctl disable systemd-resolved 2>/dev/null
systemctl mask systemd-resolved 2>/dev/null
systemctl stop systemd-resolved-varlink.socket 2>/dev/null
systemctl disable systemd-resolved-varlink.socket 2>/dev/null
systemctl mask systemd-resolved-varlink.socket 2>/dev/null
systemctl stop systemd-resolved-monitor.socket 2>/dev/null
systemctl disable systemd-resolved-monitor.socket 2>/dev/null
systemctl mask systemd-resolved-monitor.socket 2>/dev/null
# Assign Qubes standard DNS IPs to eth0 for downstream VMs
# These IPs are dynamically provided to downstream qubes via Qubes mechanisms
ip addr add 10.139.1.1/32 dev eth0 2>/dev/null
ip addr add 10.139.1.2/32 dev eth0 2>/dev/null
# start dnscrypt-proxy (let's add it just in case)
systemctl start dnscrypt-proxy
EOF
5. Configure nftables (Accept Rules for DNS) in sys-dns:
sudo tee /rw/config/qubes-firewall-user-script << 'EOF'
#!/bin/bash
# Allow DNS queries from downstream qubes to 10.139.1.1/2
# vif* are interfaces for downstream qubes, group 2
nft add rule ip qubes custom-input iifgroup 2 ip daddr { 10.139.1.1, 10.139.1.2 } udp dport 53 accept 2>/dev/null
nft add rule ip qubes custom-input iifgroup 2 ip daddr { 10.139.1.1, 10.139.1.2 } tcp dport 53 accept 2>/dev/null
EOF
Restart sys-dns to apply all changes.
