Infrastructure Series -- Recursive DNS and Adblocking DNS over TLS w/NGINX

before we get started. i am using docker for pihole and not unbound. if this is an issue let me know.

Its not you just have to understound your routing, your firewall rules. What you open the pihole to and what you dont… etc.

Docker MASQ’s in IPTables.

I have a similar setup on my edge setup where the pihole is within a docker but I had to rejigger a couple of things to make it work

Modem >> ASUS ROUTER + Network Switch >>> old macbook pro running ubuntu server >>> Docker PIhole…

All of my devices connect to the asus router/network switch.

I have dns pointed towards pihole and it works. When I do anything with unbound it gets fucky. works for like a minute then stops.

  GNU nano 4.8                                                                                     /etc/unbound/unbound.conf.d/pi-hole.conf                                                                                               
    harden-dnssec-stripped: yes

    # Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes
    # see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details
    use-caps-for-id: no

    # Reduce EDNS reassembly buffer size.
    # IP fragmentation is unreliable on the Internet today, and can cause
    # transmission failures when large DNS messages are sent via UDP. Even
    # when fragmentation does work, it may not be secure; it is theoretically
    # possible to spoof parts of a fragmented DNS message, without easy
    # detection at the receiving end. Recently, there was an excellent study
    # >>> Defragmenting DNS - Determining the optimal maximum UDP response size for DNS <<<
    # by Axel Koolhaas, and Tjeerd Slokker (https://indico.dns-oarc.net/event/36/contributions/776/)
    # in collaboration with NLnet Labs explored DNS using real world data from the
    # the RIPE Atlas probes and the researchers suggested different values for
    # IPv4 and IPv6 and in different scenarios. They advise that servers should
    # be configured to limit DNS messages sent over UDP to a size that will not
    # trigger fragmentation on typical network links. DNS servers can switch
    # from UDP to TCP when a DNS response is too big to fit in this limited
    # buffer size. This value has also been suggested in DNS Flag Day 2020.
    edns-buffer-size: 1232

    # Perform prefetching of close to expired message cache entries
    # This only applies to domains that have been frequently queried
    prefetch: yes

    # One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads>
    num-threads: 2

    # Ensure kernel buffer is large enough to not lose messages in traffic spikes
    so-rcvbuf: 1m

    # Ensure privacy of local IP ranges
    private-address: 192.168.0.0/16
    private-address: 169.254.0.0/16
    private-address: 172.16.0.0/12
    private-address: 10.0.0.0/8
    private-address: fd00::/8
    private-address: fe80::/10

    root-hints: "/etc/unbound/root.hints"
    forward-zone:
    name: "."
    forward-addr: 1.1.1.1
    forward-addr: 8.8.8.8


here is my unbound pihole config.

Also I use UFW as firewall for all my devices and ASUS has a built in firewall as well.

Okay so I expect you to understand these and work with them.

Now a question for you. What is your expectation with unbound and what are you trying to use it for? Recursion/recursive resolver or what?

Recursion

Im going to give you my unbound configuration

## Unbound Configuration for Recursive Resolve
# Version: Red Hat 20210502

# SERVER BLOCK

server:

# Initial Configuration and Ports
	logfile: "/var/log/unbound/unbound.log" # Define log location
	username: "unbound"
	directory: "/etc/unbound"
	log-time-ascii: yes
	pidfile: "/var/run/unbound/unbound.pid"
	verbosity: 3
	interface: 0.0.0.0
	interface: ::0 # Define if you want to answer IPv6 requests
	access-control: 172.0.0.0/8 allow
	access-control: 10.0.0.0/8 allow
	access-control: 192.0.0.0/8 allow
	access-control: 2001:DB8::/64 allow
	port: 19235 
	statistics-interval: 0
	statistics-cumulative: no
	extended-statistics: yes
	interface-automatic: no
	outgoing-port-permit: 32768-60999
	outgoing-port-avoid: 0-32767
	outgoing-port-avoid: 61000-65535
	include: /etc/unbound/local.d/*.conf
	tls-ciphers: "PROFILE=SYSTEM"
	ip-transparent: yes
	edns-tcp-keepalive: yes
	chroot: ""

# IP4/6 TCP/UDP Configuration
	do-ip4: yes
	do-udp: yes
	do-tcp: yes
	do-ip6: yes # Enable but not prefer if 6 is a capability on the network (i.e 6in4)
	prefer-ip6: yes # Only enable if on NATIVE IPV6 Stack
	so-reuseport: yes
	max-udp-size: 3072
	udp-upstream-without-downstream: yes

# Root Hints 
	root-hints: "/etc/unbound/root.hints" # Top level root servers file
    
# Hardened Resolution
	harden-short-bufsize: yes
	harden-large-queries: yes
	harden-glue: yes
	harden-dnssec-stripped: yes
	harden-below-nxdomain: yes
	harden-referral-path: yes
	target-fetch-policy: "0 0 0 0 0" # Emulate Bind 9
	harden-algo-downgrade: no
	trusted-keys-file: /etc/unbound/keys.d/*.key
	auto-trust-anchor-file: "/var/lib/unbound/root.key"
	use-caps-for-id: no # Set no if you plan to use DNSSEC
	edns-buffer-size: 1472 # Set MTU of network
	hide-identity: yes
	hide-version: yes
	qname-minimisation: yes
	aggressive-nsec: yes
	unwanted-reply-threshold: 10000000
	deny-any: no
	rrset-roundrobin: yes
	minimal-responses: yes
	module-config: "validator iterator"
	root-key-sentinel: yes
	val-clean-additional: yes
	val-permissive-mode: no
	val-log-level: 2
	trust-anchor-signaling: yes
	prefetch-key: yes

# Optimizations
	prefetch: yes
	cache-min-ttl: 0
	serve-expired: yes
	serve-expired-ttl: 14400
	so-reuseport: yes
	msg-cache-slabs: 8
	rrset-cache-slabs: 8
	infra-cache-slabs: 8
	key-cache-slabs: 8
	outgoing-range: 4096
	msg-cache-size: 256m
	rrset-cache-size: 512m
	num-threads: 4
	so-rcvbuf: 8m
	so-sndbuf: 8m

# Other parameters
	private-address: 192.168.0.0/16
	private-address: 169.254.0.0/16
	private-address: 172.16.0.0/12
	private-address: 10.0.0.0/8
	private-address: fd00::/8
	private-address: fe80::/10

# Remote Control
remote-control:
	control-enable: yes
	control-use-cert: "no"
	# unbound server key file.
	server-key-file: "/etc/unbound/unbound_server.key"
	# unbound server certificate file.
	server-cert-file: "/etc/unbound/unbound_server.pem"
	# unbound-control key file.
	control-key-file: "/etc/unbound/unbound_control.key"
	# unbound-control certificate file.
	control-cert-file: "/etc/unbound/unbound_control.pem"


This is my setup for recursion

This is tweaked for the device BUT… you cant have a forward zone in your unbound because thats not what you are using it for.

You need to read the documentation on what these do: NLnet Labs Documentation - Unbound - unbound.conf.5

Your issue is you are configuring unbound wrong. It needs to be recursive not forwarding. Additionally if you have a dual stack configuration I keep my DNS resolvers both pihole and Unbound running on both 0.0.0.0 and ::0 which is answering all but the firewall protects them from answering anything they should not.

Once you have figured that out. If you are running the docker on the same system; you must tweak the docker configuration to prevent some isolation that can get in the way of stuff. As in you need to configure its network

networks:
  pihole:
    driver: bridge
    ipam:
      config:
        - subnet: <CIDR>
          gateway: <docker_gateway_IP>
          aux_addresses:
            pihole: <docker_pihole_IP>

make sure your docker configuration can use port 53:

    cap_add:
      - NET_ADMIN

and

make sure your container configuration has the following under the docker compose service profile:

    restart: always
    networks:
      - pihole

and

    ports:
      - '<DNS port remap for NGINX socket>:53/tcp'
      - '<DNS port remap for NGINX socket>:53/udp'
      - '<port 67 remap>:67/udp'
      - '<Web interface remap port>:80/tcp'
1 Like

So I realize everything I just gave you is a lot. Take some time; look it over. Reverse your steps. Figure out where you are at and see what you might have left out?

If its not the DNS server thats the issue and its your router you will need to find someone experienced with ASUS wrt. I dont know it well anymore as I use prosumer products or netgear (w/OpenWRT).

I suspect though the router shouldnt have an issue redirecting DNS to the pihole even if it does the normal consumer router thing which is to use DNSMasq to use itself as another cache (annoying but fine)

My wiki’s are not up to date with a lot of my recent changes. Its hard to know what to update and what not to. What will be useful information to people and what is not

1 Like

I will get this done
but for now i need rest. I was messing with this since yesterday even. Have had not sleep since yesterday morning. 30+ hours baby!

1 Like

So this is a hobby application/home lab.

You should not be sacrificing personal health for it. Go to sleep. Resume on a rested mind

when you diagnose. Lets use some known responses to make sure lookups are getting through properly. These will not change save the DNSSEC Keys (per my policy but I know what they should be)

So what you will do to perform them as checks is
dig +multi +dnssec @(your server IP) < MY-TLD >.net {LOOKUP TYPE CODE}

A Lookup:

dig +multi +dnssec @< MY-TLD >.net < MY-TLD >.net A

; <<>> DiG 9.16.25 <<>> +multi +dnssec @< MY-TLD >.net < MY-TLD >.net A
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39617
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1472
;; QUESTION SECTION:
;< MY-TLD >.net.		IN A

;; ANSWER SECTION:
< MY-TLD >.net.		269 IN A 192.53.120.164
< MY-TLD >.net.		269 IN RRSIG A 14 2 300 (
				20220212142757 20220128142720 5704 < MY-TLD >.net.
				4MKyixMJcZvf/n7KHcmkF40dgzUhtHuP/lZwJDi65fzL
				TK1BujAhm0iV8Al7vnxJyW0NyjFZ0JXICkbOisjU0Lim
				NxS8TuMDx7kLyAi17GqcgFMXRoyeBVJkmgLGXS5q )

;; Query time: 56 msec
;; SERVER: 2600:3c04::f03c:92ff:fec6:2030#53(2600:3c04::f03c:92ff:fec6:2030)
;; WHEN: Sat Feb 05 17:01:04 MST 2022
;; MSG SIZE  rcvd: 197


AAAA Lookup:

dig +multi +dnssec @< MY-TLD >.net < MY-TLD >.net AAAA

; <<>> DiG 9.16.25 <<>> +multi +dnssec @< MY-TLD >.net < MY-TLD >.net AAAA
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13684
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1472
;; QUESTION SECTION:
;< MY-TLD >.net.		IN AAAA

;; ANSWER SECTION:
< MY-TLD >.net.		82 IN AAAA 2600:3c04::f03c:92ff:fec6:2030
< MY-TLD >.net.		82 IN RRSIG AAAA 14 2 300 (
				20220212155339 20220128150353 5704 < MY-TLD >.net.
				bIPSlOcjosAZkAmxoJZsB7f/Dv0U2hSR4e+yWT/BoeIn
				QKrRjqrbg7HuQ+/VWZqDi8Y7D7EB2WLRhzuxDJMDO4Hh
				2aDOJeaeqq/bo47BVKHpEb4UyCLtFGvIWvmWz/Jo )

;; Query time: 65 msec
;; SERVER: 2600:3c04::f03c:92ff:fec6:2030#53(2600:3c04::f03c:92ff:fec6:2030)
;; WHEN: Sat Feb 05 16:46:45 MST 2022
;; MSG SIZE  rcvd: 209


NSEC Bad Lookup: (TLSA is low hanging fruit since its port TXT lookup specific)

dig +multi +dnssec @< MY-TLD >.net < MY-TLD >.net TLSA

; <<>> DiG 9.16.25 <<>> +multi +dnssec @< MY-TLD >.net < MY-TLD >.net TLSA
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4755
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1472
;; QUESTION SECTION:
;< MY-TLD >.net.		IN TLSA

;; AUTHORITY SECTION:
< MY-TLD >.net.		300 IN SOA ns1.< MY-TLD >.net. hostmaster.< MY-TLD >.net. (
				2022012246 ; serial
				3600       ; refresh (1 hour)
				900        ; retry (15 minutes)
				7200       ; expire (2 hours)
				3600       ; minimum (1 hour)
				)
< MY-TLD >.net.		300 IN RRSIG SOA 14 2 300 (
				20220220012127 20220205002127 5704 < MY-TLD >.net.
				3NMFc6Q0AaoK589bc3ZtM04TNxJXff6mPINdp/W9xO+T
				wC5oq59+oeuLD3hZjge5Ocj0tu3qW82flY3dbszpamMd
				Xh9VjGR9tvxyJkKe1J4C4lOk96A5Rn+4twU97oRg )
< MY-TLD >.net.		300 IN NSEC *.< MY-TLD >.net. A NS SOA TXT AAAA SSHFP RRSIG NSEC DNSKEY CDS CDNSKEY HTTPS CAA TYPE65534
< MY-TLD >.net.		300 IN RRSIG NSEC 14 2 300 (
				20220219030852 20220204021142 5704 < MY-TLD >.net.
				01xb8DKXZqy0vxumMsb1dF6CLLPtJlkORJa3c0tArfvW
				SociD1vFU1vFD5hxncnASy88jnqq0hxoYSJA7Ux4rwIF
				eKjQXp2Bpilt9b53KUvnm9D6SvPnyDrkHP1ZCI3W )

;; Query time: 120 msec
;; SERVER: 2600:3c04::f03c:92ff:fec6:2030#53(2600:3c04::f03c:92ff:fec6:2030)
;; WHEN: Sat Feb 05 17:00:37 MST 2022
;; MSG SIZE  rcvd: 448

  • Note an NSEC or NSEC3 bad lookup return should not return status: ERROR etc. It should still be no error. Otherwise your resolver is reading my servers proper response incorrectly.

Additionally because its recursive:

dig

; <<>> DiG 9.16.25 <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32500
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1472
;; QUESTION SECTION:
;.				IN	NS

;; ANSWER SECTION:
.			83993	IN	NS	g.root-servers.net.
.			83993	IN	NS	m.root-servers.net.
.			83993	IN	NS	f.root-servers.net.
.			83993	IN	NS	e.root-servers.net.
.			83993	IN	NS	h.root-servers.net.
.			83993	IN	NS	l.root-servers.net.
.			83993	IN	NS	i.root-servers.net.
.			83993	IN	NS	a.root-servers.net.
.			83993	IN	NS	d.root-servers.net.
.			83993	IN	NS	c.root-servers.net.
.			83993	IN	NS	b.root-servers.net.
.			83993	IN	NS	j.root-servers.net.
.			83993	IN	NS	k.root-servers.net.

;; Query time: 78 msec
;; SERVER: 192.53.120.164#53(192.53.120.164)
;; WHEN: Sat Feb 05 17:09:37 MST 2022
;; MSG SIZE  rcvd: 239

That should be your answer to just a dig of root on your network (with your IP in for the server)

If your outputs match including the flags then everything is going well. If its not or its not being answered by your server IP then you are in forwarding mode or something else is wrong.

Let me know if I can provide any tools that can help you. Without more specifics this is all I can give

I will start with non hardened. I took a melotonin an hour ago and feel wide awake… Do you have advice for a non hardened unbound?

1 Like

Yeah because your mind is spinning over the DNS server haha. Melatonin cant put your mind to rest :stuck_out_tongue:

Anyways you should probably pass out or at the very least grab a few hours

Omit the Hardened parts of my configuration (which has comments) and DNSSEC parts of my configuration and its not hardened? Not sure what you are asking?

I got it working mudda fucka! Just out of curiosity, would my dns on dnsleaktest be my isp ip address?

1 Like

No lol

I dont have it going to linode though. for me it is going to my isp. i have not gotten that far yet. before i was struggling with getting unbound and pihole to even be friendly with each other. now to tackle linode.

my domain is not working at present. but it is working!

1 Like

So you should setup rDNS on linode properly

And get your URL working as well

1 Like

I didn’t see how you did that in the tutorial. But yea it works fine now. SRV record got it.

1 Like

no

PTR is rDNS

SRV and TXT are different.

I did not publish how to do rDNS because linode handles it in their interface.

LOL them DDoS be displayed

1 Like

it is appearing as it should! congrats!