[guide] how-to setup a sys-dns qube

@DVM, I remodified /rw/config/rc.local in f41-m-dns-dvm to have only one dnat line (the one with counter).

/rw/config/rc.local in sys-dns
#!/bin/sh

# 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.

nft='/usr/sbin/nft'

# allow redirects to localhost
/usr/sbin/sysctl -w net.ipv4.conf.all.route_localnet=1
"${nft}" add rule ip qubes custom-input meta l4proto { tcp, udp } iifgroup 2 ip daddr 127.0.0.1 th dport 53 accept

# block connections to other DNS servers
"${nft}" add rule ip qubes custom-forward meta l4proto { tcp, udp } iifgroup 2 ip daddr != 127.0.0.1 th dport 53 drop

"${nft}" flush chain ip qubes dnat-dns

"${nft}" add rule ip qubes dnat-dns meta l4proto { tcp, udp } th dport 53 counter dnat to 127.0.0.1

echo 'nameserver 127.0.0.1' > /etc/resolv.conf
# https://github.com/DNSCrypt/dnscrypt-proxy/wiki/Installation-linux
# https://wiki.archlinux.org/title/Dnscrypt-proxy#Enable_EDNS0
echo 'options edns0' >> /etc/resolv.conf

ln -s /rw/dnscrypt-proxy /etc/dnscrypt-proxy
/usr/bin/systemctl start dnscrypt-proxy.service

After shutting down f41-m-dns-dvm, I restarted sys-dns, and launched tcpdump, while running host gnu.org in an AppVM. Here are the results:

`tcpdump` Output in `sys-dns`:

bash-5.2# tcpdump -i any -vvv -n port 53

tcpdump: WARNING: any: That device doesn't support promiscuous mode

(Promiscuous mode not supported on the "any" device)

dropped privs to tcpdump

tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

09:23:51.034035 vif19.0 In IP (tos 0x0, ttl 64, id 47501, offset 0, flags [none], proto UDP (17), length 53)

10.137.0.18.43968 > 10.139.1.1.domain: [bad udp cksum 0x1659 -> 0x9f75!] 45926+ A? gnu.org. (25)

09:23:56.040615 vif19.0 In IP (tos 0x0, ttl 64, id 57026, offset 0, flags [none], proto UDP (17), length 53)

10.137.0.18.54072 > 10.139.1.1.domain: [bad udp cksum 0x1659 -> 0x77fd!] 45926+ A? gnu.org. (25)

09:24:01.047239 vif19.0 In IP (tos 0x0, ttl 64, id 39680, offset 0, flags [none], proto UDP (17), length 53)

10.137.0.18.35713 > 10.139.1.2.domain: [bad udp cksum 0x165a -> 0xbfb3!] 45926+ A? gnu.org. (25)

09:24:29.739134 vif19.0 In IP (tos 0x0, ttl 64, id 53097, offset 0, flags [none], proto UDP (17), length 53)

10.137.0.18.36249 > 10.138.31.106.domain: [bad udp cksum 0x34c1 -> 0xe6e3!] 27575+ A? gnu.org. (25)

09:24:34.745003 vif19.0 In IP (tos 0x0, ttl 64, id 28033, offset 0, flags [none], proto UDP (17), length 53)

10.137.0.18.52506 > 10.138.31.106.domain: [bad udp cksum 0x34c1 -> 0xa762!] 27575+ A? gnu.org. (25)

09:24:39.750500 vif19.0 In IP (tos 0x0, ttl 64, id 7020, offset 0, flags [none], proto UDP (17), length 53)

10.137.0.18.34288 > 10.138.31.106.domain: [bad udp cksum 0x34c1 -> 0xe8c!] 27575+ A? gnu.org. (25)

6 packets captured

6 packets received by filter

0 packets dropped by kernel

AppVM Terminal Output (`u1`):

[user@u1 ~]$ host gnu.org

;; communications error to 10.139.1.1#53: timed out

;; communications error to 10.139.1.1#53: timed out

;; communications error to 10.139.1.2#53: timed out

;; no servers could be reached

[user@u1 ~]$ ping -c 4 $(qubesdb-read /qubes-gateway)

PING 10.138.31.106 (10.138.31.106) 56(84) bytes of data.

64 bytes from 10.138.31.106: icmp_seq=1 ttl=64 time=1.22 ms

64 bytes from 10.138.31.106: icmp_seq=2 ttl=64 time=0.525 ms

64 bytes from 10.138.31.106: icmp_seq=3 ttl=64 time=0.527 ms

