Unbound + pi-hole connection refused but works for most domains

Creating a bug report/issue

I have searched the existing open and closed issues

Required Information

  • DietPi version:
G_DIETPI_VERSION_CORE=9
G_DIETPI_VERSION_SUB=4
G_DIETPI_VERSION_RC=2
G_GITBRANCH='master'
G_GITOWNER='MichaIng'
G_LIVE_PATCH_STATUS[0]='not applicable'
  • Distro version: bookworm 0
  • Kernel version: Linux DietPi 6.6.28+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.6.28-1+rpt1 (2024-04-22) aarch64 GNU/Linux
  • Architecture: arm64
  • SBC model: RPi 5 Model B (aarch64)
  • Power supply used: Raspberry Pi 27W USB-C PSU
  • SD card used | Samsung EVO+ 128 GB MicroSD

Additional Information (if applicable)

  • Software title | pi-hole + unbound
  • Was the software title installed freshly or updated/migrated?
  • Can this issue be replicated on a fresh installation of DietPi? Yes

Steps to reproduce

  1. Fresh install of DietPi + any updates available on 1st boot on Apr 29.
  2. Use dietpi-software to install pi-hole and unbound using defaults from the installation

Expected behaviour

  • All domains should be resolved/blocked based on pi-hole ad lists

Actual behaviour

  • Most domains work fine but starting May 13 one domain, nzb.su, returns SERVFAIL. Also even domains that resolve have the error communications error to ::1#5335: connection refused

Extra details

dietpi@DietPi:/etc/systemd$ dig @localhost -p 5335 a nzb.su
;; communications error to ::1#5335: connection refused
;; communications error to ::1#5335: connection refused
;; communications error to ::1#5335: connection refused
;; communications error to 127.0.0.1#5335: timed out

; <<>> DiG 9.18.24-1-Debian <<>> @localhost -p 5335 a nzb.su
; (2 servers found)
;; global options: +cmd
;; no servers could be reached

sudo /usr/sbin/unbound -ddd -vvv -c /etc/unbound/unbound.conf while the above dig command was executed:

dietpi@DietPi:/etc/systemd$ dig @localhost -p 5335 a www.instagram.com
;; communications error to ::1#5335: connection refused
;; communications error to ::1#5335: connection refused
;; communications error to ::1#5335: connection refused

; <<>> DiG 9.18.24-1-Debian <<>> @localhost -p 5335 a www.instagram.com
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5076
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;www.instagram.com.             IN      A

;; ANSWER SECTION:
www.instagram.com.      3600    IN      CNAME   z-p42-instagram.c10r.instagram.com.
z-p42-instagram.c10r.instagram.com. 300 IN A    31.13.65.174

;; Query time: 176 msec
;; SERVER: 127.0.0.1#5335(localhost) (UDP)
;; WHEN: Fri May 31 11:34:08 EDT 2024
;; MSG SIZE  rcvd: 97

Output of sudo /usr/sbin/unbound -ddd -vvv -c /etc/unbound/unbound.conf while the above dig command was executed:

dietpi@DietPi:~$ dig +noall +comments @127.0.0.1 -p 5335 sigfail.verteiltesysteme.net
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 36534
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232

dietpi@DietPi:~$ dig +noall +comments +answer @127.0.0.1 -p 5335 sigok.verteiltesysteme.net
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11497
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; ANSWER SECTION:
sigok.verteiltesysteme.net. 1799 IN     CNAME   sigok.rsa2048-sha256.ippacket.stream.
sigok.rsa2048-sha256.ippacket.stream. 300 IN A  195.201.14.36
dietpi@DietPi:/etc/systemd$ sudo netstat -nltup | grep -E ':53 |unbound|dnsmasq'
tcp        0      0 0.0.0.0:53              0.0.0.0:*               LISTEN      1590/pihole-FTL
tcp        0      0 127.0.0.1:5335          0.0.0.0:*               LISTEN      2756/unbound
tcp6       0      0 :::53                   :::*                    LISTEN      1590/pihole-FTL
udp        0      0 127.0.0.1:5335          0.0.0.0:*                           2756/unbound
udp        0      0 0.0.0.0:53              0.0.0.0:*                           1590/pihole-FTL
udp6       0      0 :::53                   :::*                                1590/pihole-FTL

Since most domains work as seen with my instagram.com example, I didn’t know about the communications error to ::1#5335: connection refused error. I noticed it only today when I tried to track down why nzb.su kept failing even though it was green in pi-hole.

I’ve provided all of the information I thought to include after reading many other troubleshooting posts. Any idea what I should try next? In the meantime I’ve turned off the unbound DNS in pi-hole and configured it to use Google. I’d like to go back to unbound if possible.

Have you made any changes to the unbound conf file?

No I haven’t. Here’s the file /etc/unbound/unbound.conf.d/dietpi.conf:

