Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

IdeoLab AccessLog — v0.1.0

Addon Django “observabilité + défense active” : AccessLog (log des requêtes utiles — 200 only par défaut), TrashIP (détection scans/abuse), iptables réel (ban/unban), ban temporaire TTL (ban_until + cron), audit (FirewallActionLog), stats (admin + Chart.js).

Télécharger Lien direct Version 0.1.0 /static/toolbox/ App ideolab_accesslog
Firewall : l’exécution iptables est désactivée par défaut (TRASHIP_FIREWALL_EXECUTE=False). Active uniquement sur un serveur Linux qui possède iptables (prod), pas sur Windows/WAMP.
Ce que fait exactement la v0.1.0
  • AccessLog Log “propre” : uniquement les HTTP 200 (par défaut) + durée, view_name, UA, referer, user, session, XFF.
  • TrashIP Les 404 répétitifs (scan/bruteforce) ne polluent pas AccessLog : ils alimentent une table “poubelle” avec compteurs.
  • Sensitive block Les chemins sensibles (.php, /.env, /wp-*, /.git…) sont bloqués (403) et tracés.
  • Ban TTL Depuis l’admin : BAN 24h / 7j / permanent + UNBAN.
  • Cron unban_expired débannit automatiquement à l’expiration (ban_until).
  • Audit FirewallActionLog stocke : qui, action, commande, rc, stdout, stderr.
  • Stats Écran admin stats : bans/unbans + top scanners (Chart.js).
Design intention : AccessLog = signal utile (200), TrashIP = bruit suspect (404/sensitive), Firewall = action contrôlée + audit.
Composants livrés
ÉlémentContenuPourquoi
MiddlewareAccessLogMiddlewareCapture requêtes + classification + compteurs + blocages
ModelsAccessLog / TrashIP / FirewallActionLogHistorique + “poubelle” + audit
AdminAccessLogAdmin / TrashIPAdmin / FirewallActionLogAdminExploration + ban/unban + stats
Commandscleanup_accesslog / unban_expiredRétention + TTL auto-revert
Templatesadmin/accesslog_stats.htmlGraphes Chart.js
Windows/WAMP : tu testes logging/TrashIP/admin/stats sans firewall. Le firewall s’active en prod Linux.
Installation

Installation depuis l’archive (URL) ou en offline. Puis activation dans Django.

1) Installer via URL
Terminal
pip install https://www.ideo-lab.com/static/toolbox/accesslog-0.1.0.tar.gz
2) Installer en offline
Terminal
curl -O https://www.ideo-lab.com/static/toolbox/accesslog-0.1.0.tar.gz
pip install ./accesslog-0.1.0.tar.gz
3) Activer l’app + middleware
settings.py
INSTALLED_APPS += [
    "ideolab_accesslog",
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "ideolab_accesslog.middleware.AccessLogMiddleware",
    # ...
] + MIDDLEWARE[1:]
4) Migrations
Terminal
python manage.py migrate
5) Smoke test
Terminal
python manage.py check
python -c "import ideolab_accesslog; print('OK')"
Settings (complets)

Ci-dessous : tous les réglages utiles. Tu peux copier-coller et ensuite ajuster.

A) AccessLog (logging utile)
Recommandation prod : garder ACCESSLOG_STATUS_CODES=[200] pour éviter la pollution.
settings.py — AccessLog
ACCESSLOG_ENABLED = True

# Log uniquement les codes utiles (par défaut: 200)
ACCESSLOG_STATUS_CODES = [200]

# Sampling (1.0 = 100%). Exemple: 0.2 = 20% des 200.
ACCESSLOG_SAMPLE_RATE = 1.0

# Exclusions (évite /static + assets)
ACCESSLOG_EXCLUDE_PREFIXES = [
    "/static/", "/media/", "/favicon.ico", "/robots.txt",
]
ACCESSLOG_EXCLUDE_EXTENSIONS = [
    ".css", ".js", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".ico",
    ".woff", ".woff2", ".map",
]
B) Reverse proxy (IP réelle)
nginx.conf
proxy_set_header Host              $host;
proxy_set_header X-Real-IP         $remote_addr;
proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host  $host;
proxy_set_header X-Forwarded-Proto $scheme;
C) TrashIP (anti-scan + paths sensibles)
Principe : les 404 suspects vont dans TrashIP (compteurs). Les paths sensibles peuvent être bloqués (403).
settings.py — TrashIP
TRASHIP_ENABLED = True

