icon robot josef

Hardware

Grundsystem

Unter https://www.raspberrypi.com/software/operating-systems/ liegen angepasste Debian-Images. Wähle das schlankste 64Bit-Image aus, heute ist das https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2025-12-04/2025-12-04-raspios-trixie-arm64-lite.img.xz

Flashe das Image auf die z.B. SSD. Stelle sicher, unter welcher environment variable (/dev/sdX) die SSD nach dem Anschluß an den Rechner zu finden ist.

# dmesg|tail

# xzcat /path/to/2025-12-04-raspios-trixie-arm64-lite.img.xz | dd of=/dev/sdX bs=64k oflag=dsync status=progress

Anschließend den Pi von der SSD booten. Schließe die SSD an einen der beiden USB2-Ports an. An USB3 bricht der Bootprozess ab.

Weitere nützliche Pakete installieren:

$ sudo apt update && apt upgrade
$ sudo apt install vim zsh openssh-server

SSH

Bereite auf dem lokalen Rechner eine sichere Verbindung zum Pi vor. Generiere ein ssh key pair, das nur mit dem Pi verwendet wird, -f steht für –filename:

$ ssh-keygen -f ~/.ssh/id_lokalercomputer_2_ph.pub

Schicke den zuvor erstellten public key an den Pi:

$ ssh-copy-id -i ~/.ssh/id_lokalercomputer_2_ph.pub -p 22 user@local-ip-of-Pi

Log in den Pi vom lokalen Rechner:

ssh user@local-ip-of-Pi

Editiere die /etc/ssh/sshd_config auf dem Pi:

$sudo vim /etc/ssh/sshd_config

Passe dabei Portnummern und authentification modes an:

Port $portnumber
PubkeyAuthentication yes
PasswordAuthentication no

Auf dem Pi starte ssh (nicht sshd) neu:

$sudo systemctl restart ssh

Logge dich vom lokalen Rechner ein:

ssh -i ~/.ssh/id_lokalercomputer_2_ph 'user@local-ip-of-Pi' -p $portnumber

Wenn alles wie erwartet funktioniert, passe die lokale .ssh/config an, z.B.:

# pi-hole
Host ph
Hostname <lokale IP, z.B. 192.168.2.99>
Port < >1024, z.B. 16634>
User <user>
IdentityFile ~/.ssh/id_lokalercomputer_2_ph

Pi hole

Erneuter Login in den Pi. Downloade das Installationsscript von https://install.pi-hole.net

$ wget -O basic-install.sh https://install.pi-hole.net

Lese das Skript. Wenn alles plausibel ist und keine Modifikation erforderlich ist, benutze das Skript für die Installation der Pi-hole-Umgebung:

$ sudo bash basic-install.sh

Um die Pi-ho-Installation zu administrieren, werde Mitglied der entsprechenden Gruppe:

# sudo usermod -aG pihole $USER

Update die Pi-hole-Umgebung

$ sudo pihole up

Im Router nun die DNS-Auflösung auf den Pi umleiten. In einer aktuellen FritzBox findet sich das im Pfad Internet > Zugangsdaten > DNS-Server. Dort Andere DNSv4-Server verwenden und Andere DNSv6-Server verwenden auswählen und die lokalen IPs eingeben, z.B. 192.168.2.99. Die lokale IPv6 beginnt mit fe80:. Überprüfe auf einem lokalen Gerät und rufe eine Seite auf, von der Du weißt, dass sie viele Werbebanner mitbringt. Das Pi-hole macht nur DNS-Manipulation, vom Server der aufgerufenen Webseite ausgelieferte Werbung kann das Pi-hole nicht ausfiltern. Aber von Dritten ausgelieferte Werbung sollte verschwunden sein.

Lokale DNS-Auflösung

Installiere unbound und dns-root-data

sudo apt install unbound dns-root-data

Schreibe eine config, wie unbound mit Anfragen von pi-hole umgehen soll:

vim /etc/unbound/conf.d/pi-hole.conf

server:
# If no logfile is specified, syslog is used
logfile: "/var/log/unbound/unbound.log"
log-time-ascii: yes
verbosity: 1

interface: 127.0.0.1
port: 5335
do-ip4: yes
do-udp: yes
do-tcp: yes

# May be set to no if you don't have IPv6 connectivity
do-ip6: yes

# You want to leave this to no unless you have *native* IPv6. With 6to4 and
# Terredo tunnels your web browser should favor IPv4 for the same reasons
prefer-ip6: no

# Use this only when you downloaded the list of primary root servers!
# If you use the default dns-root-data package, unbound will find it automatically
#root-hints: "/var/lib/unbound/root.hints"

