Checkpoint: Système complet de monitoring Fail2Ban déployé avec succès. Tableau de bord admin affichant en temps réel les IPs bannies, statistiques d'attaques, et historique des bannissements. Fonctionnalité de débannissement manuel d'IPs. Système d'alertes email automatiques configuré : envoie une notification au propriétaire lorsque plus de 10 IPs sont bannies en 1 heure. Vérification toutes les 15 minutes. Déployé et testé sur le VPS de production avec logs confirmant l'initialisation correcte.

This commit is contained in:
Manus
2026-01-18 13:26:55 -05:00
parent cd18e2873a
commit 4b407b9c83
8 changed files with 610 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import { parseLocalDateTime } from "./dateUtils";
import { z } from "zod";
import * as db from "./db";
import * as analyticsDb from "./analyticsDb";
import * as fail2banDb from "./fail2banDb";
import { generateAnalyticsExcel, generateAnalyticsPDF } from "./analyticsExportService";
import { TRPCError } from "@trpc/server";
import { sendInscriptionConfirmation, sendGroupEmail, sendNotificationFormateurNouvelleInscription, sendNotificationFormateurAnnulation, sendAlerteCapaciteAtteinte, sendNotificationPlaceDisponible, sendRemerciementPostFormation, sendResetPasswordEmail } from "./emailService";
@@ -2668,6 +2669,48 @@ export const appRouter = router({
}),
}),
// Monitoring Fail2Ban
fail2ban: router({
// Récupérer le statut et les statistiques Fail2Ban
getStatus: adminProcedure.query(async () => {
return await fail2banDb.getFail2BanStatus();
}),
// Récupérer l'historique des bannissements
getHistory: adminProcedure
.input(z.object({
limit: z.number().optional().default(50),
}))
.query(async ({ input }) => {
return await fail2banDb.getBanHistory(input.limit);
}),
// Débannir une IP
unbanIP: adminProcedure
.input(z.object({
ip: z.string(),
}))
.mutation(async ({ input }) => {
const success = await fail2banDb.unbanIP(input.ip);
if (!success) {
throw new TRPCError({
code: 'INTERNAL_SERVER_ERROR',
message: `Impossible de débannir l'IP ${input.ip}`,
});
}
return { success: true };
}),
// Compter les bannissements récents
countRecentBans: adminProcedure
.input(z.object({
hours: z.number().optional().default(1),
}))
.query(async ({ input }) => {
return await fail2banDb.countRecentBans(input.hours);
}),
}),
});
export type AppRouter = typeof appRouter;