64 bytes from 10.138.31.106: icmp_seq=4 ttl=64 time=0.541 ms

--- 10.138.31.106 ping statistics ---

4 packets transmitted, 4 received, 0% packet loss, time 3071ms

rtt min/avg/max/mdev = 0.525/0.703/1.221/0.298 ms

[user@u1 ~]$ nslookup gnu.org $(qubesdb-read /qubes-gateway)

;; communications error to 10.138.31.106#53: timed out

;; communications error to 10.138.31.106#53: timed out

;; communications error to 10.138.31.106#53: timed out

;; no servers could be reached

`nft list table ip qubes` output
table ip qubes {
	set downstream {
		type ipv4_addr
		elements = { 10.137.0.18 }
	}

	set allowed {
		type ifname . ipv4_addr
		elements = { "vif19.0" . 10.137.0.18 }
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifgroup 2 goto antispoof
		ip saddr @downstream counter packets 0 bytes 0 drop
	}

	chain antispoof {
		iifname . ip saddr @allowed accept
		counter packets 0 bytes 0 drop
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifgroup 2 accept
		oif "lo" accept
		masquerade
	}

	chain input {
		type filter hook input priority filter; policy drop;
		jump custom-input
		ct state invalid counter packets 0 bytes 0 drop
		iifgroup 2 udp dport 68 counter packets 0 bytes 0 drop
		ct state established,related accept
		iifgroup 2 meta l4proto icmp accept
		iif "lo" accept
		iifgroup 2 counter packets 0 bytes 0 reject with icmp host-prohibited
		counter packets 0 bytes 0
	}

	chain forward {
		type filter hook forward priority filter; policy accept;
		jump custom-forward
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		oifgroup 2 counter packets 0 bytes 0 drop
	}

	chain custom-input {
		meta l4proto { tcp, udp } iifgroup 2 ip daddr 127.0.0.1 th dport 53 accept
	}

	chain custom-forward {
		meta l4proto { tcp, udp } iifgroup 2 ip daddr != 127.0.0.1 th dport 53 drop
	}

	chain dnat-dns {
		type nat hook prerouting priority dstnat; policy accept;
		meta l4proto { tcp, udp } th dport 53 counter packets 6 bytes 318 dnat to 127.0.0.1
	}
}

`nft list ruleset` output
table ip qubes {
	set downstream {
		type ipv4_addr
		elements = { 10.137.0.18 }
	}

	set allowed {
		type ifname . ipv4_addr
		elements = { "vif19.0" . 10.137.0.18 }
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifgroup 2 goto antispoof
		ip saddr @downstream counter packets 0 bytes 0 drop
	}

	chain antispoof {
		iifname . ip saddr @allowed accept
		counter packets 0 bytes 0 drop
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifgroup 2 accept
		oif "lo" accept
		masquerade
	}

	chain input {
		type filter hook input priority filter; policy drop;
		jump custom-input
		ct state invalid counter packets 0 bytes 0 drop
		iifgroup 2 udp dport 68 counter packets 0 bytes 0 drop
		ct state established,related accept
		iifgroup 2 meta l4proto icmp accept
		iif "lo" accept
		iifgroup 2 counter packets 0 bytes 0 reject with icmp host-prohibited
		counter packets 0 bytes 0
	}

	chain forward {
		type filter hook forward priority filter; policy accept;
		jump custom-forward
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		oifgroup 2 counter packets 0 bytes 0 drop
	}

	chain custom-input {
		meta l4proto { tcp, udp } iifgroup 2 ip daddr 127.0.0.1 th dport 53 accept
	}

	chain custom-forward {
		meta l4proto { tcp, udp } iifgroup 2 ip daddr != 127.0.0.1 th dport 53 drop
	}

	chain dnat-dns {
		type nat hook prerouting priority dstnat; policy accept;
		meta l4proto { tcp, udp } th dport 53 counter packets 6 bytes 318 dnat to 127.0.0.1
	}
}
table ip6 qubes {
	set downstream {
		type ipv6_addr
	}

	set allowed {
		type ifname . ipv6_addr
	}

	chain antispoof {
		iifname . ip6 saddr @allowed accept
		counter packets 12 bytes 768 drop
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifgroup 2 goto antispoof
		ip6 saddr @downstream counter packets 0 bytes 0 drop
	}

	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;
		oifgroup 2 accept
		oif "lo" accept
		masquerade
	}

	chain _icmpv6 {
		meta l4proto != ipv6-icmp counter packets 0 bytes 0 reject with icmpv6 admin-prohibited
		icmpv6 type { nd-router-advert, nd-redirect } counter packets 0 bytes 0 drop
		accept
	}

	chain input {
		type filter hook input priority filter; policy drop;
		jump custom-input
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		iifgroup 2 goto _icmpv6
		iif "lo" accept
		ip6 saddr fe80::/64 ip6 daddr fe80::/64 udp dport 546 accept
		meta l4proto ipv6-icmp accept
		counter packets 0 bytes 0
	}

	chain forward {
		type filter hook forward priority filter; policy accept;
		jump custom-forward
		ct state invalid counter packets 0 bytes 0 drop
		ct state established,related accept
		oifgroup 2 counter packets 0 bytes 0 drop
	}

	chain custom-input {
	}

	chain custom-forward {
	}
}
table ip qubes-firewall {
	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept
		iifname != "vif*" accept
		ip saddr 10.137.0.18 jump qbs-10-137-0-18
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
		iifname != "vif*" ip saddr { 10.137.0.18, 10.138.10.105 } drop
	}

	chain postrouting {
		type filter hook postrouting priority raw; policy accept;
		oifname != "vif*" ip daddr { 10.137.0.18, 10.138.10.105 } drop
	}

	chain qbs-10-137-0-18 {
		accept
		reject with icmp admin-prohibited
	}
}
table ip6 qubes-firewall {
	chain forward {
		type filter hook forward priority filter; policy drop;
		ct state established,related accept
		iifname != "vif*" accept
	}

	chain prerouting {
		type filter hook prerouting priority raw; policy accept;
	}

	chain postrouting {
		type filter hook postrouting priority raw; policy accept;
	}
}
table inet qubes-nat-accel {
	flowtable qubes-accel {
		hook ingress priority filter
		devices = { eth0, lo, vif19.0 }
	}

	chain qubes-accel {
		type filter hook forward priority filter + 5; policy accept;
		meta l4proto { tcp, udp } iifgroup 2 oifgroup 1 flow add @qubes-accel
		counter packets 0 bytes 0
	}
}

