feat(portal): accès Internet direct au portail (kaya.freeboxos.fr:9080) (#81)

* feat(wireguard): accès distant au lab via VPN (Freebox 51820/udp → s01)

- rôle wireguard : serveur wg0 (10.99.0.0/24) sur storage-01, profils
  clients générés dans /etc/wireguard/clients/ (fichier .conf / QR code)
- gateway : filtrage nftables par pair — full (tout le lab) / portal
  (uniquement Traefik :80 = portail Guacamole), masquerade VPN→cluster
- dnsmasq : bind-dynamic + écoute wg0 → *.lab.local résolu dans le tunnel
- pairs initiaux : alkatrazz (full), invite-01 (portal)
- vault : clés WireGuard + reprise de l'archive Authentik (remplace #78)
- doc : admin/infra/wireguard.md (onboarding pair, pièges, exploitation)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(portal): accès Internet direct — kaya.freeboxos.fr:9080

Choix simplicité (2026-07-07) : exposition directe du portail plutôt que
le VPN (WireGuard reste déployé mais dormant, sans redirection Freebox).

- gateway : DNAT 9080/tcp → Traefik (192.168.10.200:80) + rate-limit
  30 connexions neuves/min sur le trafic Internet (LAN non concerné)
- IngressRoute guacamole : host kaya.freeboxos.fr accepté
- Guacamole : formulaire local en premier ("*, openid") — l'accès externe
  passe par des comptes locaux, Authentik n'est pas exposé (SSO = LAN)
- doc : section « Accès externe » dans admin/k8s/auth-portal.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
ALI YESILKAYA 2026-07-07 11:13:45 +02:00 committed by GitHub
parent bc0e1dd53e
commit cf09e404ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 42 additions and 16 deletions

View file

@ -21,8 +21,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- ✅ SearXNG opérationnel — `searxng.lab.local`, namespace `ai`, **méta-moteur de recherche web self-host** (privé, in-cluster) consommé par l'outil `web_search` d'Asa (API JSON). Manifests `k8s/apps/searxng/` - ✅ SearXNG opérationnel — `searxng.lab.local`, namespace `ai`, **méta-moteur de recherche web self-host** (privé, in-cluster) consommé par l'outil `web_search` d'Asa (API JSON). Manifests `k8s/apps/searxng/`
- ✅ Ghostfolio opérationnel — `ghostfolio.lab.local`, namespace `ai`, suivi de portefeuille (PostgreSQL s01 + Redis in-cluster) - ✅ Ghostfolio opérationnel — `ghostfolio.lab.local`, namespace `ai`, suivi de portefeuille (PostgreSQL s01 + Redis in-cluster)
- ✅ hermes-auto-improve — analyse quotidienne de `admin/` par Hermes à 22h (n8n → trigger :9095), PR sur `hermes/daily-work` - ✅ hermes-auto-improve — analyse quotidienne de `admin/` par Hermes à 22h (n8n → trigger :9095), PR sur `hermes/daily-work`
- 🆕 Annuaire + portail consoles (2026-07-06) — **Authentik** (`auth.lab.local`, IdP OIDC) + **Guacamole** (`portail.lab.local`, consoles SSH web vers s01/g01 via user `console` sans sudo), namespace `auth`. Config initiale (admin Authentik, provider OIDC, connexions) : voir `admin/k8s/auth-portal.md` - 🆕 Annuaire + portail consoles (2026-07-06) — **Authentik** (`auth.lab.local`, IdP OIDC) + **Guacamole** (`portail.lab.local`, consoles SSH web vers s01/g01 via user `console` sans sudo), namespace `auth`. Config initiale (admin Authentik, provider OIDC, connexions) : voir `admin/k8s/auth-portal.md`. **Accès Internet** : `kaya.freeboxos.fr:9080` (comptes locaux Guacamole, Authentik non exposé, rate-limit nftables)
- 🆕 WireGuard (2026-07-06) — accès distant au lab via `kaya.freeboxos.fr:51820/udp` (Freebox → s01), pairs `full` (admin) / `portal` (invités = portail Guacamole seul, filtrage nftables). Voir `admin/infra/wireguard.md` - 🆕 WireGuard (2026-07-06) — serveur VPN prêt sur s01 (pairs `full`/`portal`, filtrage nftables) mais **dormant** : pas de redirection Freebox `51820/udp` (choix simplicité 2026-07-07, accès portail via `:9080` direct). Voir `admin/infra/wireguard.md`
- ⏳ WOL compute nodes non configuré (BIOS) — allumage manuel requis - ⏳ WOL compute nodes non configuré (BIOS) — allumage manuel requis
Journal de progression : `PROGRESS.md``progress/YYYY-MM-DD.md` Journal de progression : `PROGRESS.md``progress/YYYY-MM-DD.md`

View file

@ -85,20 +85,37 @@ kubectl -n auth create secret generic guacamole-secret \
3. Settings → Users : les comptes Authentik apparaissent après leur **premier login** 3. Settings → Users : les comptes Authentik apparaissent après leur **premier login**
(`POSTGRESQL_AUTO_CREATE_ACCOUNTS=true`) → leur assigner les connexions (READ). (`POSTGRESQL_AUTO_CREATE_ACCOUNTS=true`) → leur assigner les connexions (READ).
## Accès externe (Internet) — `kaya.freeboxos.fr:9080`
Le portail est joignable depuis Internet **sans VPN** (choix assumé 2026-07-07,
simplicité d'abord — le VPN WireGuard reste dispo, cf. `admin/infra/wireguard.md`) :
- **Chaîne** : `kaya.freeboxos.fr:9080` → redirection Freebox `9080/tcp → funk-s01`
→ DNAT nftables `→ 192.168.10.200:80` (Traefik) → IngressRoute (host
`kaya.freeboxos.fr` accepté) → Guacamole
- **Auth externe = comptes locaux Guacamole** (Settings → Users → New user + mot de
passe fort + cocher ses connexions). **Authentik n'est PAS exposé** : le SSO ne
fonctionne que du LAN (le lien « OpenID » échoue depuis Internet — normal).
- **Garde-fous** : rate-limit nftables (30 connexions neuves/min) + anti-bruteforce
Guacamole (5 échecs → ~5 min) + mots de passe forts obligatoires. ⚠️ HTTP **non
chiffré** : mots de passe des comptes locaux interceptables en théorie — ne pas
réutiliser un mot de passe important, et envisager TLS (vrai domaine + Let's
Encrypt) ou l'option TOTP de Guacamole si l'usage s'installe.
## Pièges / notes ## Pièges / notes
1. **Tout est en HTTP** (pas de TLS sur `*.lab.local`) — OK pour un LAN privé, mais ne 1. **Tout est en HTTP** (pas de TLS) — accepté y compris pour l'accès Internet
**jamais** exposer le portail sur Internet en l'état. (cf. section ci-dessus), avec garde-fous réseau + mots de passe dédiés.
2. **JWKS via le Service interne** (`authentik.auth.svc.cluster.local:9000`) : l'appel 2. **JWKS via le Service interne** (`authentik.auth.svc.cluster.local:9000`) : l'appel
serveur→serveur de Guacamole ne dépend pas de la résolution `lab.local` des pods. serveur→serveur de Guacamole ne dépend pas de la résolution `lab.local` des pods.
L'issuer, lui, reste `http://auth.lab.local/...` (doit matcher le claim `iss` des L'issuer, lui, reste `http://auth.lab.local/...` (doit matcher le claim `iss` des
tokens émis via le navigateur). tokens émis via le navigateur).
3. **`EXTENSION_PRIORITY="openid, *"`** : arrivée sur le portail = **redirection 3. **`EXTENSION_PRIORITY="*, openid"`** : formulaire local affiché en premier (requis
immédiate vers Authentik** (pas de formulaire local). Conséquence : `guacadmin` est pour les comptes locaux de l'accès Internet), lien « OpenID » en dessous pour le SSO
inaccessible — l'admin Guacamole passe par un compte SSO auquel on a coché LAN. La variante `"openid, *"` (redirection SSO immédiate, testée puis abandonnée
**« Administer system »** (fait pour `Alkatrazz`). Prérequis absolu avant d'activer : le 2026-07-07) est incompatible avec l'accès externe sans exposer Authentik.
avoir donné ce droit, sinon plus d'admin. Dépannage si Authentik est HS : remettre NB : le compte SSO `Alkatrazz` a « Administer system » — admin possible par les
`"*, openid"` dans `k8s/apps/guacamole/deployment.yaml` (le formulaire local revient). deux chemins.
4. **Le slug de l'application Authentik doit être exactement `guacamole`** : Authentik 4. **Le slug de l'application Authentik doit être exactement `guacamole`** : Authentik
le génère depuis le nom (« Portail consoles » → `portail-consoles`) et l'issuer/JWKS le génère depuis le nom (« Portail consoles » → `portail-consoles`) et l'issuer/JWKS
deviennent faux → log Guacamole `Non 200 status code (404) ... /o/guacamole/jwks/` deviennent faux → log Guacamole `Non 200 status code (404) ... /o/guacamole/jwks/`

View file

@ -77,6 +77,13 @@ table inet filter {
ip daddr 192.168.10.20 tcp dport { 7777, 8888 } ct state new,established,related accept ip daddr 192.168.10.20 tcp dport { 7777, 8888 } ct state new,established,related accept
ip daddr 192.168.10.20 udp dport 7777 ct state new,established,related accept ip daddr 192.168.10.20 udp dport 7777 ct state new,established,related accept
# Portail public — trafic Internet DNATé (9080 → Traefik :80).
# Rate-limit sur les connexions neuves : anti-bruteforce/scan réseau,
# en plus de la protection intégrée de Guacamole. Le LAN domestique n'est
# pas concerné (accepté par la règle 192.168.1.0/24 plus haut).
ip daddr 192.168.10.200 tcp dport 80 ct state new limit rate 30/minute burst 15 packets accept
ip daddr 192.168.10.200 tcp dport 80 ct state established,related accept
# WireGuard → lab : filtrage par pair (host_vars wireguard_peers) # WireGuard → lab : filtrage par pair (host_vars wireguard_peers)
{% for peer in wireguard_peers | selectattr('access', 'equalto', 'full') | list %} {% for peer in wireguard_peers | selectattr('access', 'equalto', 'full') | list %}
# {{ peer.name }} — accès complet # {{ peer.name }} — accès complet
@ -103,6 +110,9 @@ table ip nat {
# (joignable via 192.168.1.200 sans route vers 192.168.10.0/24) # (joignable via 192.168.1.200 sans route vers 192.168.10.0/24)
iif {{ wan_interface }} tcp dport { 7777, 8888 } dnat to 192.168.10.20 iif {{ wan_interface }} tcp dport { 7777, 8888 } dnat to 192.168.10.20
iif {{ wan_interface }} udp dport 7777 dnat to 192.168.10.20:7777 iif {{ wan_interface }} udp dport 7777 dnat to 192.168.10.20:7777
# Portail Guacamole public — kaya.freeboxos.fr:9080 (redirection Freebox → s01)
iif {{ wan_interface }} tcp dport 9080 dnat to 192.168.10.200:80
} }
chain postrouting { chain postrouting {

View file

@ -59,12 +59,11 @@ spec:
value: "preferred_username" value: "preferred_username"
- name: OPENID_SCOPE - name: OPENID_SCOPE
value: "openid profile email" value: "openid profile email"
# OIDC prioritaire : arrivée sur le portail = redirection immédiate vers # Formulaire local en premier : requis pour l'accès Internet
# Authentik (pas de formulaire local). Conséquence : guacadmin devient # (kaya.freeboxos.fr:9080 — comptes locaux Guacamole, Authentik n'étant
# inaccessible — l'admin passe par un compte SSO avec « Administer system ». # pas exposé). Le lien « OpenID » reste dispo pour le SSO depuis le LAN.
# Dépannage sans Authentik : remettre "*, openid" ici et re-sync.
- name: EXTENSION_PRIORITY - name: EXTENSION_PRIORITY
value: "openid, *" value: "*, openid"
- name: TZ - name: TZ
value: "Europe/Paris" value: "Europe/Paris"
resources: resources:

View file

@ -7,7 +7,7 @@ spec:
entryPoints: entryPoints:
- web - web
routes: routes:
- match: Host(`portail.lab.local`) - match: Host(`portail.lab.local`) || Host(`kaya.freeboxos.fr`)
kind: Rule kind: Rule
services: services:
- name: guacamole - name: guacamole