# How to Set Up a Secure DNS Sinkhole for Network Protection

> Create a secure DNS sinkhole with Pi-hole and dnscrypt-proxy. Protect your network by filtering malicious traffic before it reaches devices and encrypting upstream DNS queries.

- Repository: [Michał Ży/the-book-of-secret-knowledge](https://github.com/trimstray/the-book-of-secret-knowledge)
- Tags: how-to-guide
- Published: 2026-02-24

---

**Combine Pi-hole for domain blocking with dnscrypt-proxy for encrypted upstream queries to create a privacy-preserving DNS sinkhole that filters malicious traffic before it reaches your devices.**

The **trimstray/the-book-of-secret-knowledge** repository aggregates battle-tested open-source tools for hardening network infrastructure. Setting up a secure DNS sinkhole for network protection requires orchestrating multiple components that handle resolution, filtering, and encryption to prevent ads, trackers, and malware domains from reaching client devices.

## Core Components of a Hardened DNS Sinkhole

According to the source code analysis of [`README.md`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/README.md) in `trimstray/the-book-of-secret-knowledge`, four primary tools form the foundation of a resilient DNS sinkhole:

- **Pi-hole**: Acts as the primary DNS server and sinkhole, answering queries for blocked domains with `0.0.0.0` or `NXDOMAIN`. The repository lists Pi-hole at line 759 as "a DNS sinkhole that protects your devices from unwanted content."
- **dnscrypt-proxy**: Provides encrypted upstream resolution using DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT). Referenced at line 220 as "a flexible DNS proxy, with support for encrypted DNS protocols."
- **Unbound**: Optional recursive resolver that adds DNSSEC validation to prevent DNS spoofing. The repository cites an "Unbound DNS Tutorial" at line 1524.
- **Community Blocklists**: Curated lists of malicious domains (e.g., `StevenBlack`, `Firebog`) aggregated in the repository between lines 499-511 under DNS-related resources.

## Deployment Architecture

A secure deployment chains these components so that client devices interact only with the sinkhole, while upstream queries remain encrypted and validated:

```

Client Devices → Pi-hole (Port 53) → dnscrypt-proxy (Port 5353) → Encrypted Internet DNS
                     ↓
              Blocklists (NXDOMAIN/0.0.0.0)

```

**Traffic flow:**
1. All client DNS queries route to **Pi-hole** on port 53.
2. Pi-hole checks its **blocklist**; matching domains return sinkhole addresses immediately.
3. Permitted queries forward to **dnscrypt-proxy** (listening on `127.0.0.1:5353`) for encrypted upstream resolution.
4. Optional **Unbound** insertion between Pi-hole and dnscrypt-proxy adds DNSSEC validation before encryption.

## Step-by-Step Implementation

### 1. Deploy Pi-hole as the Blocking Layer

Create a [`docker-compose.yml`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/docker-compose.yml) file that defines Pi-hole with persistent storage for configuration and blocklists. The container must expose port 53 to your LAN and depend on the dnscrypt-proxy service.

```yaml
services:
  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    environment:
      TZ: "UTC"
      WEBPASSWORD: "SecureAdminPassword"
      DNSMASQ_LISTENING: "all"
      PIHOLE_DNS_: "127.0.0.1#5353"
    volumes:
      - "./pihole/etc-pihole:/etc/pihole"
      - "./pihole/etc-dnsmasq.d:/etc/dnsmasq.d"
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "80:80/tcp"
    restart: unless-stopped
    depends_on:
      - dnscrypt

```

**Key configuration details:**
- `PIHOLE_DNS_: "127.0.0.1#5353"` directs Pi-hole to forward uncached queries to the dnscrypt-proxy container.
- Volume mounts preserve blocklists and custom DNS settings across container restarts.

### 2. Configure dnscrypt-proxy for Encrypted Upstream

Add the dnscrypt-proxy service to your [`docker-compose.yml`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/docker-compose.yml) to handle DNS encryption. This prevents your ISP or network eavesdroppers from viewing DNS queries that pass the sinkhole filter.

```yaml
  dnscrypt:
    image: jedisct1/dnscrypt-proxy:2
    container_name: dnscrypt-proxy
    volumes:
      - "./dnscrypt-proxy/dnscrypt-proxy.toml:/etc/dnscrypt-proxy/dnscrypt-proxy.toml"
    ports:
      - "5353:53/tcp"
      - "5353:53/udp"
    restart: unless-stopped

```

Create [`./dnscrypt-proxy/dnscrypt-proxy.toml`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/./dnscrypt-proxy/dnscrypt-proxy.toml) to specify encrypted upstream resolvers and force DNSSEC validation:

