mirror of
https://github.com/deunix-educ/Fail2banMqttActionBanishment.git
synced 2026-08-24 03:11:58 +02:00
57 lines
2.6 KiB
Python
57 lines
2.6 KiB
Python
"""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 '?',
|
|
)
|