klutchell/unbound-docker

Custom port being ignored since update to v1.19.1

Closed this issue ยท 25 comments

I use unbound with PiHole, therefore I have a custom .conf file specifying port 5335 for use by unbound. This has been working without issue. However, since updating the docker container from unbound version 1.19.0 to 1.19.1 at the weekend the custom port is ignored and unbound fails to start due to not being able to bind port 53.

Specifying v1.19.0 in the docker compose file rather than latest has my setup back running as before.

Can you share the relevant bits of your custom.conf and how you are mounting it?

It sounds similar to the same issue we discussed here so I would suggest reading through that thread for suggestions as well.

Thank you for your quick response. Apologies for missing that previously closed issue. It is interesting to read in your linked thread that the order of interface and port is important - this could be my issue (as you can see below, I specify port after interface), I will have play around after work.

The top of my custom .conf file:

server:
verbosity: 0

interface: 127.0.0.1
port: 5335

do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
prefer-ip6: yes

My docker-compose.yml:

unbound:
    container_name: unbound
    image: klutchell/unbound
    hostname: unbound
    network_mode: "host"
    volumes:
      - ./unbound.d:/etc/unbound/custom.conf.d
    restart: 'unless-stopped'

I still can't get this to work. However, I now suspect that it is an issue with my Docker setup as Pi-Hole is no longer saving to or reading from config files either (I hadn't realised this until I updated the container yesterday).

I will investigate this.

Apologies for the noise.

I just wanted to report that I stumbled upon the same issue. I have a similar setup with pi-hole behind unbound, though bound together with a podman pod rather than docker-compose. Upgrading the unbound container to 1.19.1, I hit the same issue where unbound suddenly began binding to port 53. Here is all of my custom config:

server:
    port: 5354

# RFC 8806
auth-zone:
    name: "."
    master: "b.root-servers.net"
    master: "c.root-servers.net"
    master: "d.root-servers.net"
    master: "f.root-servers.net"
    master: "g.root-servers.net"
    master: "k.root-servers.net"
    fallback-enabled: yes
    for-downstream: no
    for-upstream: yes
    url: "https://www.internic.net/domain/root.zone"
    zonefile: "root.zone"

The idea is to have unbound only run on 127.0.0.1, port 5354

Downgrading the container to 1.19.0 fixes the issue.

Reading through #221, the suggested change for 1.19.1 is to use the interface directive. So I changed it to the following:

server:
    interface: 127.0.0.1@5354

# rest of config see above

While this makes unbound open a listening socket on 127.0.0.1:5354, it keeps 0.0.0.0:53 open as well, which I don't want as it conflicts with pi-hole:

# ss -tuln
Netid            State             Recv-Q            Send-Q                       Local Address:Port                       Peer Address:Port           Process
udp              UNCONN            0                 0                                  0.0.0.0:53                              0.0.0.0:*
udp              UNCONN            0                 0                                127.0.0.1:5354                            0.0.0.0:*
tcp              LISTEN            0                 256                              127.0.0.1:5354                            0.0.0.0:*
tcp              LISTEN            0                 256                                0.0.0.0:53                              0.0.0.0:*

If I'm reading this comment correctly, then there is no way to stop unbound from listening on 0.0.0.0 (and port 53) via the custom config file. Is there another workaround?

Yes, it seems that interface is additive, in that you can specify additional interfaces but you cannot remove existing ones (not with config inheritance anyway).

Perhaps there is a middle ground if we do not specify a port: in the default config and only provide interface: 0.0.0.0 like we had before. This might satisfy the most use cases but it would need to be tested to see what happens if port remains unset, and if a new value for port is provided in the custom config.

This might be the best move, just avoid providing a port in the default config so it can be overridden easily. Port 53 is implied if not provided, and is used in conjunction with interface: 0.0.0.0.

Could you try running klutchell/unbound:build-kyle-custom-ports and see if it works for your setup?

Maybe @SimonInOps and @klmcwhirter could give it a try too?

tl;dr with the above PR a custom config should only need the port: directive to use a custom port, and the default port 53 will not bind

For me the image klutchell/unbound:build-kyle-custom-ports:

  1. Is NOT working with single config entry - port
server:
    port: 5354

This still makes unbound run under 53.


  1. Checked different configs:
server:
    interface: 0.0.0.0@5354

AND

server:
    port: 5354
    interface: 0.0.0.0

That creates unbound under the 5354 port, but still binds port 53, so not sure if it solves the problem above.
So basically behavior is the same as for the release image.

Thanks for checking @SimonInOps , can you also add verbosity: 2 and observe the container start logs?

In my case it clearly prints which interfaces it is listening on.

custom conf I'm using

server-1  | [1709317252] unbound[1:0] notice: Start of unbound 1.19.1.
server-1  | [1709317252] unbound[1:0] debug: creating udp4 socket 0.0.0.0 5353
server-1  | [1709317252] unbound[1:0] debug: creating tcp4 socket 0.0.0.0 5353
server-1  | [1709317252] unbound[1:0] debug: chdir to /var/unbound
server-1  | [1709317252] unbound[1:0] debug: drop user privileges, run as unbound
server-1  | [1709317252] unbound[1:0] debug: switching log to stderr
server-1  | [1709317252] unbound[1:0] debug: module config: "subnetcache