# Burst de 404 par IP (fenêtre glissante en cache)
TRASHIP_404_WINDOW_S = 600        # 10 minutes
TRASHIP_404_THRESHOLD = 200       # seuil (utile si auto-ban, sinon analytics)

# Si True: bloque immédiatement les paths sensibles + trace en TrashIP
TRASHIP_BLOCK_SENSITIVE = True

TRASHIP_SENSITIVE_SUBSTRINGS = [
    "/wp-", "/wordpress", "/wp-admin", "/wp-login", "/xmlrpc.php",
    "/.env", "/.git", "/.svn", "/.hg",
    "/phpmyadmin", "/pma",
    "/admin.php", "/login.php",
]

TRASHIP_SENSITIVE_SUFFIXES = [
    ".php", ".asp", ".aspx", ".cgi", ".pl",
    ".bak", ".old", ".sql", ".zip", ".tar", ".gz",
]

# Si True: si IP est_banned=True en DB, middleware répond 403
TRASHIP_BLOCK_BANNED = True

# Optionnel : auto-ban sur seuil 404 (désactivé recommandé)
TRASHIP_AUTO_BAN = False
D) Firewall (iptables) — exécution réelle
Important : activer uniquement sur serveur Linux. L’exécution passe par un helper root whitelisté + sudoers.
settings.py — Firewall
# Exécution firewall depuis l'admin + cron (False par défaut)
TRASHIP_FIREWALL_EXECUTE = False
TRASHIP_FIREWALL_TIMEOUT_S = 3

# Helper recommandé (ban/unban/check) :
# /usr/local/sbin/ideolab-fw-ip {ban|unban|check} <ip>
TRASHIP_FIREWALL_HELPER = ["/usr/bin/sudo", "/usr/local/sbin/ideolab-fw-ip"]
Comportement exact du middleware

Le middleware classe chaque requête et applique la bonne action (log, trash, block).

Règles de décision
CasRésultatStockageAction
HTTP 200 (non exclu)Requête utileAccessLogLog (selon ACCESSLOG_SAMPLE_RATE)
HTTP 404 (répétitif)Scan probableTrashIPIncr compteur (cache) + upsert TrashIP (reason=404_burst)
Path sensible (ex: /.env, .php)MalveillantTrashIP403 immédiat + upsert TrashIP (reason=sensitive_path)
IP DB bannieInterdite-403 immédiat (si TRASHIP_BLOCK_BANNED)
Ce qui est loggé dans AccessLog (rappel)
  • ip, forwarded_for (XFF), user (si auth), session_key
  • method, host, path, query_string, referer
  • user_agent, accept_language
  • status_code, response_bytes (si dispo), duration_ms, view_name
Conseil : si tu veux logger d’autres codes (ex: 302), ajoute-les à ACCESSLOG_STATUS_CODES.
Django Admin (présentation + usage)

L’admin est le cockpit : exploration logs (200), analyse scanners, ban/unban, audit, stats.

A) AccessLog (lecture)
  • But : voir le trafic réel “utile” (pages/temps/référents/UA).
  • Par défaut : contient principalement les 200 (et pas les 404).
  • Champs clés : ts, ip, path, status_code, duration_ms, view_name.
Astuce : utilise search_fields sur IP / path / UA pour diagnostiquer un incident.
B) TrashIP (table poubelle)
  • But : stocker les IP suspectes : scans 404, accès sensibles, abus.
  • Compteurs : count_hits, count_404, count_sensitive.
  • Infos : last_path, last_user_agent, reason, last_seen.
  • Statut : is_banned, ban_until, iptables_applied.
