Help for configure DNS-Over-Https with Pi-Hole and Cloudflared in Docker

Hi guys, I'm very satisfied with the use of Pi-Hole with Raspberry Pi 4 and now I would like to integrate the use of DoH Cloudflared in Docker.
Can anyone tell me if the items I have set are right? Thank you!

this i the stack of my pihole

version: "2"

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 67:67/udp
      - 80:80/tcp
      - 8443:8443/tcp
    environment:
      TZ: Europe/Rome
      WEBPASSWORD: password
      PROXY_LOCATION=pihole
      VIRTUAL_PORT=80
      DNS1=172.26.0.3#5053
      DNS2=1.1.1.1					   
    volumes:
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-pihole:/etc/pihole
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
    hostname: pihole
    networks:
      pihole:
        ipv4_address: 172.26.0.2
    dns:
      - 127.0.0.1
      - 1.1.1.1
    cap_add:
      - NET_ADMIN
    restart: unless-stopped

internal docker ip is: 172.26.0.2 (pihole_default) / 172.26.0.1 (pihole_default gateway) / 172.26.0.0 (pihole_default subnet).

version: 2

services:
   cloudflared:
    image: crazymax/cloudflared:latest
    container_name: cloudflared
    hostname: cloudflared
    networks:
     pihole_default:
       ipv4_address: 172.26.0.3
    environment:
      - TZ=Europe/Rome
      - TUNNEL_DNS_UPSTREAM=https://1.1.1.1/dns-query,https://1.0.0.1/dns-query
    restart: always

I have joined cloudflared container to pihole_default network and assigned ip .3
is it correct? how can I see if effectively work?
on https://www.cloudflare.com/ssl/encrypted-sni/ I have better result without pihole.

I have stopped using the cloudflared proxy as my DoH interface and went to DNSCRYPT. I have been running this way over 6 months and haven't had any issues like I had with the cloudflared proxy. Here is my commented yaml file for docker-compose. You can use it as a template. You may want to do some reading on macvlan networks and some of their limitations for host access in docker but you will find that Pi-hole works best in this configuration.

Version: '2'

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    hostname: pihole2
    domainname: somedomain.com             # <-- Update
#    mac_address: d0:ca:ab:cd:ef:01
    cap_add:
      - NET_ADMIN
    networks:
      pihole_network:
        ipv4_address: 192.168.x.x  # <-- Update
    dns:
      - 1.1.1.1
      - 1.0.0.1
    ports:
      - 443/tcp
      - 53/tcp
      - 53/udp
      - 67/udp
      - 80/tcp
    environment:
      ServerIP: 192.168.x.x         # <-- Update (match ipv4_address)
      VIRTUAL_HOST: host.domain  # <-- Update (match hostname + domainname)
      WEBPASSWORD: letmein                   # <-- Add password (if required)
      UTC: America/Chicago
      DNS1: 192.168.x.x#53       # <-- DNS1 of pihole configured to DNSCRYPT address
      DNS2: 192.168.x.x#53       # <-- DNS2 of pihole configured to DNSCRYPT address
    volumes:
       - '/volume1/docker/pi-hole/etc-pihole/:/etc/pihole/'
       - '/volume1/docker/pi-hole/etc-dnsmasq.d/:/etc/dnsmasq.d/'
    restart: unless-stopped

  dnscrypt:
    container_name: dnscrypt-proxy
    image: gists/dnscrypt-proxy:latest
    hostname: dnscrypt
    domainname: somedomain.com             # <-- Update
    ports:
    - 53/udp
    - 53/tcp
    networks:
      pihole_network:
        ipv4_address: 192.168.x.x  # <--Update
    volumes:
    - '/volume1/docker/dnscrypt-proxy/dnscrypt-proxy.toml:/etc/dnscrypt-proxy/dnscrypt-proxy.toml'  # <--custom toml file for easy editing
    restart: always

networks:
  pihole_network:
    driver: macvlan
    driver_opts:
      parent: eth0     # <-- validate the native network inferface on host
    ipam:
      config:
        - subnet: 192.168.x.x/24            # <-- Update
          gateway: 192.168.x.x             # <-- Update
          ip_range: 192.168.x.x/32        # <-- Update

Hi @RonV42 thanks for your reply, I have some question:

  • ipv4_address: I need to put internal docker ip or router ip? I have for container ip like 172.20.x.x to 172.27.x.x, in particular Pihole network is 172.26.0.2.
    same questo for ServerIP
  • domain name I don't know what insert here
  • pihole_network is the name of network connectivity? in my portainer all containers have NameNetwork_default, I need to replace with pihole_default?

then I try to write a draft of stack and tell me if is correct

since you are going to be using macvlan you will need to use addresses from the network the host is using for example if your host is 192.168.1.10 you need to pick addresses for both the pi.hole and the dnscrypt that isn't used by other devices in the 192168.1.0 network. I usually leave a block of addresses free that the DHCP server will not assign for this purpose say 192.168.1.10-192.168.1.29.

