178 lines
6.4 KiB
TypeScript
178 lines
6.4 KiB
TypeScript
import { countRecentBans } from './fail2banDb';
|
|
import { sendEmail } from './_core/emailSender';
|
|
import { ENV } from './_core/env';
|
|
|
|
// Seuil de déclenchement de l'alerte (nombre d'IPs bannies par heure)
|
|
const ALERT_THRESHOLD = 10;
|
|
|
|
// Intervalle de vérification (en millisecondes) - toutes les 15 minutes
|
|
const CHECK_INTERVAL = 15 * 60 * 1000;
|
|
|
|
// Dernière alerte envoyée (timestamp)
|
|
let lastAlertTime = 0;
|
|
|
|
// Délai minimum entre deux alertes (1 heure)
|
|
const MIN_ALERT_INTERVAL = 60 * 60 * 1000;
|
|
|
|
/**
|
|
* Vérifie s'il y a une attaque massive et envoie une alerte email si nécessaire
|
|
*/
|
|
async function checkAndSendAlert() {
|
|
try {
|
|
const recentBans = await countRecentBans(1); // Dernière heure
|
|
|
|
console.log(`[Fail2Ban Alert] ${recentBans} bannissements dans la dernière heure`);
|
|
|
|
// Vérifier si le seuil est atteint
|
|
if (recentBans >= ALERT_THRESHOLD) {
|
|
const now = Date.now();
|
|
|
|
// Vérifier si on n'a pas déjà envoyé une alerte récemment
|
|
if (now - lastAlertTime >= MIN_ALERT_INTERVAL) {
|
|
console.log(`[Fail2Ban Alert] Seuil atteint (${recentBans} >= ${ALERT_THRESHOLD}), envoi de l'alerte...`);
|
|
|
|
await sendAlertEmail(recentBans);
|
|
|
|
lastAlertTime = now;
|
|
console.log('[Fail2Ban Alert] Alerte envoyée avec succès');
|
|
} else {
|
|
console.log('[Fail2Ban Alert] Alerte déjà envoyée récemment, pas de nouvel envoi');
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('[Fail2Ban Alert] Erreur lors de la vérification:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Envoie un email d'alerte pour une attaque massive
|
|
*/
|
|
async function sendAlertEmail(banCount: number) {
|
|
const ownerEmail = ENV.ownerName; // Utiliser l'email du propriétaire
|
|
|
|
if (!ownerEmail || !ownerEmail.includes('@')) {
|
|
console.error('[Fail2Ban Alert] Email du propriétaire non configuré');
|
|
return;
|
|
}
|
|
|
|
const subject = `🚨 Alerte Sécurité: Attaque SSH massive détectée`;
|
|
|
|
const htmlContent = `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
|
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
|
.header { background-color: #dc2626; color: white; padding: 20px; border-radius: 8px 8px 0 0; }
|
|
.content { background-color: #f9fafb; padding: 30px; border-radius: 0 0 8px 8px; }
|
|
.alert-box { background-color: #fee2e2; border-left: 4px solid #dc2626; padding: 15px; margin: 20px 0; }
|
|
.stats { background-color: white; padding: 15px; border-radius: 8px; margin: 20px 0; }
|
|
.stat-item { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #e5e7eb; }
|
|
.stat-value { font-weight: bold; color: #dc2626; }
|
|
.footer { text-align: center; color: #6b7280; font-size: 12px; margin-top: 20px; }
|
|
.button { display: inline-block; background-color: #2563eb; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; margin-top: 20px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1 style="margin: 0;">🚨 Alerte Sécurité SSH</h1>
|
|
<p style="margin: 5px 0 0 0;">Attaque massive détectée sur votre serveur</p>
|
|
</div>
|
|
<div class="content">
|
|
<div class="alert-box">
|
|
<strong>⚠️ Attention !</strong><br>
|
|
Une activité suspecte importante a été détectée sur votre serveur SSH.
|
|
</div>
|
|
|
|
<div class="stats">
|
|
<h3 style="margin-top: 0;">Statistiques de l'attaque</h3>
|
|
<div class="stat-item">
|
|
<span>IPs bannies (dernière heure)</span>
|
|
<span class="stat-value">${banCount}</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span>Seuil d'alerte</span>
|
|
<span class="stat-value">${ALERT_THRESHOLD}</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span>Date de détection</span>
|
|
<span class="stat-value">${new Date().toLocaleString('fr-FR')}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<h3>Actions recommandées</h3>
|
|
<ul>
|
|
<li>Vérifiez le tableau de bord Fail2Ban pour plus de détails</li>
|
|
<li>Examinez les logs SSH pour identifier les patterns d'attaque</li>
|
|
<li>Envisagez de renforcer temporairement les règles Fail2Ban</li>
|
|
<li>Vérifiez que vos mots de passe sont robustes</li>
|
|
</ul>
|
|
|
|
<p style="text-align: center;">
|
|
<a href="https://votre-domaine.com/admin/fail2ban" class="button">
|
|
Voir le tableau de bord Fail2Ban
|
|
</a>
|
|
</p>
|
|
|
|
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;">
|
|
<strong>Note:</strong> Cette alerte est automatiquement déclenchée lorsque plus de ${ALERT_THRESHOLD} IPs sont bannies en moins d'une heure.
|
|
Fail2Ban continue de protéger votre serveur en bannissant automatiquement les adresses IP suspectes.
|
|
</p>
|
|
</div>
|
|
<div class="footer">
|
|
<p>Cet email a été envoyé automatiquement par le système de monitoring Fail2Ban</p>
|
|
<p>Gestion des Formations Manager Itinova</p>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
const textContent = `
|
|
🚨 ALERTE SÉCURITÉ SSH
|
|
|
|
Une attaque massive a été détectée sur votre serveur.
|
|
|
|
STATISTIQUES:
|
|
- IPs bannies (dernière heure): ${banCount}
|
|
- Seuil d'alerte: ${ALERT_THRESHOLD}
|
|
- Date de détection: ${new Date().toLocaleString('fr-FR')}
|
|
|
|
ACTIONS RECOMMANDÉES:
|
|
1. Vérifiez le tableau de bord Fail2Ban
|
|
2. Examinez les logs SSH
|
|
3. Renforcez les règles Fail2Ban si nécessaire
|
|
4. Vérifiez la robustesse de vos mots de passe
|
|
|
|
Fail2Ban continue de protéger votre serveur automatiquement.
|
|
|
|
---
|
|
Gestion des Formations Manager Itinova
|
|
`;
|
|
|
|
await sendEmail({
|
|
to: ownerEmail,
|
|
subject,
|
|
html: htmlContent,
|
|
text: textContent,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Initialise le système d'alertes Fail2Ban
|
|
*/
|
|
export function initFail2BanAlertSystem() {
|
|
console.log('[Fail2Ban Alert] Initialisation du système d\'alertes');
|
|
console.log(`[Fail2Ban Alert] Seuil: ${ALERT_THRESHOLD} IPs/heure, Vérification toutes les ${CHECK_INTERVAL / 60000} minutes`);
|
|
|
|
// Première vérification immédiate
|
|
checkAndSendAlert();
|
|
|
|
// Vérifications périodiques
|
|
setInterval(checkAndSendAlert, CHECK_INTERVAL);
|
|
|
|
console.log('[Fail2Ban Alert] Système d\'alertes initialisé');
|
|
}
|