This isn't a new topic, many people do it already. You can google and see for yourself, but I'm doing a bit more

I run a local domain at home (example.casa) , and also I run a local domain in my laptop (example.lap), for the vm/containers/lxc I run.

The problem with unbound is that it will fail to validate example.lap and example.casa and when I use my laptop at Jhon's it will fail to validate jhon.casa domain

The solution for this is to whitelist the domain example.lap all the time, and parse the local domain on the network am I and whitelist it too (this domain will change on every network)

I configure dnsmasq to publish DNS on the port 5353 and answer DHCP requests on br0

dnsmasq.conf

port=5353
no-resolv
local=/example.lap/
interface=br0
bind-interfaces
domain=example.lap
dhcp-range=192.168.250.150,192.168.250.155,1m
dhcp-leasefile=/run/dnsmasq/dnsmasq.leases

unbound is configured to listen on my br0 iface

/etc/unbound/unbound.conf.d/local.conf

server:
        interface: 127.0.0.1
        interface: ::1
        interface: 192.168.250.1
        access-control: 127.0.0.1 allow
        access-control: ::1 allow
        access-control: 192.168.250.0/24 allow

I tell unbound to trust example.lap and forward its queries to dnsmasq

/etc/unbound/unbound.conf.d/example.lap.conf

server:
    do-not-query-localhost: no
    private-domain: "example.lap."
    domain-insecure: "example.lap."
    private-domain: "250.168.192.in-addr.arpa."
    domain-insecure: "250.168.192.in-addr.arpa."
    local-zone: "250.168.192.in-addr.arpa" transparent

    forward-zone:
            name: "example.lap."
            forward-addr: 127.0.0.1@5353

    forward-zone:
            name: "250.168.192.in-addr.arpa."
            forward-addr: 127.0.0.1@5353

Here I tell isc-dhcp-client to setup the forwarding for the local domain in unbound and disable DNSSEC for it

/etc/dhcp/dhclient-exit-hooks.d/dns-bound

#!/bin/sh
case $reason in
        "BOUND")
                unbound-control forward_add +i $new_domain_name $new_domain_name_servers
                ;;
        "RELEASE")
                unbound-control forward_remove +i $old_domain_name
                ;;
esac

The last piece is the cherry of the cake and the weakest link in the chain

I'm parsing untrusted data, and feeding it to my local resolver

Someone could pass .com as local domain and I'd be effectively disabling DNSSEC for all .com domains :o

I tried to use psl to handle what domains cannot be registered and only allow those but any domain I used/can think of can be registered now

$ psl .corp
.corp: 1
$ psl .casa
.casa: 1
$ psl .local
.local: 1 **WTF**

useless, I wont use it :(

I'll be careful after connecting to unstrusted networks, I don't care much as a simple

# service unbound restart

will clean the forward zones

There is a command, unbound-control forward_remove.... but I won't remember that command tomorrow :P

It wont work on IPv6 only networks

I'm only using DHCP IPv4 events (BOUND,RELEASE), so the DNS servers exposed and the domain names configured over IPv6 only won't get configured,

I think can live with that :), I don't think I'll live long enough to see local IPv6 only networks, I'm not even sure they make sense (I may be wrong on that point, but I think I'm right)

Anyway, it is just an start, and I finally could ditch systemd-networkd/systemd-resolved :)