Now we can see in the nft outputs:

counter packets 6 bytes 318 dnat to 127.0.0.1

Why are you all having so many issues with something that is super easy to set up and get working?
It takes 30 minutes from boot to ISO to finish of configuration…

@Vael_S it is a good question that we are trying to answer.
Any suggestions?

One thing that caught my eye in your earlier nft rules: chain antispoor (not antispoof). That’s irrelevant to your current problem, just FYI.

Re. the main issue:

  • dnscrypt-proxy is running but not responding to queries.

If you are able to resolve names in sys-dns, then it is responding to queries. It seems packets are not forwarded correctly somewhere.

But let’s please clarify the actual task and problem. You say there is no DNS resolution in sys-wall. First, I would ask myself - is it necessary in sys-wall at all? The goal is to use it in client VMs, e.g. AppVMs.

Perhaps try this in sys-wall’s DVM template:

Remove any nft commands from /rw/config/rc.local and any other firewall customizations you may have.

Create an executable /rw/config/qubes-firewall.d/90-dnscrypt.nft:

#!/usr/sbin/nft -f

define sys_dns_addr = "IP address of your sys-dns qube"

define qubes_internal_ipv4_addr = {
        10.137.0.0/16,
        10.138.0.0/16
}

flush chain ip qubes custom-forward

add    chain ip qubes custom-dnat-dns
delete chain ip qubes custom-dnat-dns

table ip qubes {
        chain custom-forward {
                iifgroup 2 \
                        ip saddr $qubes_internal_ipv4_addr \
                        meta l4proto { tcp, udp } th dport 53 \
                        log prefix "[forward] " level debug \
                        accept
        }

        chain custom-dnat-dns {
                type nat hook prerouting priority dstnat - 1
                policy accept

                # Traffic not originating from the resolver goes to it
                iifgroup 2 \
                        ip saddr != $sys_dns_addr \
                        meta l4proto { tcp, udp } th dport 53 \
                        log prefix "[dnat] " level debug \
                        dnat to $sys_dns_addr
        }
}

Shutdown sys-wall’s DVM and sys-wall.
Create an AppVM which uses sys-wall as netvm.

After rebooting sys-wall, journalctl -f (as root) will show you what is actually happening in real time when you attempt DNS resolution. If everything works (i.e. if you have DNS resolution in the client AppVM), you can remove the lines starting with log. You can use similar logging in your sys-dns if you want.