In this case the pihole would use 192.168.1.11 as it's ipv4 address and the dnscrypt would be assigned 192.168.1.12 in the yaml file.

The goal is not to use the default networks that docker creates and with this stack you will have a direct access to the host network with no nat or routing needed.

@RonV42
can you check this stack? sorry for my noob question..

Version: '2'

services:
  pihole:
    container_name: pihole						   
    image: pihole/pihole:latest						   
    hostname: pihole
    domainname: somedomain.com             # what insert here? my router is 192.168.178.1 named fritz.box on my local network
#    mac_address: 							# same here, what mac? pihole_default mac address (virtual card on portainer)?
    cap_add:
      - NET_ADMIN							
    networks:
      pihole_default:
        ipv4_address: 192.168.178.45		#ok?
    dns:
      - 1.1.1.1
      - 1.0.0.1
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 67:67/udp
      - 80:80/tcp
      - 8443:8443/tcp
    environment:
      ServerIP: 192.168.178.45         # ok?
      VIRTUAL_HOST: host.domain  #   ???
      WEBPASSWORD: password                   
      UTC: Europe/Rome
      DNS1: 192.168.178.46#53       # 
      DNS2: 192.168.178.46#53       # correct?
    volumes:
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-pihole:/etc/pihole
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped

  dnscrypt:
    container_name: dnscrypt-proxy
    image: gists/dnscrypt-proxy:latest
    hostname: dnscrypt
    domainname: somedomain.com             # <-- Update
    ports:
    - 53/udp
    - 53/tcp
    networks:
      pihole_default:
        ipv4_address: 192.168.178.46  #  ok?
    volumes:
    - /srv/dev-disk-KINGSTON/appdata/dnscrypt-proxy/dnscrypt-proxy.toml:/etc/dnscrypt-proxy/dnscrypt-proxy.toml
    restart: always

networks:
  pihole_default:
    driver: macvlan
    driver_opts:
      parent: eth0     # real eth port on raspberry
    ipam:
      config:
        - subnet: 255.255.255.0/24 ?           
          gateway: 192.168.x.x             # ?
          ip_range: 192.168.x.x/32        # ?

I did some clean up and added more comments. You still need to provide IP address for your router and the macvlan network IP address for IPAM I made some suggestions in the comments:

Version: '2'

services:
  pihole:
    container_name: pihole						   
    image: pihole/pihole:latest						   
    hostname: pihole
    domainname: local             # < - local domain you can use "local" 
#    mac_address: 							# < - ignore this is a deprecated value I commented out once I installed a new versin of docker
    cap_add:
      - NET_ADMIN							
    networks:
      pihole_default:
        ipv4_address: 192.168.178.45		#ok? < ok
    dns:
      - 1.1.1.1
      - 1.0.0.1
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 67:67/udp
      - 80:80/tcp
      - 8443:8443/tcp
    environment:
      ServerIP: 192.168.178.45         # ok? < ok
      VIRTUAL_HOST: pihole.local  #   < try this 
      WEBPASSWORD: password  # ha password you may want something stronger :-)                   
      UTC: Europe/Rome
      DNS1: 192.168.178.46#53       # 
      DNS2: 192.168.178.46#53       # correct?
    volumes:
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-pihole:/etc/pihole
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped

  dnscrypt:
    container_name: dnscrypt-proxy
    image: gists/dnscrypt-proxy:latest
    hostname: dnscrypt
    domainname: local             # <- same as above
    ports:
    - 53/udp
    - 53/tcp
    networks:
      pihole_default:
        ipv4_address: 192.168.178.46  #  ok? < - ok
    volumes:
    - /srv/dev-disk-KINGSTON/appdata/dnscrypt-proxy/dnscrypt-proxy.toml:/etc/dnscrypt-proxy/dnscrypt-proxy.toml
    restart: always

networks:
  pihole_default:
    driver: macvlan
    driver_opts:
      parent: eth0     # real eth port on raspberry
    ipam:
      config:
        - subnet: 255.255.255.0/24 ?           
          gateway: 192.168.x.x             # < -  you need to provide the address of your router here
          ip_range: 192.168.x.x/32        # < - a free address in your network 192.168.178.43 or 192.168.178.47?  If they are free

Hi @RonV42 thanks again, I have adjust stack, only two questions:

  • dns1 and 2 in env are correct? only for recap my raspi have from router 192.168.178.44 and in docker networks named "pihole_default" it get 172.26.0.2/16 - gateway .1 and subnet .0/16, now on my router I have free .45 .46 .47 etc.
  • in ipam config, subnet is correct? and in ip range what mean /32?

thanks!

Edit:
I have copied this in new stack and get "error response from daemon failed to allocate gateway (192.168.178.1) requested address is out of range"

