Raspberry Pi dédiée hors cluster : Pi-hole comme serveur DNS/DHCP, PiVPN OpenVPN pour un accès distant sécurisé aux services auto-hébergés.
Le cluster Kubernetes expose plusieurs services (Immich, Gitea, Docker Registry, Joplin, Radicale) que je voulais pouvoir atteindre de façon sécurisée depuis internet, sans les exposer directement. Plutôt que de gérer un reverse proxy public, j’ai opté pour un VPN : une Raspberry Pi dédiée, hors cluster, fait office de passerelle réseau.
Cette même machine héberge Pi-hole, qui filtre les publicités et les trackers pour tout le réseau local.
Pi-hole fonctionne comme résolveur DNS : en pointant le DNS des équipements vers lui, il peut bloquer les domaines publicitaires avant même la requête. Mais la Livebox ne permet pas de spécifier un serveur DNS personnalisé distribué par son DHCP. Résultat : impossible de forcer les équipements à utiliser Pi-hole via la box.
La solution retenue consiste à désactiver le serveur DHCP de la Livebox et à activer celui de Pi-hole. C’est désormais Pi-hole qui attribue les adresses IP à tous les équipements du réseau, et qui leur pousse en même temps son adresse comme serveur DNS.
Avantage supplémentaire : Pi-hole connaît le nom et l’IP de chaque équipement du réseau. Les nœuds du cluster, les téléphones, les ordinateurs — tous sont déclarés avec leurs hostnames dans Pi-hole, ce qui simplifie la résolution de noms en local sans toucher aux fichiers /etc/hosts de chaque machine.
Une fois connecté au VPN depuis internet, le trafic est tunnelisé vers le réseau local. Cela me permet d’accéder à tous les services du cluster comme si j’y étais physiquement, sans ouvrir d’autres ports que celui du VPN sur la box.
PiVPN simplifie l’installation d’OpenVPN sur Raspberry Pi et la gestion des certificats clients.
La configuration d’OpenVPN est la suivante (informations sensibles anonymisées) :
dev tun
proto udp
port <VPN-port>
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/<hostname>.crt
key /etc/openvpn/easy-rsa/pki/private/<hostname>.key
dh none
ecdh-curve prime256v1
topology subnet
server 10.18.193.0 255.255.255.0
# DNS Pi-hole poussé aux clients VPN
push "dhcp-option DNS <IP-pihole>"
push "dhcp-option DOMAIN cluster"
# Prévention des fuites DNS sous Windows
push "block-outside-dns"
# Tunnel complet : tout le trafic client passe par le VPN
push "redirect-gateway def1 bypass-dhcp"
# Route vers le réseau local
push "route 192.168.1.0 255.255.255.0"
client-to-client
client-config-dir /etc/openvpn/ccd
keepalive 15 120
remote-cert-tls client
tls-version-min 1.2
tls-crypt /etc/openvpn/easy-rsa/pki/ta.key
cipher AES-256-CBC
auth SHA256
# Abandon des privilèges après démarrage
user openvpn
group openvpn
persist-key
persist-tun
crl-verify /etc/openvpn/crl.pem
status /var/log/openvpn-status.log 20
status-version 3
verb 3
Points notables de cette configuration :
dh.pem à générertls-crypt — chiffre et authentifie les paquets TLS avant même la négociation : protège contre le scanning de port et les attaques par déni de service sur le handshakeuser openvpn / group openvpn — le daemon abandonne ses privilèges root après démarrageredirect-gateway def1 — tout le trafic client passe par le tunnel, évitant les fuitesUne couche de filtrage iptables est mise en place pour limiter les connexions entrantes sur la Raspberry Pi :
Ces règles sont persistées via iptables-persistent pour survivre aux redémarrages.
Sur Android, même en étant connecté au VPN en mode tunnel complet (redirect-gateway def1), les requêtes DNS peuvent contourner le serveur poussé par le serveur VPN. Android dispose d’une fonctionnalité Private DNS (DNS-over-TLS) qui prend la priorité sur le DNS distribué par le DHCP ou le VPN, court-circuitant Pi-hole.
Désactiver le Private DNS dans les paramètres réseau Android (Réseau → DNS privé → Désactivé). Une fois cette option coupée, Android utilise le DNS poussé par OpenVPN — l’IP de Pi-hole — et le blocage de publicités fonctionne correctement y compris depuis le mobile en itinérance.
Une fois connecté, tous les services deviennent accessibles via leurs noms de domaine internes :
| Service | Domaine interne |
|---|---|
| Immich | immich.cluster |
| Gitea | gitea.cluster |
| Docker Registry | registry.cluster |
| Joplin | joplin.cluster |
| Radicale | radicale.cluster |
Traefik, l’ingress controller du cluster, gère le routage et les certificats TLS internes. Pi-hole résout les noms en .cluster vers le control plane, Traefik dispatch vers le bon service.
OpenVPN fonctionne mais WireGuard offre de meilleures performances (latence, vitesse de négociation) et une surface d’attaque plus petite (base de code ~4 000 lignes vs ~100 000 pour OpenVPN). La migration vers WireGuard via PiVPN est prévue.