Skip to main content

🛡️ DNS Appliance: Pi-hole + Unbound (Full Performance) 12/2025!!!!

Konfigurace: 2025 High-Performance Edition Hardware: Raspberry Pi (Dedikovaný provoz) Status: Produkční / Wiki-Ready


1️⃣ Host OS Tuning (Kernel & CPU)

Optimalizace pro maximální propustnost a konzistentní latenci.

  1. Sysctl optimalizace:

sudo nano /etc/sysctl.d/99-dns-tuning.conf

a vložit:

# UDP stack připraven na burst provoz
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.netdev_max_backlog = 8192

# TCP a systémová odezva
net.ipv4.tcp_fastopen = 3
vm.swappiness = 10
  1. Aplikace: sudo sysctl --system

  2. CPU Performance (Volitelné): Pro eliminaci latence při změnách frekvence procesoru: sudo apt install -y linux-cpupower && sudo cpupower frequency-set -g performance


2️⃣ Unbound: Full Performance Mode

Konfigurace využívá všechna jádra RPi a eliminuje zamykání cache (lock contention).

Příprava

sudo curl -o /opt/unbound/root.hints https://www.internic.net/

Konfigurace:

sudo nano /opt/unbound/unbound.conf

 

server:
  interface: 0.0.0.0@5335
  access-control: 127.0.0.1 allow
  access-control: 172.20.0.0/24 allow
  access-control: 192.168.0.0/16 allow
  root-hints: "/etc/unbound/root.hints"

  # Soukromí a bezpečnost
  hide-identity: yes
  hide-version: yes
  qname-minimisation: yes
  harden-dnssec-stripped: yes
  harden-glue: yes
  use-caps-for-id: no  # Prevence falešných timeoutů v Dockeru

  # === MAX PERFORMANCE ===
  num-threads: 4
  msg-cache-size: 128m
  rrset-cache-size: 256m
  msg-cache-slabs: 8    # threads * 2
  rrset-cache-slabs: 8

  prefetch: yes
  serve-expired: yes

3️⃣ Deployment: Portainer Stack

Nasazení přes Portainer UI s Environment Variables. Port 81 pro Pi-hole kvůli koexistenci s Nginx Proxy Managerem.

version: "3"
services:
  unbound:
    image: klutchell/unbound:latest
    container_name: unbound
    restart: unless-stopped
    networks:
      dns_net:
        ipv4_address: 172.20.0.2
    volumes:
      - /opt/unbound/unbound.conf:/etc/unbound/unbound.conf:ro
      - /opt/unbound/root.hints:/etc/unbound/root.hints:ro
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  pihole:
    image: pihole/pihole:latest
    container_name: pihole
    restart: unless-stopped
    networks:
      dns_net:
        ipv4_address: 172.20.0.3
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "81:80/tcp"
    environment:
      - TZ=Europe/Prague
      - WEBPASSWORD=${PIHOLE_PASS}
      - PIHOLE_DNS_=172.20.0.2#5335
      - DNSSEC=true
      - DNSMASQ_LISTENING=all
    volumes:
      - /opt/pihole/etc-pihole:/etc/pihole
      - /opt/pihole/etc-dnsmasq.d:/etc/dnsmasq.d
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

networks:
  dns_net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

4️⃣ Automatizace & Údržba

  • Root Hints: Skript /opt/unbound/update-root-hints.sh s příkazem docker kill -s SIGHUP unbound (zero-downtime).

  • Aktualizace: Watchtower Stack s label-based filtrací.

  • Cron: Spouštění aktualizace root.hints měsíčně.


5️⃣ Verifikace (Povinné testy)

Test Metoda Očekávaný výsledek
Výkon docker exec -it unbound top 4 aktivní thready
Rekurze dig @127.0.0.1 -p 5335 whoami.akamai.net Moje veřejná IP
DNSSEC dig @127.0.0.1 -p 5335 sigfail.verteiltesysteme.net Status SERVFAIL
Latence dig @127.0.0.1 -p 5335 google.com +stats Query time < 10ms (cache hit)