Play with this, see what happens, and if it doesn’t work, post what the journal shows.

A few remarks:

I am not using DNSCrypt currently. Just trying to help.

FYI, you can also test if a service is reachable like this:

nc -zvw <seconds> <host> <port>

No need to post the output of nft list table ip qubes as nft list ruleset contains all tables.

@qubist thank you for your assistance.

I did all you suggested. host gnu.org in sys-wall still timed-out.

  1. I removed all the nft rules in rc.local in f41-m-firewall-dvm
  2. put your “90-dnscrypt.nft” script in /rw/config/qubes-firewall.d/90-dnscrypt.nft
  3. shut down the DVM.
  4. Launched journalctl -f in a restarted sys-wall,
  5. launched “nc -zvw 5 10.138.31.106 53” in another terminal of sys-wall.
nc -zvw 5 10.138.31.106 53 output
nc: Ncat: Version 7.92 (https://nmap.org/ncat) 
Ncat: TIMEOUT.
  1. Ran host gnu.org and ping commands. The result/are same as before
  2. Obtained outputs:
journalctl -f output for sys-wall
Mar 17 16:23:23 sys-wall audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=qubes-sync-time comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:23:23 sys-wall audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=qubes-sync-time comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:23:23 sys-wall kernel: kauditd_printk_skb: 184 callbacks suppressed
Mar 17 16:23:23 sys-wall kernel: audit: type=1130 audit(1742225003.696:126): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=qubes-sync-time comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:23:23 sys-wall kernel: audit: type=1131 audit(1742225003.696:127): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=qubes-sync-time comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:23:52 sys-wall systemd[1]: systemd-hostnamed.service: Deactivated successfully.
Mar 17 16:23:52 sys-wall audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-hostnamed comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:23:52 sys-wall kernel: audit: type=1131 audit(1742225032.514:128): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-hostnamed comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:23:52 sys-wall audit: BPF prog-id=35 op=UNLOAD
Mar 17 16:23:52 sys-wall kernel: audit: type=1334 audit(1742225032.541:129): prog-id=35 op=UNLOAD
Mar 17 16:24:17 sys-wall audit: BPF prog-id=37 op=UNLOAD
Mar 17 16:24:17 sys-wall audit: BPF prog-id=36 op=UNLOAD
Mar 17 16:24:17 sys-wall kernel: audit: type=1334 audit(1742225057.951:130): prog-id=37 op=UNLOAD
Mar 17 16:24:17 sys-wall kernel: audit: type=1334 audit(1742225057.951:131): prog-id=36 op=UNLOAD
Mar 17 16:24:17 sys-wall audit: BPF prog-id=54 op=LOAD
Mar 17 16:24:17 sys-wall kernel: audit: type=1334 audit(1742225057.952:132): prog-id=54 op=LOAD
Mar 17 16:24:17 sys-wall kernel: audit: type=1334 audit(1742225057.953:133): prog-id=55 op=LOAD
Mar 17 16:24:17 sys-wall kernel: audit: type=1334 audit(1742225057.953:134): prog-id=56 op=LOAD
Mar 17 16:24:17 sys-wall audit: BPF prog-id=55 op=LOAD
Mar 17 16:24:17 sys-wall audit: BPF prog-id=56 op=LOAD
Mar 17 16:24:17 sys-wall systemd[1]: Starting systemd-hostnamed.service - Hostname Service...
Mar 17 16:24:18 sys-wall systemd[1]: Started systemd-hostnamed.service - Hostname Service.
Mar 17 16:24:18 sys-wall audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-hostnamed comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:18 sys-wall kernel: audit: type=1130 audit(1742225058.016:135): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-hostnamed comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:18 sys-wall qrexec-agent[947]: 2025-03-17 16:24:18.086 qrexec-agent[947]: qrexec-agent-data.c:256:handle_new_process_common: executed: root:QUBESRPC qubes.VMShell dom0 (pid 949)
Mar 17 16:24:18 sys-wall audit[949]: USER_AUTH pid=949 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=pam_rootok acct="root" exe="/usr/lib/qubes/qrexec-agent" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:18 sys-wall kernel: audit: type=1100 audit(1742225058.090:136): pid=949 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=pam_rootok acct="root" exe="/usr/lib/qubes/qrexec-agent" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:18 sys-wall kernel: audit: type=1103 audit(1742225058.090:137): pid=949 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:setcred grantors=pam_rootok acct="root" exe="/usr/lib/qubes/qrexec-agent" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:18 sys-wall kernel: audit: type=1006 audit(1742225058.090:138): pid=949 uid=0 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=7 res=1
Mar 17 16:24:18 sys-wall kernel: audit: type=1300 audit(1742225058.090:138): arch=c000003e syscall=1 success=yes exit=1 a0=3 a1=7ffd801e2610 a2=1 a3=0 items=0 ppid=947 pid=949 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=7 comm="qrexec-agent" exe="/usr/lib/qubes/qrexec-agent" key=(null)
Mar 17 16:24:18 sys-wall audit[949]: CRED_ACQ pid=949 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:setcred grantors=pam_rootok acct="root" exe="/usr/lib/qubes/qrexec-agent" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:18 sys-wall audit[949]: SYSCALL arch=c000003e syscall=1 success=yes exit=1 a0=3 a1=7ffd801e2610 a2=1 a3=0 items=0 ppid=947 pid=949 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=7 comm="qrexec-agent" exe="/usr/lib/qubes/qrexec-agent" key=(null)
Mar 17 16:24:18 sys-wall audit: PROCTITLE proctitle="/usr/lib/qubes/qrexec-agent"
Mar 17 16:24:18 sys-wall systemd[1]: Started session-7.scope - Session 7 of User root.
Mar 17 16:24:18 sys-wall qrexec-agent[949]: pam_unix(qrexec:session): session opened for user root(uid=0) by root(uid=0)
Mar 17 16:24:18 sys-wall audit[949]: USER_START pid=949 uid=0 auid=0 ses=7 msg='op=PAM:session_open grantors=pam_selinux,pam_loginuid,pam_selinux,pam_keyinit,pam_limits,pam_systemd,pam_unix,pam_umask,pam_lastlog acct="root" exe="/usr/lib/qubes/qrexec-agent" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:48 sys-wall systemd[1]: systemd-hostnamed.service: Deactivated successfully.
Mar 17 16:24:48 sys-wall audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-hostnamed comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:48 sys-wall kernel: kauditd_printk_skb: 2 callbacks suppressed
Mar 17 16:24:48 sys-wall kernel: audit: type=1131 audit(1742225088.165:140): pid=1 uid=0 auid=4294967295 ses=4294967295 msg='unit=systemd-hostnamed comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'
Mar 17 16:24:48 sys-wall audit: BPF prog-id=54 op=UNLOAD
Mar 17 16:24:48 sys-wall kernel: audit: type=1334 audit(1742225088.193:141): prog-id=54 op=UNLOAD
Mar 17 16:29:03 sys-wall systemd[860]: Created slice background.slice - User Background Tasks Slice.
Mar 17 16:29:03 sys-wall systemd[619]: Created slice background.slice - User Background Tasks Slice.
Mar 17 16:29:03 sys-wall systemd[619]: Starting systemd-tmpfiles-clean.service - Cleanup of User's Temporary Files and Directories...
Mar 17 16:29:03 sys-wall systemd[1]: Starting qubes-update-check.service - Qubes check for VM updates and notify dom0...
Mar 17 16:29:03 sys-wall systemd[860]: Starting systemd-tmpfiles-clean.service - Cleanup of User's Temporary Files and Directories...
Mar 17 16:29:03 sys-wall systemd[619]: Finished systemd-tmpfiles-clean.service - Cleanup of User's Temporary Files and Directories.
Mar 17 16:29:03 sys-wall systemd[860]: Finished systemd-tmpfiles-clean.service - Cleanup of User's Temporary Files and Directories.
journalctl -f output for sys-dns

Mar 17 16:26:33 sys-dns systemd[1986]: Listening on dbus.socket - D-Bus User Message Bus Socket.
Mar 17 16:26:33 sys-dns systemd[1986]: Reached target sockets.target - Sockets.
Mar 17 16:26:33 sys-dns systemd[1986]: Reached target basic.target - Basic System.
Mar 17 16:26:33 sys-dns systemd[1986]: Reached target default.target - Main User Target.
Mar 17 16:26:33 sys-dns systemd[1986]: Startup finished in 218ms.
Mar 17 16:26:33 sys-dns systemd[1]: Started user@0.service - User Manager for UID 0.
Mar 17 16:26:33 sys-dns audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=user@0 comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:26:33 sys-dns systemd[1]: Started session-4.scope - Session 4 of User root.
Mar 17 16:26:33 sys-dns qrexec-agent[1983]: pam_unix(qrexec:session): session opened for user root(uid=0) by root(uid=0)
Mar 17 16:26:33 sys-dns audit[1983]: USER_START pid=1983 uid=0 auid=0 ses=4 msg=‘op=PAM:session_open grantors=pam_selinux,pam_loginuid,pam_selinux,pam_keyinit,pam_limits,pam_systemd,pam_unix,pam_umask,pam_lastlog acct=“root” exe=“/usr/lib/qubes/qrexec-agent” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:03 sys-dns systemd[1]: systemd-hostnamed.service: Deactivated successfully.
Mar 17 16:27:03 sys-dns audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=systemd-hostnamed comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:03 sys-dns kernel: kauditd_printk_skb: 100 callbacks suppressed
Mar 17 16:27:03 sys-dns kernel: audit: type=1131 audit(1742225223.853:201): pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=systemd-hostnamed comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:03 sys-dns audit: BPF prog-id=39 op=UNLOAD
Mar 17 16:27:03 sys-dns kernel: audit: type=1334 audit(1742225223.888:202): prog-id=39 op=UNLOAD
Mar 17 16:27:20 sys-dns audit: BPF prog-id=41 op=UNLOAD
Mar 17 16:27:20 sys-dns audit: BPF prog-id=40 op=UNLOAD
Mar 17 16:27:20 sys-dns kernel: audit: type=1334 audit(1742225240.627:203): prog-id=41 op=UNLOAD
Mar 17 16:27:20 sys-dns kernel: audit: type=1334 audit(1742225240.627:204): prog-id=40 op=UNLOAD
Mar 17 16:27:20 sys-dns kernel: audit: type=1334 audit(1742225240.628:205): prog-id=57 op=LOAD
Mar 17 16:27:20 sys-dns audit: BPF prog-id=57 op=LOAD
Mar 17 16:27:20 sys-dns audit: BPF prog-id=58 op=LOAD
Mar 17 16:27:20 sys-dns audit: BPF prog-id=59 op=LOAD
Mar 17 16:27:20 sys-dns kernel: audit: type=1334 audit(1742225240.629:206): prog-id=58 op=LOAD
Mar 17 16:27:20 sys-dns kernel: audit: type=1334 audit(1742225240.629:207): prog-id=59 op=LOAD
Mar 17 16:27:20 sys-dns systemd[1]: Starting systemd-hostnamed.service - Hostname Service…
Mar 17 16:27:20 sys-dns systemd[1]: Started systemd-hostnamed.service - Hostname Service.
Mar 17 16:27:20 sys-dns audit[1]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=systemd-hostnamed comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:20 sys-dns kernel: audit: type=1130 audit(1742225240.707:208): pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=systemd-hostnamed comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:20 sys-dns qrexec-agent[2067]: 2025-03-17 16:27:20.782 qrexec-agent[2067]: qrexec-agent-data.c:256:handle_new_process_common: executed: root:QUBESRPC qubes.VMShell dom0 (pid 2069)
Mar 17 16:27:20 sys-dns audit[2069]: USER_AUTH pid=2069 uid=0 auid=4294967295 ses=4294967295 msg=‘op=PAM:authentication grantors=pam_rootok acct=“root” exe=“/usr/lib/qubes/qrexec-agent” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:20 sys-dns audit[2069]: CRED_ACQ pid=2069 uid=0 auid=4294967295 ses=4294967295 msg=‘op=PAM:setcred grantors=pam_rootok acct=“root” exe=“/usr/lib/qubes/qrexec-agent” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:20 sys-dns audit[2069]: SYSCALL arch=c000003e syscall=1 success=yes exit=1 a0=3 a1=7ffc7ae96e90 a2=1 a3=0 items=0 ppid=2067 pid=2069 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=6 comm=“qrexec-agent” exe=“/usr/lib/qubes/qrexec-agent” key=(null)
Mar 17 16:27:20 sys-dns kernel: audit: type=1100 audit(1742225240.786:209): pid=2069 uid=0 auid=4294967295 ses=4294967295 msg=‘op=PAM:authentication grantors=pam_rootok acct=“root” exe=“/usr/lib/qubes/qrexec-agent” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:20 sys-dns kernel: audit: type=1103 audit(1742225240.786:210): pid=2069 uid=0 auid=4294967295 ses=4294967295 msg=‘op=PAM:setcred grantors=pam_rootok acct=“root” exe=“/usr/lib/qubes/qrexec-agent” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:20 sys-dns kernel: audit: type=1006 audit(1742225240.786:211): pid=2069 uid=0 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=6 res=1
Mar 17 16:27:20 sys-dns kernel: audit: type=1300 audit(1742225240.786:211): arch=c000003e syscall=1 success=yes exit=1 a0=3 a1=7ffc7ae96e90 a2=1 a3=0 items=0 ppid=2067 pid=2069 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=6 comm=“qrexec-agent” exe=“/usr/lib/qubes/qrexec-agent” key=(null)
Mar 17 16:27:20 sys-dns audit: PROCTITLE proctitle=“/usr/lib/qubes/qrexec-agent”
Mar 17 16:27:20 sys-dns systemd[1]: Started session-6.scope - Session 6 of User root.
Mar 17 16:27:20 sys-dns qrexec-agent[2069]: pam_unix(qrexec:session): session opened for user root(uid=0) by root(uid=0)
Mar 17 16:27:20 sys-dns audit[2069]: USER_START pid=2069 uid=0 auid=0 ses=6 msg=‘op=PAM:session_open grantors=pam_selinux,pam_loginuid,pam_selinux,pam_keyinit,pam_limits,pam_systemd,pam_unix,pam_umask,pam_lastlog acct=“root” exe=“/usr/lib/qubes/qrexec-agent” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:50 sys-dns systemd[1]: systemd-hostnamed.service: Deactivated successfully.
Mar 17 16:27:50 sys-dns audit[1]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=systemd-hostnamed comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:50 sys-dns kernel: kauditd_printk_skb: 2 callbacks suppressed
Mar 17 16:27:50 sys-dns kernel: audit: type=1131 audit(1742225270.863:213): pid=1 uid=0 auid=4294967295 ses=4294967295 msg=‘unit=systemd-hostnamed comm=“systemd” exe=“/usr/lib/systemd/systemd” hostname=? addr=? terminal=? res=success’
Mar 17 16:27:50 sys-dns audit: BPF prog-id=57 op=UNLOAD
Mar 17 16:27:50 sys-dns kernel: audit: type=1334 audit(1742225270.899:214): prog-id=57 op=UNLOAD

nft list ruleset output for sys-wall

table ip qubes {
set downstream {
type ipv4_addr
}

set allowed {
	type ifname . ipv4_addr
}

chain prerouting {
	type filter hook prerouting priority raw; policy accept;
	iifgroup 2 goto antispoof
	ip saddr @downstream counter packets 0 bytes 0 drop
}

chain antispoof {
	iifname . ip saddr @allowed accept
	counter packets 0 bytes 0 drop
}

chain postrouting {
	type nat hook postrouting priority srcnat; policy accept;
	oifgroup 2 accept
	oif "lo" accept
	masquerade
}

chain input {
	type filter hook input priority filter; policy drop;
	jump custom-input
	ct state invalid counter packets 0 bytes 0 drop
	iifgroup 2 udp dport 68 counter packets 0 bytes 0 drop
	ct state established,related accept
	iifgroup 2 meta l4proto icmp accept
	iif "lo" accept
	iifgroup 2 counter packets 0 bytes 0 reject with icmp host-prohibited
	counter packets 5 bytes 260
}

chain forward {
	type filter hook forward priority filter; policy accept;
	jump custom-forward
	ct state invalid counter packets 0 bytes 0 drop
	ct state established,related accept
	oifgroup 2 counter packets 0 bytes 0 drop
}

chain custom-input {
}

chain custom-forward {
}

chain dnat-dns {
	type nat hook prerouting priority dstnat; policy accept;
	ip daddr 10.139.1.1 udp dport 53 dnat to 10.139.1.1
	ip daddr 10.139.1.1 tcp dport 53 dnat to 10.139.1.1
	ip daddr 10.139.1.2 udp dport 53 dnat to 10.139.1.2
	ip daddr 10.139.1.2 tcp dport 53 dnat to 10.139.1.2
}

}
table ip6 qubes {
set downstream {
type ipv6_addr
}

set allowed {
	type ifname . ipv6_addr
}

chain antispoof {
	iifname . ip6 saddr @allowed accept
	counter packets 0 bytes 0 drop
}

chain prerouting {
	type filter hook prerouting priority raw; policy accept;
	iifgroup 2 goto antispoof
	ip6 saddr @downstream counter packets 0 bytes 0 drop
}

chain postrouting {
	type nat hook postrouting priority srcnat; policy accept;
	oifgroup 2 accept
	oif "lo" accept
	masquerade
}

chain _icmpv6 {
	meta l4proto != ipv6-icmp counter packets 0 bytes 0 reject with icmpv6 admin-prohibited
	icmpv6 type { nd-router-advert, nd-redirect } counter packets 0 bytes 0 drop
	accept
}

chain input {
	type filter hook input priority filter; policy drop;
	jump custom-input
	ct state invalid counter packets 0 bytes 0 drop
	ct state established,related accept
	iifgroup 2 goto _icmpv6
	iif "lo" accept
	ip6 saddr fe80::/64 ip6 daddr fe80::/64 udp dport 546 accept
	meta l4proto ipv6-icmp accept
	counter packets 0 bytes 0
}

chain forward {
	type filter hook forward priority filter; policy accept;
	jump custom-forward
	ct state invalid counter packets 0 bytes 0 drop
	ct state established,related accept
	oifgroup 2 counter packets 0 bytes 0 drop
}

chain custom-input {
}

chain custom-forward {
}

}
table ip qubes-firewall {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname != “vif*” accept
}

chain prerouting {
	type filter hook prerouting priority raw; policy accept;
	iifname != "vif*" ip saddr 10.137.0.18 drop
}

chain postrouting {
	type filter hook postrouting priority raw; policy accept;
	oifname != "vif*" ip daddr 10.137.0.18 drop
}

}
table ip6 qubes-firewall {
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
iifname != “vif*” accept
}

