DNS, Pi-Hole and Mac

I have a somewhat complex DNS resolution setup, as I need to resolve domains within my client’s network using specific DNS servers. Given my frequent movement between networks, this configuration is essential.

To achieve this, I’ve implemented the solution, which also involves a DNS Sinkhole. Please note that this is a Mac-specific approach, but it may be adaptable to other systems as well.

Different DNS servers for different domains

My customer uses some internal domains that cannot be resolved with public DNS servers. For example: one custom domain is foo.internal, and it is resolved by the DNS servers 10.1.1.1 and 10.2.2.2.

The implementation would be in /etc/resolver/foo.internal with this content:

domain foo.internal
search foo.internal
nameserver 10.1.1.1
nameserver 10.2.2.2

Reload with:

sudo killall -HUP mDNSResponder

Check the DNS configuration with:

scutil --dns

VPN issues

I still encountered an issue: every time I connected to a VPN, the system got the DNS server via DHCP, overwrote /etc/resolv.conf file, and I had to reconfigure it. Since I had solved the issue of resolving internal company domains with custom resolvers, I needed a way to protect the /etc/resolv.conf file from being overwritten.

chflags uchange /var/run/resolv.conf

It worked like a charm!

This is how to unblock it:

chflags nouchange /var/run/resolv.conf

Pi-Hole

Considering the ongoing issues I was experiencing with the ads-blocker, I decided to use Pi-Hole as an alternative solution. There is a convenient way to set up Pi-Hole locally with Docker, eliminating the need for an external server or box.

Ref: Docker Pi-hole

Create a Docker Compose file such as the following:

# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    ports:
      # DNS Ports
      - "53:53/tcp"
      - "53:53/udp"
      # Default HTTP Port
      - "80:80/tcp"
      # Default HTTPs Port. FTL will generate a self-signed certificate
      - "443:443/tcp"
      # Uncomment the below if using Pi-hole as your DHCP Server
      #- "67:67/udp"
    environment:
      # Set the appropriate timezone for your location (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), e.g:
      TZ: 'Europe/London'
      # Set a password to access the web interface. Not setting one will result in a random password being assigned
      FTLCONF_webserver_api_password: 'correct horse battery staple'
      # If using Docker's default `bridge` network setting the dns listening mode should be set to 'all'
      FTLCONF_dns_listeningMode: 'all'
    # Volumes store your data between container upgrades
    volumes:
      # For persisting Pi-hole's databases and common configuration file
      - './etc-pihole:/etc/pihole'
      # Uncomment the below if you have custom dnsmasq config files that you want to persist. Not needed for most starting fresh with Pi-hole v6. If you're upgrading from v5 you and have used this directory before, you should keep it enabled for the first v6 container start to allow for a complete migration. It can be removed afterwards. Needs environment variable FTLCONF_misc_etc_dnsmasq_d: 'true'
      #- './etc-dnsmasq.d:/etc/dnsmasq.d'
    cap_add:
      # See https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
      # Required if you are using Pi-hole as your DHCP server, else not needed
      - NET_ADMIN
      # Required if you are using Pi-hole as your NTP client to be able to set the host's system time
      - SYS_TIME
      # Optional, if Pi-hole should get some more processing time
      - SYS_NICE
    restart: unless-stopped

The start it with docker compose up -d.

To make it easier, I created an alias in my .zshrc:

export CUR_FOLDER=`dirname $0`
alias docker_pi_hole="docker compose -f ${CUR_FOLDER}/pi-hole.docker up -d"

Open Pi-Hole Admin Panel to check it out: the password is in the Docker Compose file (correct horse battery staple).

Add filtering lists

Pi-Hole alone is not sufficient to filter internet traffic, and it is necessary to configure at least one DNS blacklist list to block malicious websites. I use Hagezi block list that can be configured in the admin panel under Lists.

Configure your favourite public DNS

It’s also a good idea to have a look to the core DNS servers under Settings/DNS to pick the most appropriate server or configure a custom one.

Add custom white/black-listed domains

Filtering is self-explanatory in the domain tab.

NordVPN and similar

VPNs may override the DNS settings bypassing Pi-Hole and that setting must be disabled.

Browsers with DNS over HTTPS

DOH bypasses Pi-Hole and must be disabled.

Checking that everything works

Open Pi-Hole query log, browse internet and verify that the log moves.