mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-08-16 18:40:05 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
032611e544 | ||
|
|
8630e808a3 | ||
|
|
7c6b3969ab |
@@ -1,3 +1,73 @@
|
||||
secubox-haproxy (1.8.0-1~bookworm1) bookworm; urgency=high
|
||||
|
||||
* Cette version REUNIT deux corrections qui vivaient sur des branches
|
||||
separees, et dont l'une avait efface l'autre sur la board : un paquet
|
||||
construit depuis master a fait perdre le verbe `cert sync` de la 1.6.4,
|
||||
jamais fusionne. Le renouvellement automatique des certificats etait donc
|
||||
casse en silence — les certificats servis restaient valables, mais rien ne
|
||||
recopiait plus les renouvellements vers HAProxy.
|
||||
|
||||
secubox-haproxy (1.7.1-1~bookworm1) bookworm; urgency=high
|
||||
|
||||
* HAProxy servait des certificats que le renouvellement ne mettait jamais a
|
||||
jour (ref #1019). certbot renouvelle dans /etc/letsencrypt/live ; HAProxy
|
||||
sert un fichier CONCATENE dans /data/haproxy/certs. Rien ne recopiait l'un
|
||||
vers l'autre : aucun hook n'existait, ni par certificat ni dans les
|
||||
repertoires globaux, tous deux vides.
|
||||
* Le defaut etait SILENCIEUX. Le renouvellement reussit, les journaux de
|
||||
certbot sont propres, le site repond — jusqu'au jour ou la copie servie
|
||||
expire, des semaines plus tard, et le lien de cause a effet est alors
|
||||
indechiffrable.
|
||||
* Constate sur gk2 : trois certificats sur six divergeaient, dont un qui
|
||||
serait tombe le 14 octobre alors qu'une version valide jusqu'au 2 novembre
|
||||
dormait deja sur le disque, inutilisee.
|
||||
* Nouveau `haproxyctl cert sync` : reconstruit les .pem depuis
|
||||
/etc/letsencrypt/live, compare le CONTENU et non les dates — un mtime plus
|
||||
recent ne prouve pas qu'un fichier a change, et une copie touchee a la main
|
||||
aurait un mtime recent tout en servant un certificat perime. Ecriture par
|
||||
renommage, sans quoi un .pem tronque ferait echouer le rechargement pour
|
||||
TOUS les vhosts. Ne recharge que si quelque chose a change.
|
||||
* Un hook de deploiement certbot l'appelle apres chaque renouvellement reussi.
|
||||
Livre par le paquet, pas pose a la main — sans quoi il disparaitrait a la
|
||||
prochaine reinstallation, comme le reste.
|
||||
* `cert sync` NE RACCOURCIT JAMAIS la vie d'un certificat servi. Le premier
|
||||
jet ecrasait des que le contenu differait ; l'essai a blanc sur gk2 a montre
|
||||
le piege : deux certificats servis expiraient PLUS TARD que la copie de
|
||||
/etc/letsencrypt (live.maegia.tv, 4 novembre contre 14 octobre). Les
|
||||
synchroniser aurait raccourci leur duree de vie — l'inverse du but. Un .pem
|
||||
servi peut venir d'ailleurs qu'ACME (joker, autre outil, depot manuel) : la
|
||||
source n'est pas autoritaire par nature, seule la date d'expiration l'est.
|
||||
* `cert renew` reste ecrit pour acme.sh, absent de cette board : c'est du
|
||||
code mort ici, laisse tel quel plutot que retire a l'aveugle.
|
||||
|
||||
-- Gerald Kerma <devel@cybermind.fr> Thu, 13 Aug 2026 10:00:00 +0200
|
||||
|
||||
secubox-haproxy (1.7.2-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* DELAI RELEVE PAR REQUETE POUR LES TELEVERSEMENTS DU DEPOT (ref #1030). La
|
||||
section `defaults` porte `timeout client/server 30s`, et c'est bien : elle
|
||||
protege TOUS les vhosts d'un amont qui trainerait. Mais un depot de 22 Mio
|
||||
a mis 116 s a s'ecrire — HAProxy abandonnait a 30, le deposant voyait un
|
||||
504, ET LE SERVEUR TERMINAIT LE TRAVAIL. Chaque essai deposait a nouveau.
|
||||
* `http-request set-timeout` (HAProxy >= 2.4, la board est en 2.6) releve le
|
||||
delai POUR CES REQUETES SEULEMENT. Relever `defaults` aurait couvert le cas
|
||||
en retirant la protection a la centaine de vhosts qui n'en ont pas besoin —
|
||||
payer pour tous ce dont un seul a besoin.
|
||||
* DEUX LECONS PAYEES A L'ESSAI. `http-request set-timeout` ne vit QUE dans un
|
||||
backend — HAProxy refuse « proxy has no backend capability » cote frontend —
|
||||
et il ne connait que `server` et `tunnel` : `set-timeout client` N'EXISTE
|
||||
PAS. Les deux refus ont ete rattrapes par la validation qui precede
|
||||
l'installation : la configuration vivante n'a jamais bouge. Ce garde-fou
|
||||
vaut sa ligne.
|
||||
* `timeout client` reste a 30 s, et c'est correct : c'est un delai
|
||||
d'INACTIVITE, qu'un televersement regulier n'atteint jamais.
|
||||
* L'ACL porte sur le CHEMIN, pas sur l'hote : deux `acl` de meme nom sont un
|
||||
OU chez HAProxy, pas un ET. Nommer l'hote ET le chemin aurait releve le
|
||||
delai pour tout hote contenant « depot », ou pour ce chemin sur n'importe
|
||||
quel hote — l'inverse de ce qu'on cherche.
|
||||
|
||||
-- Gerald Kerma <devel@cybermind.fr> Thu, 13 Aug 2026 17:45:00 +0200
|
||||
|
||||
secubox-haproxy (1.6.3-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* `vhost add` est idempotent (ref #1015). Il appendait sans jamais regarder
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
override_dh_usrlocal:
|
||||
|
||||
override_dh_auto_install:
|
||||
# Hook de deploiement certbot (#1019). Sans lui, HAProxy sert des copies que
|
||||
# le renouvellement ne met jamais a jour : trois certificats sur six
|
||||
# divergeaient sur gk2, dont un qui serait tombe alors qu'une version valide
|
||||
# dormait deja sur le disque.
|
||||
install -d debian/secubox-haproxy/etc/letsencrypt/renewal-hooks/deploy
|
||||
install -m 0755 letsencrypt-hooks/secubox-haproxy debian/secubox-haproxy/etc/letsencrypt/renewal-hooks/deploy/secubox-haproxy
|
||||
install -d debian/secubox-haproxy/usr/lib/secubox/haproxy/
|
||||
cp -r api debian/secubox-haproxy/usr/lib/secubox/haproxy/
|
||||
install -d debian/secubox-haproxy/usr/share/secubox/www
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
# /etc/letsencrypt/renewal-hooks/deploy/secubox-haproxy — #1019
|
||||
#
|
||||
# certbot renouvelle dans /etc/letsencrypt/live ; HAProxy sert un fichier
|
||||
# CONCATENE (chaine + cle) dans /data/haproxy/certs. Rien ne recopiait l'un vers
|
||||
# l'autre : trois certificats sur six divergeaient sur gk2, dont un qui serait
|
||||
# tombe le 14 octobre alors qu'une version valide jusqu'au 2 novembre dormait
|
||||
# deja sur le disque.
|
||||
#
|
||||
# Le defaut etait SILENCIEUX : le renouvellement reussit, les journaux de
|
||||
# certbot sont propres, le site repond — jusqu'au jour ou la copie servie
|
||||
# expire, des semaines plus tard. Le lien de cause a effet est alors
|
||||
# indechiffrable.
|
||||
#
|
||||
# Ce hook est un DEPLOY hook : certbot ne l'appelle qu'apres un renouvellement
|
||||
# reussi, jamais sur un simple controle. `cert sync` ne recharge HAProxy que si
|
||||
# un fichier a change, donc ce hook ne coupe aucune connexion pour rien.
|
||||
set -eu
|
||||
exec /usr/sbin/haproxyctl cert sync
|
||||
@@ -727,6 +727,99 @@ cmd_cert_renew() {
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_cert_sync() {
|
||||
# Reconstruit les .pem servis par HAProxy depuis /etc/letsencrypt/live (#1019).
|
||||
#
|
||||
# POURQUOI CE VERBE EXISTE. certbot renouvelle dans /etc/letsencrypt/live ;
|
||||
# HAProxy sert un fichier CONCATENE (chaine + cle) dans $CERTS_DIR. Rien ne
|
||||
# recopiait l'un vers l'autre : aucun hook de renouvellement n'existait, et
|
||||
# `cert renew` ci-dessus est ecrit pour acme.sh, absent de cette board.
|
||||
#
|
||||
# Le defaut est SILENCIEUX. Le renouvellement reussit, les journaux sont
|
||||
# propres, le site repond — jusqu'au jour ou la copie servie expire, des
|
||||
# semaines plus tard. Le lien de cause a effet est alors indechiffrable.
|
||||
#
|
||||
# Constate sur gk2 : trois certificats sur six divergeaient, dont un qui
|
||||
# serait tombe le 14 octobre alors qu'une version valide jusqu'au 2 novembre
|
||||
# dormait deja sur le disque.
|
||||
local ecrire=1
|
||||
[ "${1:-}" = "--dry-run" ] && ecrire=0
|
||||
|
||||
local live_root="/etc/letsencrypt/live"
|
||||
[ -d "$live_root" ] || { log "cert-sync: pas de certbot sur cette board"; return 0; }
|
||||
mkdir -p "$CERTS_DIR"
|
||||
|
||||
local change=0 vus=0
|
||||
for d in "$live_root"/*/; do
|
||||
[ -d "$d" ] || continue
|
||||
local nom chaine cle cible
|
||||
nom=$(basename "$d")
|
||||
chaine="$d/fullchain.pem"
|
||||
cle="$d/privkey.pem"
|
||||
[ -f "$chaine" ] && [ -f "$cle" ] || continue
|
||||
vus=$((vus + 1))
|
||||
cible="$CERTS_DIR/$nom.pem"
|
||||
|
||||
# ON COMPARE LE CONTENU, PAS LES DATES. Un mtime plus recent ne prouve
|
||||
# pas que le contenu a change — et une copie touchee a la main aurait un
|
||||
# mtime plus recent tout en servant un certificat perime.
|
||||
local somme_src somme_dst
|
||||
somme_src=$(cat "$chaine" "$cle" | sha256sum | cut -d' ' -f1)
|
||||
somme_dst=$([ -f "$cible" ] && sha256sum "$cible" | cut -d' ' -f1 || echo "")
|
||||
[ "$somme_src" = "$somme_dst" ] && continue
|
||||
|
||||
local fin_src fin_dst
|
||||
fin_src=$(openssl x509 -in "$chaine" -noout -enddate 2>/dev/null | cut -d= -f2)
|
||||
fin_dst=$([ -f "$cible" ] && openssl x509 -in "$cible" -noout -enddate 2>/dev/null | cut -d= -f2 || echo "")
|
||||
|
||||
# ON NE RACCOURCIT JAMAIS LA VIE D'UN CERTIFICAT SERVI.
|
||||
#
|
||||
# Le premier jet ecrasait des que le contenu differait. L'essai a blanc
|
||||
# sur gk2 a montre le piege : deux certificats servis expiraient PLUS
|
||||
# TARD que la copie de /etc/letsencrypt (live.maegia.tv, 4 novembre
|
||||
# contre 14 octobre). Les synchroniser aurait raccourci leur duree de
|
||||
# vie — l'inverse exact du but.
|
||||
#
|
||||
# Un .pem servi peut venir d'ailleurs qu'ACME : joker, autre outil,
|
||||
# depot manuel. La source n'est donc pas autoritaire par nature ; seule
|
||||
# la date d'expiration l'est.
|
||||
if [ -n "$fin_dst" ]; then
|
||||
local ts_src ts_dst
|
||||
ts_src=$(date -d "$fin_src" +%s 2>/dev/null || echo 0)
|
||||
ts_dst=$(date -d "$fin_dst" +%s 2>/dev/null || echo 0)
|
||||
if [ "$ts_src" -le "$ts_dst" ]; then
|
||||
log "cert-sync: $nom — IGNORE, le certificat servi expire plus tard ($fin_dst) que la source ($fin_src)"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
change=$((change + 1))
|
||||
log "cert-sync: $nom — servi jusqu'au ${fin_dst:-absent}, remplace par $fin_src"
|
||||
|
||||
[ "$ecrire" = "1" ] || continue
|
||||
|
||||
# Ecriture par fichier temporaire puis renommage : HAProxy peut relire le
|
||||
# repertoire a tout instant, et un .pem tronque le ferait echouer au
|
||||
# rechargement — donc tomber pour TOUS les vhosts, pas seulement celui-ci.
|
||||
local tmp="$cible.nouveau"
|
||||
cat "$chaine" "$cle" > "$tmp" || { error "cert-sync: ecriture $nom impossible"; rm -f "$tmp"; continue; }
|
||||
chmod 0600 "$tmp"
|
||||
mv "$tmp" "$cible"
|
||||
done
|
||||
|
||||
if [ "$ecrire" = "0" ]; then
|
||||
log "cert-sync: $vus certificat(s), $change a mettre a jour (lecture seule)"
|
||||
return 0
|
||||
fi
|
||||
log "cert-sync: $vus certificat(s), $change mis a jour"
|
||||
|
||||
# ON NE RECHARGE QUE SI QUELQUE CHOSE A CHANGE. Recharger a chaque passage
|
||||
# coupe les connexions en cours sans raison, et ce verbe est appele apres
|
||||
# CHAQUE renouvellement — donc souvent, pour rien la plupart du temps.
|
||||
[ "$change" -gt 0 ] && cmd_reload
|
||||
return 0
|
||||
}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
# CONFIG GENERATION
|
||||
# ─────────────────────────────────────────────────────────────────────
|
||||
@@ -806,6 +899,7 @@ frontend http-in
|
||||
# garde anti-dérive refusait de régénérer — elle protégeait exactement ça.
|
||||
acl is_acme_challenge path_beg /.well-known/acme-challenge/
|
||||
use_backend acme_challenge if is_acme_challenge
|
||||
|
||||
EOF
|
||||
|
||||
if webui_regex=$(_fetch_webui_regex); then
|
||||
@@ -935,6 +1029,25 @@ EOF
|
||||
# WAF Inspector Backend (mitmproxy LXC at $waf_ip:$waf_port)
|
||||
backend mitmproxy_inspector
|
||||
mode http
|
||||
# TELEVERSEMENTS LONGS : DELAI SERVEUR RELEVE PAR REQUETE (#1030).
|
||||
#
|
||||
# La section `defaults` porte `timeout server 30s`, et c'est bien : elle
|
||||
# protege TOUS les vhosts d'un amont qui trainerait. Mais un depot de 22 Mio
|
||||
# a mis 116 s a s'ecrire sur cette board — HAProxy abandonnait a 30, le
|
||||
# deposant voyait un 504, ET LE SERVEUR TERMINAIT LE TRAVAIL. Chaque essai
|
||||
# deposait a nouveau : trois depots pour une seule intention.
|
||||
#
|
||||
# DEUX LECONS PAYEES A L'ESSAI. `set-timeout` ne vit QUE dans un backend —
|
||||
# HAProxy refuse « proxy has no backend capability » cote frontend — et il
|
||||
# ne connait que `server` et `tunnel` : `set-timeout client` n'existe pas.
|
||||
# `timeout client` reste donc a 30 s, ce qui convient : c'est un delai
|
||||
# d'INACTIVITE, et un televersement regulier ne l'atteint jamais.
|
||||
#
|
||||
# Relever `defaults` aurait couvert le cas en retirant la protection a la
|
||||
# centaine de vhosts qui n'en ont pas besoin — payer pour tous ce dont un
|
||||
# seul a besoin.
|
||||
acl est_depot_long path_beg /api/v1/droplet/depot
|
||||
http-request set-timeout server 1h if est_depot_long
|
||||
option forwardfor
|
||||
http-request set-header X-Real-IP %[src]
|
||||
# %[query] rend la chaine de requete SANS le « ? » qui l'introduit : une
|
||||
@@ -1273,6 +1386,7 @@ case "${1:-}" in
|
||||
cert)
|
||||
case "${2:-}" in
|
||||
list) cmd_cert_list ;;
|
||||
sync) cmd_cert_sync "${3:-}" ;;
|
||||
add) cmd_cert_add "$3" "$4" ;;
|
||||
renew) cmd_cert_renew ;;
|
||||
*) echo "Usage: haproxyctl cert {list|add|renew} [domain]" ;;
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
secubox-waf-ng (1.4.1-1~bookworm1) bookworm; urgency=medium
|
||||
|
||||
* `--upstream-timeout` porte de 10 s a 120 s (ref #1030). Dix secondes sont
|
||||
trop courtes pour tout point d'entree qui ecrit sur disque : un depot de
|
||||
22 Mio a mis 116 s, le WAF abandonnait a 10 s, le deposant voyait un 504 —
|
||||
et le serveur, lui, TERMINAIT le travail. Chaque essai deposait a nouveau.
|
||||
* 120 s et non « une minute de plus par securite » : c'est la duree au-dela
|
||||
de laquelle plus rien de sain ne se passe sur un point d'entree qui accuse
|
||||
reception avant d'envoyer son alerte. Assez pour un televersement honnete,
|
||||
assez court pour qu'un amont reellement mort soit encore constate comme tel.
|
||||
|
||||
-- Gerald Kerma <devel@cybermind.fr> Thu, 13 Aug 2026 17:45:00 +0200
|
||||
|
||||
secubox-waf-ng (1.3.2-1~bookworm1) bookworm; urgency=high
|
||||
|
||||
* Le WAF detectait sans jamais pouvoir bannir (ref #1017). Deux defauts
|
||||
|
||||
@@ -65,8 +65,20 @@ ExecStartPre=+/bin/chmod 0750 /var/log/secubox/cookie-audit
|
||||
ExecStartPre=+/bin/mkdir -p /var/log/secubox/waf
|
||||
ExecStartPre=+/bin/chown -R secubox-waf:secubox-waf /var/log/secubox/waf
|
||||
ExecStartPre=+/bin/chmod 0750 /var/log/secubox/waf
|
||||
# DELAI AMONT : 10 s PAR DEFAUT, TROP COURT POUR QUI ECRIT SUR DISQUE (#1030).
|
||||
#
|
||||
# Un depot de 22 Mio a mis 116 s a s'ecrire sur cette board. Le WAF abandonnait
|
||||
# a 10 s, le deposant voyait un 504 — ET LE SERVEUR TERMINAIT LE TRAVAIL. Chaque
|
||||
# essai deposait donc a nouveau : trois depots pour une seule intention. Un
|
||||
# delai mal regle devenait un amplificateur du volume recu.
|
||||
#
|
||||
# 120 s : assez pour un televersement honnete, assez court pour qu'un amont
|
||||
# reellement mort soit encore constate comme tel. Ce n'est pas « une minute de
|
||||
# plus par securite » — c'est la duree au-dela de laquelle plus rien de sain ne
|
||||
# se passe sur un point d'entree qui accuse reception avant d'envoyer l'alerte.
|
||||
ExecStart=/usr/sbin/sbxwaf \
|
||||
--listen 127.0.0.1:8085 \
|
||||
--upstream-timeout 120s \
|
||||
--routes /etc/secubox/waf/haproxy-routes.json \
|
||||
--rules /etc/secubox/waf/waf-rules.json \
|
||||
--on-demand-vhosts /etc/secubox/waf/on-demand-vhosts.json \
|
||||
|
||||
Reference in New Issue
Block a user