# Trust glue only if it is within the server's authority
harden-glue: yes

# Require DNSSEC data for trust-anchored zones, if such data is absent, the zone becomes BOGUS
harden-dnssec-stripped: yes

# Don't use Capitalization randomization as it known to cause DNSSEC issues sometimes
# see https://discourse.pi-hole.net/t/unbound-stubby-or-dnscrypt-proxy/9378 for further details
use-caps-for-id: no

# Reduce EDNS reassembly buffer size.
# IP fragmentation is unreliable on the Internet today, and can cause
# transmission failures when large DNS messages are sent via UDP. Even
# when fragmentation does work, it may not be secure; it is theoretically
# possible to spoof parts of a fragmented DNS message, without easy
# detection at the receiving end. Recently, there was an excellent study
# >>> Defragmenting DNS - Determining the optimal maximum UDP response size for DNS <<<
# by Axel Koolhaas, and Tjeerd Slokker (https://indico.dns-oarc.net/event/36/contributions/776/)
# in collaboration with NLnet Labs explored DNS using real world data from the
# the RIPE Atlas probes and the researchers suggested different values for
# IPv4 and IPv6 and in different scenarios. They advise that servers should
# be configured to limit DNS messages sent over UDP to a size that will not
# trigger fragmentation on typical network links. DNS servers can switch
# from UDP to TCP when a DNS response is too big to fit in this limited
# buffer size. This value has also been suggested in DNS Flag Day 2020.
edns-buffer-size: 1232

# Perform prefetching of close to expired message cache entries
# This only applies to domains that have been frequently queried
prefetch: yes

# One thread should be sufficient, can be increased on beefy machines. In reality for most users running on small networks or on a single machine, it should be unnecessary to seek performance enhancement by increasing num-threads above 1.
num-threads: 1

# Ensure kernel buffer is large enough to not lose messages in traffic spikes
so-rcvbuf: 1m

# Ensure privacy of local IP ranges
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10

# Ensure no reverse queries to non-public IP ranges (RFC6303 4.2)
private-address: 192.0.2.0/24
private-address: 198.51.100.0/24
private-address: 203.0.113.0/24
private-address: 255.255.255.255/32
private-address: 2001:db8::/32

Ich habe natives IPv6, daher ändere ich prefer-ip6: no zu prefer-ip6: yes.

Debian installiert routinemäßig konkurrierende Namensauflösung (openresolv). Dienst deaktivieren:

$ sudo systemctl disable --now unbound-resolvconf.service

Verhindern, dass bei einen Aufruf von resolvconf die Datei resolvconf_resolvers.conf angelegt wird:

$ sudo sed -Ei 's/^unbound_conf=/#unbound_conf=/' /etc/resolvconf.conf
$ sudo rm /etc/unbound/unbound.conf.d/resolvconf_resolvers.conf

Logging einschalten:

$ sudo mkdir -p /var/log/unbound
$ sudo touch /var/log/unbound/unbound.log
$ sudo chown unbound /var/log/unbound/unbound.log

Unbound neu starten:

$ sudo service unbound restart

Im Pi-hole-Interface die Namensauflösung umstellen: Uncheck alle Haken bei den großen DNS-Providern, bei Custom DNS servers eintragen:

127.0.0.1#5335

Achtung: Der lokale Port is 5335, nicht 5353. Funktioniert die lokale Auflösung?

dig heise.de @127.0.0.1

; <<>> DiG 9.20.15-1~deb13u1-Debian <<>> heise.de @127.0.0.1
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11410
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;heise.de.                      IN      A

;; ANSWER SECTION:
heise.de.               86400   IN      A       193.99.144.80

;; Query time: 43 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Mon Dec 15 10:24:09 CET 2025
;; MSG SIZE  rcvd: 53

Checke das log:

$ sudo tail /var/log/pihole/pihole.log

Dec 15 10:24:09 dnsmasq[882]: query[A] heise.de from 127.0.0.1
Dec 15 10:24:09 dnsmasq[882]: forwarded heise.de to 127.0.0.1#5335
Dec 15 10:24:09 dnsmasq[882]: reply heise.de is 193.99.144.80

Manche blockierte URLs will ich doch freigeben, z.B. für Kommentarfunktionen auf blogs. Electrek.co nutzt einen Dienst namens spot.im, den ich als regex komplett freigegeben habe: Domains > List of Domains.

Zusätzliche Blocklisten können hilfreich sein. Einige finden sich auf https://github.com/RPiList/specials/blob/54876178ffa7e4d1224ac81b00bedd0040f65802/Blocklisten.md.

Done!

via