Pourquoi TrashIP ? tu gardes le bruit suspect dans une table séparée (analysable + actionnable).
C) Actions admin (TrashIP)
ActionEffet DBEffet firewallAudit
🔥 BAN 24his_banned=True, ban_until=now+24hiptables DROP (via helper)FirewallActionLog (ban)
🔥 BAN 7jis_banned=True, ban_until=now+7diptables DROPFirewallActionLog (ban)
🔥 BAN permanentis_banned=True, ban_until=NULLiptables DROPFirewallActionLog (ban)
🧯 UNBAN maintenantis_banned=False, ban_until=NULLiptables rule removeFirewallActionLog (unban)
🔍 CHECKmaj iptables_applied (si implémenté)-C INPUT -s IP -j DROPFirewallActionLog (check)
Audit : toutes les actions firewall écrivent dans FirewallActionLog (actor, rc, stdout, stderr, commande).
D) Écran stats (Chart.js)
  • URL : /admin/.../traship/stats/
  • Graphe : bans / unbans par jour (source : FirewallActionLog)
  • Table : top scanners (count_404) + bans actifs (ban_until)
Note MySQL/MariaDB timezone : si tu n’as pas les TZ tables, évite les widgets admin de type date_hierarchy.
Firewall (ban/unban réel) + TTL ban_until

Le but : exécuter iptables “pour de vrai”, mais de façon sécurisée et réversible, avec trace SQL.

Règle d’or : Django ne doit pas exécuter iptables via shell. Utilise un helper root whitelisté (sudoers) qui valide l’IP.
Helper recommandé : ideolab-fw-ip
  • Interface : ideolab-fw-ip ban <ip>, unban <ip>, check <ip>
  • Validation stricte IP (regex), pas d’injection.
  • Support IPv4/IPv6 (iptables/ip6tables).
  • Anti-doublon : check avant insert ; unban supprime toutes occurrences.
Sudoers (exemple Linux)
Remplace www-data par l’utilisateur réel du process Django (gunicorn/uwsgi). Cette règle autorise uniquement ce helper.
/etc/sudoers (via visudo)
www-data ALL=(root) NOPASSWD: /usr/local/sbin/ideolab-fw-ip *
TTL : comment ça marche
  • Action admin “BAN 24h” : ban_until = now + 24h (DB) + iptables DROP.
  • Action admin “BAN 7j” : ban_until = now + 7j + iptables DROP.
  • Action “BAN permanent” : ban_until = NULL + iptables DROP.
  • Cron unban_expired : si ban_until <= now ⇒ unban iptables + DB reset.
  • Audit : chaque ban/unban (admin ou cron) est loggé dans FirewallActionLog.
Objectif : ban rapide + réversible + traçable, sans faux positifs irréversibles.
Cron : exécution, logs, validation

Deux jobs recommandés : (1) unban_expired (fréquent) et (2) cleanup_accesslog (quotidien).

A) unban_expired (revert TTL)
Pourquoi fréquent ? Pour débannir rapidement quand un TTL expire, sans intervention humaine.
Test manuel
python manage.py unban_expired --dry-run
python manage.py unban_expired
crontab (Linux) — toutes les 5 minutes
*/5 * * * * /path/to/venv/bin/python /path/to/manage.py unban_expired >> /var/log/ideolab_unban_expired.log 2>&1
Pré-requis : sur serveur Linux : iptables + helper + sudoers + TRASHIP_FIREWALL_EXECUTE=True.
B) cleanup_accesslog (rétention)
But : maîtriser la volumétrie et respecter une rétention (RGPD).
Test manuel
python manage.py cleanup_accesslog --dry-run
python manage.py cleanup_accesslog --accesslog-days 30 --traship-days 180
crontab (Linux) — quotidien 03:20
20 3 * * * /path/to/venv/bin/python /path/to/manage.py cleanup_accesslog --accesslog-days 30 --traship-days 180 >> /var/log/ideolab_cleanup.log 2>&1
Politique suggérée : AccessLog 7–30j ; TrashIP non-banned 90–180j ; bannies conservées plus longtemps (forensic).
C) Où mettre les cron ?
Linux (prod)
crontab -e (user service) ou /etc/cron.d/
Docker
idéal : scheduler externe (K8s CronJob) ou sidecar cron
Windows/WAMP
Task Scheduler (sans iptables), utile pour cleanup/stats
Exemples d’utilisation (concrets)

