Pihole Installation mit Nginx Proxy

Hinweis

Die Anleitung kann veraltet sein und kann als Inspiration genutzt werden!

Diese Anleitung installiert sowohl nginx, als auch den Certbot, damit das Webinterface von Pihole per HTTPS erreichbar ist.
Möchte man das Webinterface nur intern verwenden und hat keine feste IP-Adresse oder Dyndns für die äußere IP, wird das ausstellen des Zertifikats komplizierter und man muss ggf. zur DNS Validierung greifen. Diese wird aber nicht Bestandteil der Anleitung sein, weil je nach DNS-Anbieter unterschiedliche Plugins und Schritte nötig sind…
In dieser Anleitung wird allerdings auch der Fall berücksichtigt, dass man intern ohne HTTPS auf das Webinterface zugreifen möchte. In diesem Fall bietet es sich an, einen DNS Eintrag anzulegen, der auf die internet IP-Adresse zeigt.

Für dieses Beispiel wird der Hostname pihole.dr3st.de gewählt, dieser muss den persönlichen Vorstellungen nach angepasst werden!Alle Befehle sind mittels Root-Rechten auszuführen. Es empfiehlt sich ein Root-Login oder “sudo -i”!

Nginx

Installation

Zuerst installiert man Nginx und den Certbot, sofern noch nicht passiert:

#Archlinux

pacman -Syu nginx certbot

# Ubuntu
apt-get update
apt-get install -y nginx certbot
Zertifikat anfragen

Sofern der Pfad der Standardseite von Nginx nicht anders konfiguriert wurde, sollte dieser Befehl das Zertifikat ausstellen lassen.Hierfür ist aber ein externer Zugang zum Nginx nötig.

PI_DOMAIN=pihole.dr3st.de
EMAIL="email@domain.de"

certbot certonly --webroot -w /var/www/html/ --email ${EMAIL} --non-interactive --agree-tos -d ${PI_DOMAIN} --rsa-key-size 4096
Konfiguration anlegen

Sollte Pihole nur intern laufen, müssen die Konfigurationen unten angepasst werden. Hierfür bitte die Kommentare berücksichtigen!Erst den Befehl ausführen und dann die gewünschten Parameter anpassen.
Außerdem kann der Hostname auch auf die lokale private IP-Adresse zeigen. Beispielsweise könnte pihole.dr3st.de auf 192.168.178.222 zeigen und somit per Hostname im internen Netz erreichbar gemacht werden.

Wichtig:

Die IP-Adresse im proxy_pass Parameter muss mit der Adresse im docker-compose.yml übereinstimmen!Außerdem sollte das Webinterface noch abgesichert werden, hierfür sind allow / deny Beispiele vorbereitet, allerdings auskommentiert. Einfach die Netze freigeben die Zugriff haben dürfen.

cat > /etc/nginx/sites-enabled/${PI_DOMAIN}.conf <<EOF
server {
    server_name     ${PI_DOMAIN};

    listen          0.0.0.0:80;

    location ~ .well-known {
        root        /var/www/html;
    }

    # HTTPS Umleitung falls HTTPS genutzt wird, wenn nicht, auskommentieren!
    location / {
        return  301 https://${PI_DOMAIN}$request_uri;
    }
    
    # Falls kein HTTPS verwendet wird, diese Sektion aktivieren
    #location / {
    #	include /etc/nginx/proxy_params;
    #	proxy_pass http://10.11.12.3:80;
    # bestimmte Netze erlauben, alle anderen verbieten
    #   allow 192.168.178.0/24;
    #   allow 10.10.10.0/24;
    #   allow 192.168.1.33/32; # /32 bedeutet eine einzelne IP-Adresse
    #   deny  all;
    #}
    
}

