AdguardTeam / AdGuardHome

Network-wide ads & trackers blocking DNS server
https://adguard.com/adguard-home/overview.html
GNU General Public License v3.0
25.57k stars 1.84k forks source link

Docker Containers can connect to AdGuard GUI but Unable to Resolve via host IP #6442

Open jschwalbe opened 12 months ago

jschwalbe commented 12 months ago

Prerequisites

Platform (OS and CPU architecture)

Linux, AMD64 (aka x86_64)

Installation

Docker

Setup

On one machine

AdGuard Home version

v0.107.41

Action

Please bear with me on this. It's a confusing issue.

First of all, adguard docker-compose.yml:

version: "3.9"
services:
  adguardhome:
    image: adguard/adguardhome
    container_name: adguardhome
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 3000:3000/tcp
      - 3001:80/tcp
      - 3002:8902/tcp
    volumes:
      - ./conf:/opt/adguardhome/conf
      - ./data:/opt/adguardhome/work
    restart: always
    network_mode: bridge

Pretty vanilla setup.

The host IP here is 192.168.25.81.


user@192.168.25.81$ nslookup google.com 192.168.25.81
<success>

# now try to resolve from another docker container:
user@192.168.25.81:~/docker-configs/mosquitto$ docker compose exec mosquitto nslookup google.com 192.168.25.81
;; connection timed out; no servers could be reached

# however, the adguard container can still be reached on different ports.. why is that??
user@192.168.25.81:~/docker-configs/mosquitto$ docker compose exec mosquitto wget 192.168.25.81:3001 -O -
Connecting to 192.168.25.81:3001 (192.168.25.81:3001)
writing to stdout
<!doctype html><html lang="en"><head><meta charset="utf-8"><me.... (snip)

### Expected result

I should be able to use the host IP to resolve from other containers. Since it can connect to the GUI, why can't it connect to the DNS server on port 53?

### Actual result

See above. Thank you!

### Additional information and/or screenshots

_No response_
jschwalbe commented 12 months ago

I'll even add that from within the adguard container itself, the above is also true.. (just realized this)

user@192.168.25.81$ docker compose exec adguardhome nslookup google.com 192.168.25.81
;; connection timed out; no servers could be reached

user@192.168.25.81$ docker compose exec adguardhome wget 192.168.25.81:3001 -O- -
Connecting to 192.168.25.81:3001 (192.168.25.81:3001)
writing to stdout
<!doctype html><html lang="en"><head> ...
ainar-g commented 12 months ago

As far as I know there is an internal address for containers, usually within 172.17.0.0/16 subnet. See https://docs.docker.com/compose/networking/. Have you tried resolving adguardhome. from within the containers?

jschwalbe commented 12 months ago

Thanks - I believe your assumptions are correct, but that doesn’t explain why the web server responds to the docker host address, but the DNS server does not.

My limited knowledge thinks it’s a configuration error akin to the web server listening on all interfaces/IPs, but the DNS server only to certain ones?

To answer you question about resolving adguardhone, I believe that works, but it’s not reasonable to have my router tell all the hosts on my network to try to use adguardhome, bc my laptop will not know what that is.

MADx00 commented 11 months ago

I am facing a similar issue, as I am using AGH with WireGuard (specifically wg-easy) as a DNS resolver, what is weirder in my case, is that I can see from UI that the DNS requests are received by AGH, and the A record is translated, but from the VPN client side no response is received

image

*IP addreess "192.168.192.1" looks like the gateway of docker network

My setup is: AGH is deployed as a docker container, and WG (VPN clients) are trying to communicate with AGH through the host IP that links port 54 to AGH port 53

my docker-compose is

version: '3.5'
services:
  adguardhome:
    container_name: adguardhome
    image: adguard/adguardhome:latest
    restart: unless-stopped
    volumes: 
      - ./config-adguardhome/work:/opt/adguardhome/work
      - ./config-adguardhome/conf:/opt/adguardhome/conf
    ports:
      - "54:53/tcp"
      - "54:53/udp"
      - "80:80/tcp"

  wg-easy:
      - WG_HOST=<host ip>
      - WG_DEFAULT_DNS=<host ip>:54
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    volumes:
      - ./config-wg-easy:/etc/wireguard
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
nathan815 commented 9 months ago

@MADx00 I had the same exact issue and same set up - running wg-easy and AdGuardHome in docker containers on the same host. DNS resolution to AdGuardHome over WG did not work, but the server was in fact reachable through WG (confirmed by running nc -vz <ip> 53 from client connected to WG). I think what is happening is WG is routing it correctly, but AdGuardHome is sending the response out the wrong interface for some reason.

Here is what solved it for me:

  1. Put both containers in the same docker network. In docker-compose this looks like:

    
    services:
    wireguard:
     #...
     networks:
       - dns_network
    
    adguardhome:
     #...
     networks:
       - dns_network

networks: dns_network: name: dns_network


2. Explicitly bind the ports of the AdGuardHome container to the host IP. Say the IP of your host machine running the containers is `192.168.0.42`, then in docker-compose:

adguardhome:

...

ports:
  - 192.168.0.42:53:53/tcp
  - 192.168.0.42:53:53/udp
etwasmitbaum commented 9 months ago

I can confirm the solution from @nathan815. As alternative, to also have IPv6 you can use

  adguardhome:
    # ...
     network_mode: host

Although this will discard the port mapping from docker, see https://docs.docker.com/network/drivers/host/

jlmanohar commented 7 months ago

Had a similar issue, can confirm that explicit binding to host ip ports: 192.168.x.x:53:53/udp fixes the issue and other containers of different docker networks can use the adguard docker. But it messes up the logs, i now see the gateway that the aduguard home container is on and not the ip of other docker container.

i.e. All queries from all docker containers come in as 172.17.0.1 which is docker bride gateway

sfo commented 6 months ago

I am facing the same problem. AGH is working perfectly for all hosts and containers within my network but not for docker containers on the same host. Using docker run --rm busybox nslookup google.com, the query is visible in AGH log, showing a successful resolution. However, the answer never reaches the client container, resulting in a time out.

The workaround suggested by @nathan815 is solving this problem for me.