# https://nlnetlabs.nl/documentation/unbound/unbound.conf/
server:
        # Do not daemonize, to allow proper systemd service control and status estimation.
        do-daemonize: no

        # A single thread is pretty sufficient for home or small office instances.
        num-threads: 1

        # Logging: For the sake of privacy and performance, keep logging at a minimum!
        # - Verbosity 2 and up practically contains query and reply logs.
        verbosity: 0
        log-queries: no
        log-replies: no
        # - If required, uncomment to log to a file, else logs are available via "journalctl -u unbound".
        #logfile: "/var/log/unbound.log"

        # Set interface to "0.0.0.0" to make Unbound listen on all network interfaces.
        # Set it to "127.0.0.1" to listen on requests from the same machine only, useful in combination with Pi-hole.
        interface: 127.0.0.1
        # Default DNS port is "53". When used with Pi-hole, set this to e.g. "5335", since "5353" is used by mDNS already.
        port: 5335

        # Control IP ranges which should be able to use this Unbound instance.
        # The DietPi defaults permit access from official local network IP ranges only, hence requests from www are denied.
        access-control: 0.0.0.0/0 refuse
        access-control: 10.0.0.0/8 allow
        access-control: 127.0.0.1/8 allow
        access-control: 172.16.0.0/12 allow
        access-control: 192.168.0.0/16 allow
        access-control: ::/0 refuse
        access-control: ::1/128 allow
        access-control: fd00::/8 allow
        access-control: fe80::/10 allow

        # Private IP ranges, which shall never be returned or forwarded as public DNS response.
        # NB: 127.0.0.1/8 is sometimes used by adblock lists, hence DietPi by default allows those as response.
        private-address: 10.0.0.0/8
        private-address: 172.16.0.0/12
        private-address: 192.168.0.0/16
        private-address: 169.254.0.0/16
        private-address: fd00::/8
        private-address: fe80::/10

        # Define protocols for connections to and from Unbound.
        # NB: Disabling IPv6 does not disable IPv6 IP resolving, which depends on the clients request.
        do-udp: yes
        do-tcp: yes
        do-ip4: yes
        do-ip6: no

        # DNS root server information file. Updated monthly via cron job: /etc/cron.monthly/dietpi-unbound
        root-hints: "/var/lib/unbound/root.hints"

        # Maximum number of queries per second
        ratelimit: 1000

        # Defend against and print warning when reaching unwanted reply limit.
        unwanted-reply-threshold: 10000

        # Set EDNS reassembly buffer size to match new upstream default, as of DNS Flag Day 2020 recommendation.
        edns-buffer-size: 1232

        # Increase incoming and outgoing query buffer size to cover traffic peaks.
        so-rcvbuf: 4m
        so-sndbuf: 4m

        # Hardening
        harden-glue: yes
        harden-dnssec-stripped: yes
        harden-algo-downgrade: yes
        harden-large-queries: yes
        harden-short-bufsize: yes

        # Privacy
        use-caps-for-id: yes # Spoof protection by randomising capitalisation
        rrset-roundrobin: yes
        qname-minimisation: yes
        minimal-responses: yes
        hide-identity: yes
        identity: "Server" # Purposefully a dummy identity name
        hide-version: yes

        # Caching
        cache-min-ttl: 300
        cache-max-ttl: 86400
        serve-expired: yes
        neg-cache-size: 4M
        prefetch: yes
        prefetch-key: yes
        msg-cache-size: 50m
        rrset-cache-size: 100m

Are you using IPv6?

I think it tries also to contact localhost via IPv6, but localhost has no IPv6 address assigned to?

Also can you do

dig @localhost -p 5335 a nzb.su

and

dig nzb.su @8.8.8.8

for comparison.

The servfail can also come from a failing DNSSEC validation.

Nope, according configuration as well as netstat, Unbound is listen to IPv4 only. Which is pritty much ok. No need to have Unbound running on IPv6

For testing, I would use dig @127.0.0.1 instead of dig @localhost

Basically that’s make a difference :slight_smile:

root@DietPiProd:~# dig dietpi.com @localhost -p 5335
;; communications error to ::1#5335: connection refused
;; communications error to ::1#5335: connection refused
;; communications error to ::1#5335: connection refused

; <<>> DiG 9.18.24-1-Debian <<>> dietpi.com @localhost -p 5335
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35564
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

vs

root@DietPiProd:~# dig dietpi.com @127.0.0.1 -p 5335

; <<>> DiG 9.18.24-1-Debian <<>> dietpi.com @127.0.0.1 -p 5335
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14753
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

Thanks for the replies. I substituted 127.0.0.1 for localhost, but still can’t reach the one site. It works fine with Google DNS enabled in pi-hole, but not with unbound:

dietpi@DietPi:/etc/systemd$ dig @127.0.0.1 -p 5335 a nzb.su                                                ;; communications error to 127.0.0.1#5335: timed out
;; communications error to 127.0.0.1#5335: timed out
;; communications error to 127.0.0.1#5335: timed out

