mirror of
https://github.com/deunix-educ/Fail2banMqttActionBanishment.git
synced 2026-08-24 03:11:58 +02:00
First commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""Diffuse chaque BanEvent (création et mise à jour géoloc) aux clients
|
||||
WebSocket via le channel layer, et déclenche la géolocalisation asynchrone
|
||||
à la création. Journalise aussi les verrouillages django-axes (protection
|
||||
/admin/, cf. AXES_* dans config/settings/base.py) pour que fail2ban
|
||||
(generic/fail2ban/jail.d/emitter-admin-auth.conf) puisse réagir."""
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from asgiref.sync import async_to_sync
|
||||
from axes.signals import user_locked_out
|
||||
from channels.layers import get_channel_layer
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.http import HttpRequest
|
||||
|
||||
from .consumers import GROUP_NAME
|
||||
from .models import BanEvent, NodeRegistry
|
||||
from .serializers import event_payload
|
||||
from .tasks import geolocate_ip
|
||||
|
||||
fail2ban_axes_logger = logging.getLogger('fail2ban.axes')
|
||||
|
||||
|
||||
@receiver(post_save, sender=BanEvent)
|
||||
def broadcast_ban_event(sender: type[BanEvent], instance: BanEvent, created: bool, **kwargs: Any) -> None:
|
||||
channel_layer = get_channel_layer()
|
||||
if channel_layer is not None:
|
||||
# Se déclenche deux fois par event (création, puis mise à jour
|
||||
# géoloc par geolocate_ip ci-dessous) : lookup unique indexé, sans
|
||||
# conséquence à tourner deux fois (résultat identique).
|
||||
node_alias = NodeRegistry.objects.filter(node_id=instance.node).values_list('alias', flat=True).first()
|
||||
async_to_sync(channel_layer.group_send)(
|
||||
GROUP_NAME,
|
||||
{'type': 'ban.event', 'payload': event_payload(instance, node_alias)},
|
||||
)
|
||||
|
||||
if created:
|
||||
geolocate_ip.delay(instance.pk)
|
||||
|
||||
|
||||
@receiver(user_locked_out)
|
||||
def log_axes_lockout(sender: Any, request: HttpRequest, username: str | None, ip_address: str, **kwargs: Any) -> None:
|
||||
"""Un seul point de vérité pour le seuil : axes décide (AXES_FAILURE_LIMIT)
|
||||
qu'il y a un problème, cette ligne fait réagir fail2ban (ban réseau +
|
||||
propagation SYNC_BAN aux autres noeuds, comme toute autre jail — cf.
|
||||
jail.local [DEFAULT] action). maxretry=1 côté jail : chaque ligne ici
|
||||
EST déjà la décision de verrouillage, pas la peine de recompter.
|
||||
|
||||
Format de message imposé par filter.d/app-auth.conf (générique,
|
||||
réutilisable par toute appli du VPS — pas seulement ce projet) :
|
||||
"Verrouillage <NOM_APPLI> après échecs répétés depuis <IP> (...)",
|
||||
<NOM_APPLI> = "émetteur" ici, un seul mot (\\S+ côté filtre)."""
|
||||
fail2ban_axes_logger.warning(
|
||||
'Verrouillage émetteur après échecs répétés depuis %s (utilisateur tenté : %s)',
|
||||
ip_address, username or '?',
|
||||
)
|
||||
Reference in New Issue
Block a user