```toml
listen_addresses = ['0.0.0.0:53']

server_names = ['cloudflare', 'quad9-doh-ip4-filter-pri', 'google']

require_dnssec = true
require_nolog = true
require_nofilter = true

log_level = 2

```

This configuration routes all permitted queries through **DNS-over-HTTPS** to privacy-focused resolvers while stripping out any providers that log queries or lack DNSSEC support.

### 3. Populate Blocklists from Curated Sources

Access the Pi-hole web interface at `http://<your-server-ip>/admin` and navigate to **Group Management → Adlists**. Import high-quality blocklists referenced in [`README.md`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/README.md) lines 499-511:

```text
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
https://v.firebog.net/hosts/Easyprivacy.txt
https://v.firebog.net/hosts/Prigent-Crypto.txt

```

Update gravity (Pi-hole's blocklist compiler) via the web interface or command line to activate the new filters.

### 4. Optional Hardening with Unbound for DNSSEC

For additional security against DNS cache poisoning, insert **Unbound** between Pi-hole and dnscrypt-proxy. The `the-book-of-secret-knowledge` repository references Unbound tutorials at line 1524 for this exact use case.

Add to [`docker-compose.yml`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/docker-compose.yml):

```yaml
  unbound:
    image: mvance/unbound:latest
    container_name: unbound
    ports:
      - "5354:53/tcp"
      - "5354:53/udp"
    volumes:
      - "./unbound/unbound.conf:/etc/unbound/unbound.conf"
    restart: unless-stopped

```

Configure [`./unbound/unbound.conf`](https://github.com/trimstray/the-book-of-secret-knowledge/blob/main/./unbound/unbound.conf) with DNSSEC validation enabled:

```conf
server:
    interface: 0.0.0.0
    access-control: 0.0.0.0/0 allow
    verbosity: 1
    
    do-ip4: yes
    do-udp: yes
    do-tcp: yes
    
    prefetch: yes
    prefetch-key: yes
    
    harden-algo-downgrade: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    aggressive-nsec: yes
    
    val-clean-additional: yes
    val-permissive-mode: no

```

Modify Pi-hole's upstream DNS settings to point to `127.0.0.1#5354` instead of port 5353, then configure Unbound to forward to dnscrypt-proxy on port 5353.

## Summary

- **Pi-hole** serves as the network's DNS authority and sinkhole engine, returning null routes for blocked domains as documented in `trimstray/the-book-of-secret-knowledge` line 759.
- **dnscrypt-proxy** encrypts all permitted queries using DNS-over-HTTPS, preventing surveillance of your DNS traffic (line 220 reference).
- **Unbound** optionally adds DNSSEC validation to cryptographically verify DNS responses and prevent cache poisoning (line 1524 reference).
- **Community blocklists** (lines 499-511) provide the threat intelligence that determines which domains get sinkholed.
- This layered architecture ensures that malware, tracking, and advertising domains never resolve on your network while maintaining privacy for legitimate DNS traffic.

## Frequently Asked Questions

### What is a DNS sinkhole and how does it protect my network?

A DNS sinkhole is a DNS server that intentionally gives false or null responses for specific domain queries, preventing devices from connecting to malicious or unwanted hosts. By configuring your network to use a sinkhole as its primary DNS resolver, you block threats at the resolution stage—before any TCP connection is established—effectively neutralizing command-and-control callbacks, malware downloads, and tracking pixels.

### Why should I use dnscrypt-proxy instead of standard DNS upstreams?

Standard DNS queries transmit domain names in plaintext, allowing ISPs, network administrators, or attackers to monitor your browsing habits and potentially hijack responses. **dnscrypt-proxy** encrypts these queries using DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT), ensuring that even if a domain isn't blocked by Pi-hole, the fact that you're querying it remains private from network eavesdroppers.

### Can I run this DNS sinkhole setup on a Raspberry Pi?

Yes, this architecture is specifically designed for low-power devices. Pi-hole originated as a Raspberry Pi project, and both **dnscrypt-proxy** and **Unbound** have ARM-compatible Docker images. A Raspberry Pi 4 or Pi Zero 2 W can handle DNS resolution for hundreds of devices with minimal latency, though you should use high-quality SD cards or USB storage for the persistent volumes to prevent corruption from frequent database writes.

### How do I automatically update blocklists in Pi-hole?

Pi-hole includes a built-in scheduler (cron) that runs `pihole updateGravity` weekly to refresh blocklists. You can verify or modify this schedule in `/etc/cron.d/pihole` inside the container, or set the `SKIP_GRAVITY_ON_BOOT` environment variable to `false` to ensure fresh lists on container restart. For immediate updates, execute `docker exec pihole pihole updateGravity` on your host system.