; <<>> DiG 9.18.24-1-Debian <<>> @127.0.0.1 -p 5335 a nzb.su
; (1 server found)
;; global options: +cmd
;; no servers could be reached

Meanwhile instagram still works, indicating it’s not a global issue:

dietpi@DietPi:/etc/systemd$ dig @127.0.0.1 -p 5335 a instagram.com

; <<>> DiG 9.18.24-1-Debian <<>> @127.0.0.1 -p 5335 a instagram.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10622
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;instagram.com.                 IN      A

;; ANSWER SECTION:
instagram.com.          300     IN      A       31.13.65.174

;; Query time: 72 msec
;; SERVER: 127.0.0.1#5335(127.0.0.1) (UDP)
;; WHEN: Sat Jun 01 18:14:36 EDT 2024
;; MSG SIZE  rcvd: 58

dig query without specifying unbound (currently using 8.8.8.8 in pi-hole:

dietpi@DietPi:/etc/systemd$ dig a nzb.su

; <<>> DiG 9.18.24-1-Debian <<>> a nzb.su
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33425
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;nzb.su.                                IN      A

;; ANSWER SECTION:
nzb.su.                 1800    IN      A       209.208.67.181

;; Query time: 152 msec
;; SERVER: 192.168.99.5#53(192.168.99.5) (UDP)
;; WHEN: Sat Jun 01 18:17:17 EDT 2024
;; MSG SIZE  rcvd: 51

This behavior is strange. Why should dig not be able to reach unbound for a certain domain? dig doesn’t really care. And unbound is not even reached here.

Theoretically, you could now try to create a trace at packet level with tcpdump

tcpdump -i any -c500 -nn port 5335 or port 53

I will try this when I can. Unfortunately I just discovered I didn’t properly setup Rustdesk for outside access, and now I can’t access the machine until next week when I get home. :disappointed:

Another option would be using a VPN :smiley: But yeah, need to be configured before leaving home :wink:

Thankfully I was able to remotely correct my Rustdesk installation (that’s a different post) and connect to the machine. I had one window running unbound with the debug flags as shown above, one running the tcpdump command, and in the third I made the same two queries just to keep it as standard as possible. The dig queries for nzb.su and instagram were the same as above, and I will not repost them.

I trimmed as much other data from the tcpdump as I could and pasted it here: Partial tcpdump - Pastebin.com. I have a lot of devices and there were many other queries mixed in with my two requests. The general format of the nzb.su queries was like this:

10:21:57.150178 lo    In  IP 127.0.0.1.46326 > 127.0.0.1.5335: UDP, length 47
10:21:57.150478 eth0  Out IP 192.168.99.5.58653 > 198.41.0.4.53: 57790% [1au] A? Su. (31)
10:21:57.179816 eth0  In  IP 198.41.0.4.53 > 192.168.99.5.58653: 57790- 0/7/11 (678)
10:21:57.180047 eth0  Out IP 192.168.99.5.56247 > 193.232.128.6.53: 11322% [1au] A? NZB.su. (35)
10:21:57.180072 eth0  Out IP 192.168.99.5.57331 > 193.232.156.17.53: 33763% [1au] DNSKEY? su. (31)
10:21:57.556490 eth0  Out IP 192.168.99.5.36482 > 193.232.128.6.53: 38047% [1au] A? NzB.SU. (35)
10:21:57.556522 eth0  Out IP 192.168.99.5.51604 > 193.232.156.17.53: 45474% [1au] DNSKEY? Su. (31)

Interestingly, after the nzb.su dig query timed out and after the successful instagram query, it was still trying to reach nzb.su. I couldn’t read the remote text well enough and didn’t realize this until after I hit ctrl-c to break the tcpdump and then pasted the results into notepad. These final lines indicate it was still working on nzb.su even though it looked to me as though the query had already failed:

10:22:19.759263 eth0  Out IP 192.168.99.5.18899 > 194.85.252.62.53: 40878% [1au] A? Nzb.SU. (35)
10:22:19.759297 eth0  Out IP 192.168.99.5.23240 > 193.232.156.17.53: 45046% [1au] A? nzb.su. (35)
10:22:21.256843 eth0  Out IP 192.168.99.5.17313 > 193.232.156.17.53: 55548% [1au] DNSKEY? su. (31)
10:22:22.770563 eth0  Out IP 192.168.99.5.24883 > 194.190.124.17.53: 42102% [1au] A? nzb.su. (35)
10:22:22.770586 eth0  Out IP 192.168.99.5.8029 > 193.232.128.6.53: 26490% [1au] A? nzb.su. (35)

I’ve also included the full tcpdump output here in case you find I accidentally trimmed out something important: Full TCP dump - Pastebin.com

Does any of this help?