kAworu's avatar

filtrer les erreurs 40x

publié par kAworu
il y a environ quatre ans

GET /phpmyadmin/main.php HTTP/1.0" 404 319 "-" "-" "-

c'est parti !

l'exemple si dessous est avec nginx parce que c'est celui que j'utilise, et que la moitié des lecteurs (moi le premier) fuyeraient ce blog comme la peste à la vue d'un fichier de configuration Apache.

/etc/nginx/nginx.conf

http {
[...]
########## servers ##########

# dummy
        server {
                listen 80;

                root /var/empty;

                access_log      /var/log/nginx/dummy.access_log main;
                #error_log      /var/log/nginx/dummy.error_log info;
        }

# Les autres serveurs...

# poupi.kaworu.ch
        server {
                listen 80;
                server_name     poupi.kaworu.ch;
[...]

Ok, maintenant les méchants vont tous voir /var/empty/ et même avec un PhpMyAdmin installé, les méchants ne le verront pas. On a les logs dans /var/log/nginx/dummy.access_log et on ne crée pas de fichier d'erreur vu que le access_log ne sera lui-même que des erreurs.

On va maintenant utiliser fail2ban pour chasser les méchant qui sont trop pressé de voir qu'il n'y a rien d'intéressant chez nous. On va créer un filtre qui étudie les logs (en particulier le fichier de log de notre serveur dummy : /var/log/nginx/dummy.access_log) et bannit avec une règle iptables (que le lecteur soulagé d'avoir échappé au fichier de configuration Apache se détende, fail2ban sait déjà comment jouer avec son pote iptables, donc nul besoin de faire nous-même les règles).

fail2ban se configure en trois étapes :

  • créer le filtre. Généralement une regex pour "matcher" les erreurs
  • définir les paramètres. Après combien de tentative on est banni, pour combien de temps etc.
  • créer l'action associée au filtre. Ici, l'action iptable existe déjà, mais l'on pourrait très bien imaginer autre chose (envoyer un email de duel à l'arme blanche au propriétaire de la machine qui nous attaque, histoire de régler ça comme des hommes)

on rajoute dans /etc/fail2ban/jail.conf

[nginx40x-iptables]

# si le filtre est actif
enabled  = true
# le nom du filtre dans le dossier /etc/fail2ban/filter.d/
filter   = nginx40x
# l'action associée, ici un ban par iptables sur le port http (80)
action   = iptables[name=nginx40x, port=http, protocol=tcp]
# le fichier de log à étudier, on peut utiliser *.access_log par exemple
logpath  = /var/log/nginx/ks.access_log
# le nombre d'essais avant d'être banni
maxretry = 3
# le temps en seconde durant lequel $maxretry
# tentative peuvent être accumulée.
findtime  = 4
# le temps en seconde durant lequel le ban est effectif.
bantime  = 60
# ici, on banni donc durant une minute lorsque un méchant
# fait plus de deux requêtes erronnées dans un laps de temps de
# quatres secondes.

# le reste de la config
[...]

maintenant le filtre : /etc/fail2ban/filter.d/nginx40x.conf

# Fail2Ban configuration file
#
# Author: Perrin Alexandre
#

[Definition]

# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile.
#             The host must be matched by a group named "host".
#             The tag "<HOST>" can be used for standard IP/hostname
#             matching and is only an alias for  (?:::f{4,6}:)?(?P<host>\S+)
# Values:  TEXT
#
failregex = <HOST> - - \[.*?\] ".*?" 4(1[0-5]|0[0-9])

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex = 

Conclusion

Hop c'est fini ! on redémarre fail2ban et nginx, et on check :

  • que le fichier /var/log/nginx/dummy.access_log est crée
  • que fail2ban est bien redémarré, et contient un filtre nginx40x. un petit iptables -L doit donner :
Chain fail2ban-nginx40x (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere
  • on test !
# depuis une autre IP, disons $IP :
$ for i in {0..20}; do
>    wget -O /dev/null -o /dev/null $SERVER || echo "PAN $i"
> done
PAN 0
PAN 1
PAN 2
PAN 3
PAN 4
PAN 5
PAN 6
PAN 7
PAN 8
^C

# plus de réponse après environ 8 requêtes

on doit avoir après coté serveur :

$ iptables -L
[...]
Chain fail2ban-nginx40x (1 references)
target     prot opt source               destination         
DROP       all  --  $IP              anywhere         
RETURN     all  --  anywhere             anywhere
$ less /var/log/fail2ban.log
[...] fail2ban.actions: WARNING [nginx40x-iptables] Ban $IP

et vous voilà banni pour une minute :)

Limitations

On peut voir plus haut que j'ai réussi à faire 8 requêtes avant d'être banni, alors qu'on avait mis trois comme maximum. dans les logs de nginx il y a plus de 3 requêtes. pourquoi ?

En faite, le temps que nginx log, que fail2ban voit que ça match plusieurs fois, qu'il le dise à iptables ... y a le temps de faire une dizaine de requêtes. si on rtfm un peu, on peut lire que si notre serveur web a un buffer pour les logs, fail2ban ne sera pas averti très vite.

J'ai essayé de modifier nginx.conf pour n'avoir pas de buffer pour les log du serveur dummy (voir ici) :

access_log      /var/log/nginx/dummy.access_log main buffer=0;

Mais cela n'a rien changé. Dans la pratique, c'est pas trop un problème, j'ai rarement plus de 4 requêtes qui passent avec cette configuration. Il est aussi possible de modifier la configuration de fail2ban (nombre de tentatives, délai, temps de ban etc) pour trouver ce qui joue le mieux.

"Hope this can help".

quatre commentaires

écrire un commentaire

  1. Nico il y a presque quatre ans Nico's avatar

    Salut :)

    Très interressant cet article :) J'ai implémenté quelque chose comme cela mais sous Apache et sans fail2ban pour l'instant, car je ne trouve pas que la somme des acces de ce type soit bien importante.

    En revanche, pour le docroot du dummy server; personelement j'ai mis l'URL du nom de domaine de mon site juste au cas ou un gentil se serait perdu :D

  2. llebegue il y a presque quatre ans llebegue's avatar

    Merci très utile pour mettre de côté les accès intempestifs à des phpMyAdmin de tout accabit !

  3. bghflt il y a environ deux ans bghflt's avatar

    Cool ton setup, j'ai mis ça sur un serveur le premier de mon range ip qui ne fera jamais d'http sur son ip..

    Trop marrant, les chinetoques qui s'écrasent le pif contre la vitre :)

    Merci! You make my day!

    Ce soir fondue!!

  4. resumes il y a quatre mois resumes's avatar

    I anticipate the emergence of a number of bugs.

écrire un commentaire:


(utilisé pour gravatar, ne sera pas affiché)



tu peux utiliser la syntaxe markdown :)