Scénarios “réels” : vérifier le logging, analyser un scan, bannir 24h, vérifier l’audit, tester le cron.

1) Vérifier que le logging 200 fonctionne
  • Visite une page normale (HTTP 200) → tu dois voir une entrée dans AccessLog (admin).
  • Visite un 404 volontaire → pas dans AccessLog, mais potentiellement dans TrashIP (si répétitif).
Exemple d’URL test
# 200
https://ton-site.tld/

# 404 (une fois = rien de spécial ; répété = TrashIP)
https://ton-site.tld/this-should-404-123
2) Déclencher un “scan 404” (test contrôlé)
Test local seulement : fais quelques requêtes 404 depuis une IP unique, pour voir count_404 augmenter.
curl (exemple)
for i in $(seq 1 20); do
  curl -s -o /dev/null -w "%{http_code}\n" https://ton-site.tld/nope-$i
done
3) Ban 24h depuis l’admin (prod Linux)
  • Admin → TrashIP → sélectionner l’IP → action “🔥 BAN 24h”.
  • DB : is_banned=True, ban_until rempli, iptables_applied=True.
  • Firewall : DROP effectif.
  • Audit : une ligne dans FirewallActionLog.
4) Vérifier le revert automatique (cron)
  • Mettre un ban_until dans le passé (test) puis lancer :
Test cron
python manage.py unban_expired --dry-run
python manage.py unban_expired
Résultat attendu : iptables unban + DB reset + audit log “expired ban_until”.
5) Lire les stats (Chart.js)
  • Admin → TrashIP → lien / page stats/
  • Observer la courbe bans/unbans + le top scanners.
Troubleshooting

Problèmes fréquents et fixes rapides (ceux que tu as déjà rencontrés).

A) Python 3.8 : “TypeError: 'type' object is not subscriptable”
Cause : annotations type Python 3.9+ (ex: list[str]) sur Python 3.8.
Fix : utiliser typing.List / typing.Tuple.
B) Admin : “path is not defined”
Cause : oubli from django.urls import path dans admin.
Fix : ajouter l’import.
C) “Database returned an invalid datetime value” (MySQL/MariaDB)
Cause : conversions timezone DB (tables tz manquantes), widgets admin type date_hierarchy.
Fix : désactiver date_hierarchy ou charger les TZ tables MySQL/MariaDB.
D) Firewall ne s’exécute pas
  • Vérifier TRASHIP_FIREWALL_EXECUTE=True (prod Linux)
  • Vérifier TRASHIP_FIREWALL_HELPER (path correct)
  • Vérifier sudoers (NOPASSWD sur le helper uniquement)
  • Lire FirewallActionLog (rc + stderr)
Exploitation & RGPD

Bonnes pratiques : perf, volumétrie, rétention, conformité, et stratégie anti-abus.

Performance / volumétrie
  • Garder ACCESSLOG_STATUS_CODES=[200] en prod (signal).
  • Activer ACCESSLOG_SAMPLE_RATE si trafic très élevé (ex: 0.2).
  • Planifier cleanup_accesslog pour éviter l’explosion DB.
Stratégie sécurité recommandée
  • Détection (TrashIP) → action admin (ban TTL) → cron (auto-unban) → audit (FirewallActionLog).
  • Éviter l’auto-ban agressif sur 404 (faux positifs), préférer l’analyse + ban TTL.
  • Si très gros volume d’IPs bannies : envisager nftables sets (v0.2.0).
RGPD
IP = donnée personnelle (UE). Limiter la rétention, documenter la finalité (sécurité/diagnostic), purger régulièrement, et restreindre l’accès admin.
Rétention conseillée : AccessLog 7–30 jours ; TrashIP non-banned 90–180 jours ; bannies plus longtemps si besoin forensic.