Sécuriser un service avec Fail2ban

De The Linux Craftsman
Révision datée du 20 novembre 2020 à 16:59 par Jc.forton (discussion | contributions) (→‎Installation)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigation Aller à la recherche

Introduction

Le but de fail2ban est d'empêcher une attaque par force brute, c'est à dire qu'un individu trouve un tuple identifiant/mot de passe permettant l'accès à un serveur. Fail2ban va analyser les logs pour compter le nombre de tentatives et bannir l'IP qui essaye de se connecter si elle dépasse le nombre maximal d’essais.

Installation

Une fois l'installation du dépôt EPEL terminée, nous pouvons procéder à celle de fail2ban:

yum -y install fail2ban

Configuration

Tout d'abord il faut copier le fichier /etc/fail2ban/jail.conf en /etc/fail2ban/jail.local

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Dans ce fichier, on va s'intéresser aux variables suivantes:

  • ignoreip : correspond à la suite d'adresses IP qui ne se feront jamais bannir;
  • maxretry : correspond au nombre d'essais;
  • findtime : correspond à la période pendant laquelle les essais vont incrémenter maxretry;
  • bantime : correspond au temps ou l'adresse IP ne peut pas se connecter.

Choix de la punition

Il faut choisir quelque chose de cohérent (une punition suffisante) pour ne pas permettre de se faire cracker son mot de passe:

  • maxretry = 3
  • findtime = 86400 (correspond à 1 journée)
  • bantime = 604800 (correspond à 1 semaine)

Cela signifie que si une adresse IP se trompe 3 fois en 1 journée (86400s) elle se fait bannir pendant 1 semaine (604800s).

Un rapide calcule permet de trouver le nombre maximal de tentative durant une année:

365 jours / 7 jours par semaine * 3 tentatives = 156 essais, ce qui reste raisonnable.

Si le pirate possède un botnet, il faut bien sûr multiplier ce nombre par le nombre de machines dans le botnet...

Attention : fail2ban parcours les logs de connexion pour connaître le numéro de la tentative, ce qui a pour conséquence, si le findtime est grand, de prendre un certain temps...

Configuration de la section Jail

  • Sur CentOS 6:

Pour sécuriser le service, il faut repérer sa section jail. Dans cet exemple, nous allons sécuriser SSH.

Nous allons avoir besoin des variables suivantes:

  • enabled : permet d'activer le filtrage
  • filter : donne un nom au filtre
  • action : permet de bloquer le port (ssh) avec une règles Iptables et d'envoyer un mail
  • logpath : indique le fichier de log
[ssh-iptables]

enabled  = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
           sendmail-whois[name=SSH, dest=MON_EMAIL, sender=fail2ban@MON_DOMAINE, sendername="Fail2Ban"]
logpath  = /var/log/secure

Remplacez MON_EMAIL par votre mail ainsi que MON_DOMAINE par votre domaine !

  • Sur CentOS 8:

Il suffit d'ajouter la ligne enabled=true dans la section à activer !


[sshd]

# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode   = normal
enabled = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Démarrage et enregistrement dans le chargeur de démarrage

  • Pour SystemVInit:
# service fail2ban start
# chkconfig fail2ban on
  • Pour SystemD:
# systemctl start fail2ban.service
# systemctl enable fail2ban.service

Ajout automatique de règles dans Iptables

Vous pouvez constater que fail2ban ajoute des règles dans la chaîne fail2ban-SSH:

Chain fail2ban-SSH (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       122.225.109.214      0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       122.225.109.115      0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       61.174.51.212        0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       61.174.51.213        0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       125.70.0.44          0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       61.174.51.210        0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       122.226.140.158      0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       122.225.109.210      0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       222.186.34.117       0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       210.14.69.244        0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       122.225.109.206      0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       74.208.209.116       0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       61.174.51.229        0.0.0.0/0           reject-with icmp-port-unreachable
    0     0 REJECT     all  --  *      *       222.186.34.119       0.0.0.0/0           reject-with icmp-port-unreachable
   14   928 REJECT     all  --  *      *       61.55.135.41         0.0.0.0/0           reject-with icmp-port-unreachable
 1049 66520 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Parcours des Logs

Une fois le service démarré, il va commencer à écrire dans le fichier /var/log/secure

Sep 22 03:52:36 s17650782 sshd[2094]: Failed password for root from 122.225.109.214 port 36975 ssh2
Sep 22 03:52:36 s17650782 sshd[2096]: Failed password for root from 122.225.109.214 port 39090 ssh2
Sep 22 03:52:37 s17650782 sshd[2102]: Failed password for root from 122.225.109.214 port 41395 ssh2
Sep 22 03:52:38 s17650782 sshd[2099]: Failed password for invalid user admin from 122.225.109.214 port 41013 ssh2
Sep 22 03:52:39 s17650782 sshd[2098]: Failed password for root from 222.186.34.119 port 4255 ssh2
Sep 22 03:52:42 s17650782 sshd[2098]: Failed password for root from 222.186.34.119 port 4255 ssh2
Sep 22 03:52:43 s17650782 sshd[2094]: Failed password for root from 122.225.109.214 port 36975 ssh2
Sep 22 03:52:43 s17650782 sshd[2095]: Disconnecting: Too many authentication failures for root
Sep 22 03:52:43 s17650782 sshd[2094]: PAM 5 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=122.225.109.214  user=root
Sep 22 03:52:43 s17650782 sshd[2094]: PAM service(sshd) ignoring max retries; 6 > 3
Sep 22 03:52:43 s17650782 sshd[2102]: Failed password for root from 122.225.109.214 port 41395 ssh2^C
Sep 22 03:52:43 s17650782 sshd[2096]: Failed password for root from 122.225.109.214 port 39090 ssh2
Sep 22 03:52:45 s17650782 sshd[2098]: Failed password for root from 222.186.34.119 port 4255 ssh2
Sep 22 03:52:46 s17650782 sshd[2101]: fatal: Read from socket failed: Connection reset by peer
Sep 22 03:52:46 s17650782 sshd[2098]: PAM 4 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=222.186.34.119  user=root

Cela vous donne une idée des IP qui essayent de casser votre mot de passe...

La commande suivante vous donne une idée du nombre de tentatives:

# cat /var/log/secure | grep disconnect | awk -F ' ' '{ print $9 }' | grep -v from | wc -l

La commande suivante liste les adresses IP:

# cat /var/log/secure | grep disconnect | awk -F ' ' '{ print $9 }' | grep -v from | sort -u


Apache

Voici quelques ajouts intéressants pour le serveur Apache:

[apache]
enabled = true
port = http,https
filter = apache-auth
logpath = %(apache_error_log)s

[apache-overflows]
enabled = true
port = http,https
filter = apache-overflows
logpath = %(apache_error_log)s

[apache-dos]
enabled = true
port = http,https
filter = apache-dos
logpath = %(apache_access_log)s