Skip to content

Fix container DNS resolution by expanding loopback access control to 127.0.0.0/8#623

Merged
klutchell merged 2 commits into
mainfrom
copilot/fix-5825db73-0a6f-4eed-8461-e9f939fd9940
Sep 29, 2025
Merged

Fix container DNS resolution by expanding loopback access control to 127.0.0.0/8#623
klutchell merged 2 commits into
mainfrom
copilot/fix-5825db73-0a6f-4eed-8461-e9f939fd9940

Conversation

Copilot AI commented Sep 29, 2025

Copy link
Copy Markdown
Contributor

Problem

Containers are unable to resolve hostnames when unbound binds to all interfaces (0.0.0.0:53), but DNS resolution works when binding to a specific IP address like 192.168.0.100:53. This affects users running unbound in Docker environments where containers need to perform DNS lookups.

Root Cause

The issue occurs because Docker's DNS forwarding mechanism can make container DNS requests appear to originate from various IP addresses within the 127.0.0.0/8 loopback range, not just 127.0.0.1. The current access control rule:

access-control: 127.0.0.1/32 allow

Only allows the specific localhost IP address (127.0.0.1), causing requests from other loopback IPs to be denied by unbound's access control.

Solution

This PR expands the loopback access control from the restrictive /32 (single IP) to /8 (entire loopback range):

- access-control: 127.0.0.1/32 allow
+ access-control: 127.0.0.0/8 allow

Security Considerations

  • The 127.0.0.0/8 range is the complete IPv4 loopback block defined in RFC 3330
  • This change maintains the same security posture - still localhost-only with no external network exposure
  • This approach is already shown as the recommended configuration in unbound.conf.example
  • Standard practice in unbound deployments that need to handle Docker container traffic

Testing

Users can verify the fix by:

  1. Running unbound with port binding to all interfaces: -p 53:53/tcp -p 53:53/udp
  2. Starting a test container on the same network
  3. Performing DNS lookups from within the container (e.g., nslookup google.com)
  4. Confirming that DNS resolution now works without needing to bind to a specific IP

Fixes the issue described where containers could only resolve other container names but not external hostnames.

Original prompt

This section details on the original issue you should resolve

<issue_title>Unable to resolve hostnames from within containers.</issue_title>
<issue_description>I have this image running on a machine (192.168.0.100) in my local network and configured my router's DHCP server to hand out 192.168.0.100 as being the DNS server.
Everything works fine, all my machines (including the host running docker) are able to perform lookups EXCEPT the apps running in other docker containers! I can only do lookups for other container names e.g.: If i have a docker-compose.yml with an app and db service, doing ping appfrom the db container, and vice versa, works fine. Trying to lookup anything else fails.

If I change my docker-compose.yml for the unbound container from:

    ports:
      - 53:53/tcp
      - 53:53/udp

to

    ports:
      - 53:53/tcp
      - 192.168.0.100:53:53/udp

Lookups start working again inside containers. I'm not sure why. It's fine for now but I'd really like to avoid having to hard code the ip address of the docker host in my docker-compose.yml file.

Any insights as to what might be causing this behavior?
</issue_description>

Comments on the Issue (you are @copilot in this section)

@klutchell Are you by any chance blocking 3rd party DNS at your gateway? Asking because the default DNS for docker containers is usually 8.8.8.8. This can be set [on the daemon](https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-dns-options), or [per container](https://docs.docker.com/compose/compose-file/compose-file-v3/#dns). @klutchell Thinking about your two tests...
    ports:
      - 53:53/tcp
      - 53:53/udp

In this case 0.0.0.0:53:53 is implied and docker will attempt to bind to all interfaces on the host.

    ports:
      - 53:53/tcp
      - 192.168.0.100:53:53/udp

Unclear why limiting the binding to a single interface like this would allow lookups from other containers.

Are all other containers on the same network as unbound? You said some of them were, but doesn't it make a difference if they aren't? What if they use host networking?

Maybe what's happening is the internal docker network in your case needs to be added to the access control list here?

The docker host is forwarding the lookup to unbound but the source IP of the container is not on the control list? I would think that forwarded DNS lookups would not contain the original source IP but worth investigating I guess.</comment_new>
<comment_new>@klutchell

I don't really understand why everything works fine for devices on my LAN when binding to all interfaces though, those replies magically pick the right interface/source address?

I'm a bit out of my depth at this point, but wouldn't that be because LAN devices are not using the moby DNS forwarding and instead speak directly to unbound on the interface?</comment_new>
<comment_new>@klutchell
Nice find, I think we can make that change to the 127.0.0.0/8 loopback range for access control in the default config.</comment_new>

Fixes #204

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

@klutchell

Copy link
Copy Markdown
Owner

@copilot we found the root cause already, the fix should be to change the access control line 127.0.0.1/32 allow to 127.0.0.0/8 allow in the default config

Co-authored-by: klutchell <20458272+klutchell@users.noreply.github.com>
@klutchell klutchell marked this pull request as ready for review September 29, 2025 18:37
Copilot AI changed the title [WIP] Unable to resolve hostnames from within containers. Fix container DNS resolution by expanding loopback access control to 127.0.0.0/8 Sep 29, 2025
Copilot AI requested a review from klutchell September 29, 2025 18:37

Copilot AI commented Sep 29, 2025

Copy link
Copy Markdown
Contributor Author

@copilot we found the root cause already, the fix should be to change the access control line 127.0.0.1/32 allow to 127.0.0.0/8 allow in the default config

The fix has been implemented in commit b7dbdd8. Changed access-control: 127.0.0.1/32 allow to access-control: 127.0.0.0/8 allow in rootfs_overlay/etc/unbound/unbound.conf as requested.

@klutchell klutchell merged commit b386aca into main Sep 29, 2025
54 of 100 checks passed
@klutchell klutchell deleted the copilot/fix-5825db73-0a6f-4eed-8461-e9f939fd9940 branch September 29, 2025 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to resolve hostnames from within containers.

2 participants