chain prerouting {
	type filter hook prerouting priority raw; policy accept;
}

chain postrouting {
	type filter hook postrouting priority raw; policy accept;
}

}

  1. put your “90-dnscrypt.nft” script in /rw/config/qubes-firewall.d/90-dnscrypt.nft

Did you make it executable? I don’t see the rules in your output and I don’t see any logging, which suggest it has not run. If you don’t see these rules in nft list ruleset, there is no point to test anything. Check if qubes-firewall service is enabled and running. Also make sure that IP forwarding is enabled:

https://linuxconfig.org/how-to-turn-on-off-ip-forwarding-in-linux

Watch journal in sys-wall - this is what you are working on.

  1. Ran host gnu.org and ping commands. The result/are same as before

Do this in an AppVM. You need to test the forward chain. Sending packets from sys-wall is output, not forward.

@qubist thank you very much, finally, it works!

host gnu.org in u1 (AppVM) succeeds with sys-wall.

Previously, it timed out with sys-dns as netvm, but now it works with sys-dns too.

I applied the script only in f41-m-firewall-dvm.
Is the script have broader impact?

@qubist Curious—what are you using instead of DNSCrypt? You’ve created quite a suspense!

@qubist out of curiosity, I reverted to using the DVM’s script in /rw/config/rc.local, deleted your 90-dnscrypt.nft, and tested host gnu.org in u2 with sys-dns as netv. Initially timed out, but then resolved:

