@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