# Falls kein HTTPS gewünscht oder möglich, kann diese ganze Sektion auskommentiert werden
server {
    server_name         ${PI_DOMAIN};

    listen              0.0.0.0:443 ssl http2;

    access_log          /var/log/nginx/${PI_DOMAIN}.access.log;
    error_log           /var/log/nginx/${PI_DOMAIN}.error.log;
    
    root                /var/www/html;

    ssl_certificate     /etc/letsencrypt/live/${PI_DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${PI_DOMAIN}/privkey.pem;

    # bestimmte Netze erlauben, alle anderen verbieten 
    #allow 192.168.178.0/24;
    #allow 10.10.10.0/24;
    #deny  all;

    # Proxy for pihole docker
    location / {
        proxy_set_header Host \$host;
        proxy_set_header X-Forwarded-Proto \$scheme;
        
        add_header          Strict-Transport-Security   "max-age=63072000" always;
        add_header          X-Frame-Options             SAMEORIGIN;

        proxy_cookie_path / "/; secure; HttpOnly";
        
        include /etc/nginx/proxy_params;
        proxy_pass http://10.11.12.3:80;
    }
}
EOF

Firewall und DNS Zugriff

Um das Webinterface aufzurufen, sollten die Ports 80 und 443 (bei Verwendung von HTTPS) freigeschaltet sein. Da der Certbot bereits oben im Einsatz war und im Standardfall eine HTTP-Anfrage durchgeführt wurde, sollte der Port bereits offen sein.

Außerdem muss der Zugang zu den DNS-Ports ermöglicht werden. Weil Pihole aber in einem isolierten Bereich aktiv ist und auf vielen Servern der Systemd-Resolved schon läuft, muss dieser erst deaktiviert werden, bevor die Ports im System gebunden werden können. Kurz gesagt Systemd-Resolved blockiert Port 53!
Eine Alternative zum Docker-Proxy kann Firewall-NAT sein, allerdings unterbindet hier die iptables-Isolation von Docker eine Konfiguration mittels NFTables. Ich möchte aber nicht unerwähnt lassen, dass wenn man iptables in Docker deaktivieren und Konfiguration mittels NFTables vornehmen kann …

Systemd-Resolved ausschalten und deaktivieren
systemctl stop systemd-resolved.service
systemctl disable systemd-resolved.service

Docker

Netzwerk anlegen

Falls noch nicht passiert, wird ein Docker Netzwerk angelegt. Dies wurde in der Nextcloud Anleitung (https://dr3st.de/komplettanleitung-mariadb-nextcloud-mit-nginx-proxy/) genauer erklärt:

docker network create \
  --gateway 10.11.12.1 \
  --subnet 10.11.12.0/24 \
  --opt com.docker.network.bridge.name=br_apps \
  br_apps
Orderstruktur anlegen
# Logverzeichnis für Lighttp (Webserver)
mkdir -p /srv/docker/containers/pihole/log/lighttpd/
Docker-Compose

Diese compose-Datei bindet sich global an Port 53 (TCP und UDP). Möchte man nur bestimmte Netze mit DNS versorgen, kann auch auf bestimmte IP-Adressen gebunden werden (siehe unten) und mittels Firewall-Regeln der Zugriff unterbunden werden.

# Ordner anlegen
mkdir -p /srv/docker/git/pihole

# Variablen nach Wunsch anpassen
DNS_1="1.1.1.1"
DNS_2="8.8.8.8"
PASSWORD="WEB_P4SSW0RD"

# docker-compose.yml erzeugen
cat > /srv/docker/git/pihole/docker-compose.yml <<EOF
version: "3"

# 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
    hostname: "${PI_DOMAIN}"
    environment:
      TZ: 'Europe/Berlin'
      DNS_1: "${DNS_1}"
      DNS_2: "${DNS_2}"
      WEBPASSWORD: "${PASSWORD}"
      SERVERIP: "0.0.0.0"
      ServerIP: "0.0.0.0"
    volumes:
       - '/srv/docker/containers/pihole/etc-pihole/:/etc/pihole/'
       - '/srv/docker/containers/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/'
       - '/srv/docker/containers/pihole/log:/var/log/'
    restart: unless-stopped
    ports:
    - 53:53/tcp
    - 53:53/udp
    networks:
      default:
        ipv4_address: 10.11.12.3

networks:
  default:
    external:
      name: br_apps
EOF

cd /srv/docker/git/pihole
docker-compose pull
docker-compuse up -d
Port-Binding anpassen

Dies ist nicht zwingend notwendig und dient nur wie bereits erwähnt als Beispiel!

services:
  pihole:
    ...
  ports:
    - 127.0.0.1:53:53
    - 127.0.0.1:53:53/udp
    - 10.20.30.7:53:53
    - 10.20.30.7:53:53/udp
  networks:
    ...

Tests

Nun sollte der Zugriff über die gewünschte Domain funktionieren (je nachdem wie konfiguriert):

  • https://$PI_DOMAIN/admin
  • http://$PI_DOMAIN/admin

Das Passwort kann in der docker-compose.yml angepasst und ausgelesen werden.
Die Auflösung des DNS kann ebenfalls getestet werden, denn der Docker-Proxy leitet die Anfragen in den Container:

# Test via NSLookup
nslookup dr3st.de 127.0.0.1
Server:         127.0.0.1
Address:        127.0.0.1#53

Non-authoritative answer:
Name:   dr3st.de
Address: 85.10.199.104


# Test via dig
root@docker-etst:/srv/docker/git/pihole# dig www.dr3st.de @127.0.0.1

; <<>> DiG 9.16.1-Ubuntu <<>> www.dr3st.de @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11441
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.dr3st.de.                  IN      A

;; ANSWER SECTION:
www.dr3st.de.           3600    IN      CNAME   dr3st.de.
dr3st.de.               3600    IN      A       85.10.199.104

Pihole-Projekt