Pulled new docker image and now everything looks as described.

unbound_test  | [1709324260] unbound[1:0] debug: creating udp4 socket 0.0.0.0 5353
unbound_test  | [1709324260] unbound[1:0] debug: creating tcp4 socket 0.0.0.0 5353
unbound_test  | [1709324261] unbound[1:0] debug: chdir to /var/unbound
docker exec unbound_test drill -p 5353 dnssec.works @127.0.0.1
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 16342
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

*Increased verbosity to a bigger number, then socket info indeed appeared.


Configuration

port: 5353
port: 5353
interface: 0.0.0.0

Creates single port โœ…


โŒ

interface: 0.0.0.0@5353

Creates 53 and 5353ports

great, thank you! will wait for some others to weigh in but the former config should be the way to go

@SimonInOps

[snip]

Ignore what I said here. See advise below.

I'm seeing different behaviour in my tests with klutchell/unbound:build-kyle-custom-ports

/etc/unbound/unbound.conf

server:
    interface: 0.0.0.0

/etc/unbound/custom.conf.d/custom-port.conf

server:
    port: 5353
    verbosity: 2
server-1  | [1709317252] unbound[1:0] notice: Start of unbound 1.19.1.
server-1  | [1709317252] unbound[1:0] debug: creating udp4 socket 0.0.0.0 5353
server-1  | [1709317252] unbound[1:0] debug: creating tcp4 socket 0.0.0.0 5353
server-1  | [1709317252] unbound[1:0] debug: chdir to /var/unbound
server-1  | [1709317252] unbound[1:0] debug: drop user privileges, run as unbound
server-1  | [1709317252] unbound[1:0] debug: switching log to stderr
server-1  | [1709317252] unbound[1:0] debug: module config: "subnetcache

The entire test is automated here if anyone can see an error in the steps I'm taking.

@klmcwhirter can you confirm you pulled the latest klutchell/unbound:build-kyle-custom-ports for these tests?

I pulled :latest just now. The other issue was tested with 1.19.0.

Would you like me to test :build-kyle-custom-ports ?

I could do that after lunch date with my wife ...

Would you like me to test :build-kyle-custom-ports ?

yes please, I haven't merged the change so if you can test it that would be great

OK - I'm back. What would you like me to test? My standard setup is to replace the whole config.

Did you want me to test the custom-conf changes you made in that branch?

Yeah! If you don't mind trying a config override and the new development image tag like I did here: #350 (comment)

I appreciate it! I think it solves your original issue in a way you don't need to provide the whole config file.

OK.
Tested my stock setup - still works - using klutchell/unbound:build-kyle-custom-ports.

Created a new docker-compose.yml without my config. So vanilla klutchell/unbound:build-kyle-custom-ports with custom-ports.conf in place.

Binds to port 5353 as implemented. nlnetlabs must have changed something ... I confirm.

$ docker exec -t dns-test-unbound-1 dig -p 5353 'dnssec.works' '@172.28.0.2'
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 22193
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; dnssec.works.	IN	A

;; ANSWER SECTION:
dnssec.works.	3207	IN	A	5.45.107.88

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 0 msec
;; SERVER: 172.28.0.2
;; WHEN: Sat Mar  2 00:17:06 2024
;; MSG SIZE  rcvd: 46

Does NOT respond to port 53.

$ docker exec -t dns-test-unbound-1 dig -p 53 'dnssec.works' '@172.28.0.2'
Error: error sending query: Could not send or receive, because of network error

Inside pi-hole Query Log:

2024-03-01 16:30:30 	A	github.com	ZenWiFi_XD4-69B0.lan	OK (answered by dns-unbound-1.dns_backplane#5353)	IP (79.7ms)

They didn't change anything. The difference with that development tag is the default config file I include with this image no longer includes the port: 53 option and it's simply implied by the unbound process, unless of course you provide an override file.

So this is the ideal behaviour I think. Custom configs with port: will work as expected, and no chance of accidentally still listening on the default port as well as the desired port.

I am confused. I juist noticed I am not seeing these lines from your log output:

server-1  | [1709317252] unbound[1:0] debug: creating udp4 socket 0.0.0.0 5353
server-1  | [1709317252] unbound[1:0] debug: creating tcp4 socket 0.0.0.0 5353
server-1  | [1709317252] unbound[1:0] debug: chdir to /var/unbound
server-1  | [1709317252] unbound[1:0] debug: drop user privileges, run as unbound
server-1  | [1709317252] unbound[1:0] debug: switching log to stderr
server-1  | [1709317252] unbound[1:0] debug: module config: "subnetcache

Let me ratchet up verbosity some more ...

EDIT:
strange with verbosity 3 I see the last 4 lines but not the creating lines.

I definitely need verbosity 3 to see debug log messages. Keep in mind I am running on Rasberry Pi 4B's.

But verbosity is not the issue.

Good job!

verbosity: 2 worked for me

The main tag now has the changes above for those in need.

Can confirm:

server:
    port: 5354

works using tag main. Though unbound will always be listening on 0.0.0.0 now. I guess it's fine as it's confined to a network namespace and I see why it was necessary to implement as per #221.

Thanks, this fixed it for me as well while I had issues with 1.19.0 ... 1.19.2 works perfectly again.