[user@u2 ~]$ host gnu.org
;; communications error to 10.139.1.1#53: timed out
;; communications error to 10.139.1.1#53: timed out
gnu.org has address 209.51.188.116
gnu.org mail is handled by 10 eggs.gnu.org.
[user@u2 ~]$ host gnu.org
gnu.org has address 209.51.188.116
gnu.org has IPv6 address 2001:470:142:5::116
gnu.org mail is handled by 10 eggs.gnu.org.

Previously, it timed out with sys-dns, maybe I didn’t wait long enough.
Anyways, thank you @qubist @DVM! I learned a lot.

To set up a sys-dns cache guest on the PC for different guest connections?

@qubist thank you very much, finally, it works!

Great.

Is the script have broader impact?

I don’t understand your question.

@qubist Curious—what are you using instead of DNSCrypt?

Traditional DNS. I have started working on an improved sys-dns setup but paused that work due to other work… and so it stayed for months. Some day I will complete and hopefully share that here.

@qubist out of curiosity, I reverted to using the DVM’s script in /rw/config/rc.local, deleted your 90-dnscrypt.nft, and tested host gnu.org in u2 with sys-dns as netv.

rc.local runs after network is up, i.e. before it has completed there is a short time during which leaks are possible. /rw/config/qubes-firewall.d/* runs before n it, and that is more correct for a firewall:

user@rdisp3147:~ > systemctl cat qubes-firewall.service
# /lib/systemd/system/qubes-firewall.service
[Unit]
Description=Qubes firewall updater
ConditionPathExists=/var/run/qubes-service/qubes-firewall
After=qubes-iptables.service
Before=qubes-network.service

[Service]
Type=notify
ExecStart=/usr/bin/qubes-firewall

[Install]
WantedBy=multi-user.target
1 Like