---
version: '2'
services:
  pihole:
    container_name: pihole						   
    image: pihole/pihole:latest						   
    hostname: pihole
    domainname: local              
    cap_add:
      - NET_ADMIN							
    networks:
      pihole_default:
        ipv4_address: 192.168.178.45		#ok
    dns:
      - 1.1.1.1
      - 1.0.0.1
    ports:
      - 53:53/tcp
      - 53:53/udp
      - 67:67/udp
      - 80:80/tcp
      - 8443:8443/tcp
    environment:
      ServerIP: 192.168.178.45         #ok
      VIRTUAL_HOST: pihole.local  #try this 
      WEBPASSWORD: password
      UTC: Europe/Rome
      DNS1: 192.168.178.46#53        
      DNS2: 192.168.178.46#53       
    volumes:
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-pihole:/etc/pihole
      - /srv/dev-disk-KINGSTON/appdata/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
    restart: unless-stopped

  dnscrypt:
    container_name: dnscrypt-proxy
    image: gists/dnscrypt-proxy:latest
    hostname: dnscrypt
    domainname: local             
    ports:
    - 53/udp
    - 53/tcp
    networks:
      pihole_default:
        ipv4_address: 192.168.178.46  #ok
    volumes:
	  - /srv/dev-disk-KINGSTON/appdata/dnscrypt-proxy/dnscrypt-proxy.toml:/etc/dnscrypt-proxy/dnscrypt-proxy.toml
    restart: always

networks:
  pihole_default:
    driver: macvlan
    driver_opts:
      parent: eth0     
    ipam:
      config:
        - subnet: 255.255.255.0/24           
          gateway: 192.168.178.1             
          ip_range: 192.168.178.47/32

What does your docker compose up command look like and what exactly is the output of it?

I see nowhere within the configuration file any address of 192.168.17.1...is anything in your network address with 192.168.17.x?

@RonV42 my error sorry I mean 192.168.178.1

what IP address is assigned to the eth0 interface of the host? Can you do a ifconfig?

as I mentioned before eth0 (raspberry) have static ip on router .44 I need to put on ipam gateway?

The gateway is usually the local address of your router. Also want to make sure you PI has a static address configured right on the PI and isn't a static that is handed out by DHCP.

raspberry have dhcp, but get always same ip from router blocked on .44

Macvlan needs the eth0 to have a static address. There are lots of articles on how to set a static address on a Raspberry PI. Here is a tutorial on Macvlan:

Hi Ron, I have followed and creat a macvlan but yesterday I have found this guide: http://mroach.com/2020/08/pi-hole-and-cloudflared-with-docker/ and followed method1 but pihole register 0 client no activity.
I don't understand why is so complicated for me use pihole in combination with cloudflared or dnscrypt..

Well you are trying to do many things at once that has to properly configured. Networking is the ultimate Rube Goldberg machine one part fails poof the whole thing doesn't work. It took me 3 months coming up with my perfect implementation for the type of network I have and I have been doing networking for over 30 years.

To make the clients on your network use Pi-hole you need to update the DHCP server on your router to use the pi-holes address for the DNS servers or you can disable DHCP totally on your router and make the pi-hole your DHCP server. There are lots of conversations on here on using either of these two approaches.

1 Like

I have found a solution and write a stack for use Pi-Hole and Cloudflared below but before two points:

  1. before start on docker create a network direct connect with our local lan so in my case, opened terminal and digit:
docker network create -d macvlan \
  --subnet=192.168.178.0/24 \
  --gateway=192.168.178.1 \
  -o parent=eth0 priv_lan

192.168.178.0/24 is my real network and .1 is Router IP, priv_lan is the name of network created on docker you can rename as you want, eth0 is the name of physical network card on my Raspberry Pi 4, so before look with ifconfig true name, at last if command not work try with sudo.

  1. in stack I have assigned .50 to cloudflared container and .51 at pihole of my real network, so before verify that you choose a free port in you router.
---
version: "2"

services:
  cloudflared:
    container_name: cloudflared
    restart: unless-stopped
    image: crazymax/cloudflared  #multi-arch image support arm
    command: proxy-dns
    environment:
      - "TUNNEL_DNS_UPSTREAM=https://1.1.1.1/dns-query,https://1.0.0.1/dns-query,https://9.9.9.9/dns-query,https://149.112.112.9/dns-query"
      - "TUNNEL_METRICS=0.0.0.0:49312"
      - "TUNNEL_DNS_ADDRESS=0.0.0.0"
      - "TUNNEL_DNS_PORT=5053"
    networks:
      priv_lan:
        ipv4_address: 192.168.178.50

  pihole:
    container_name: pihole
    restart: unless-stopped
    image: pihole/pihole:latest
    environment:
      - "TZ=Europe/Rome"
      - "DNS1=192.168.178.50#5053"
      - "DNS2=no"
      - "WEBPASSWORD=password"
    volumes:
      - '/srv/dev-disk-KINGSTON /appdata/pihole/etc-pihole:/etc/pihole'
      - '/srv/dev-disk-KINGSTON /appdata/pihole/etc-dnsmasq.d:/etc/dnsmasq.d'
    networks:
      priv_lan:
        ipv4_address: 192.168.178.51

networks:
  priv_lan:
    external:
      name: priv_lan

That's all.

1 Like