I use my Synology RS3618xs extensively at home, because it’s a beast that’s always on. With the power of BIND and the ease of use of Synology’s web application GUI, I’ve been using DNS Server for a number of years to provide internal DNS services at home. But I’ve been on the lookout for a way to integrate Pi-Hole, an internal ad-blocking solution that uses DNS to stop ads even being fetched.

I had planned to install the docker image. The problem as I saw it was that I couldn’t have two services running on port 53 — the port allocated to DNS resolution. I wasn’t interested in buying and learning about Raspberry Pi just to get this working on my LAN.

Solution

The solution is to use DNS forwarding, and the IP each docker image gets from its host.

Step 1

Run the following script to set up the container, from https://hub.docker.com/r/pihole/pihole but with a modified listening port (this ultimately doesn’t matter and won’t be referred to again — it just needs to not conflict with anything current running on the Synology).

#!/bin/bash
# Lookups may not work for VPN / tun0
IP_LOOKUP="$(ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++) if ($i=="src") print $(i+1)}')"
IPv6_LOOKUP="$(ip -6 route get 2001:4860:4860::8888 | awk '{for(i=1;i<=NF;i++) if ($i=="src") print $(i+1)}')"

# Just hard code these to your docker server's LAN IP if lookups aren't working
IP="${IP:-$IP_LOOKUP}"  # use $IP, if set, otherwise IP_LOOKUP
IPv6="${IPv6:-$IPv6_LOOKUP}"  # use $IPv6, if set, otherwise IP_LOOKUP

# Default of directory you run this from, update to where ever.
DOCKER_CONFIGS="$(pwd)"

echo "### Make sure your IPs are correct, hard code ServerIP ENV VARs if necessary\nIP: ${IP}\nIPv6: ${IPv6}"

# Default ports + daemonized docker container
docker run -d \
    --name pihole \
    -p 9953:53/tcp -p 53:53/udp \
    -p 80:80 \
    -p 443:443 \
    --cap-add=NET_ADMIN` \
    -v "${DOCKER_CONFIGS}/pihole/:/etc/pihole/" \
    -v "${DOCKER_CONFIGS}/dnsmasq.d/:/etc/dnsmasq.d/" \
    -e ServerIP="${IP}" \
    -e ServerIPv6="${IPv6}" \
    --restart=unless-stopped \
    --dns=127.0.0.1 --dns=1.1.1.1 \
    pihole/pihole:latest

echo -n "Your password for https://${IP}/admin/ is "
docker logs pihole 2> /dev/null | grep 'password:'

Step 2

Get the IP address of the container:

PS=$(sudo docker ps | grep 'pihole' | awk '{print $1}')
sudo docker exec -it $PS awk 'END{print $1}' /etc/hosts

This should spit out something like 172.17.0.16. It’s as simple as plugging this into ‘Forwarder 1’ under ‘Resolution’ in the Synology DNS Server configuration pane:

Synology DNS Server configuation pane

Synology DNS configured to refer to Pi-hole

Step 3

That’s it! Configure your pi-hole as needed.

Your LAN clients will continue to refer to your Synology DNS server as usual. Your DNS Server will now point to straight to your Pi-hole setup. The Pi-hole can be configured to point towards internet-based DNS servers for general resolution.