Bloquer les attaques DDOS avec Nginx

1/52/53/54/55/5 (6 votes, moyenne: 4,33 sur 5)
Loading...
B

Attention, cet article a plus d'une année d'ancienneté. Il est possible que les informations présentées ne soient plus à jour, spécialement dans le cadre d'un article technique.


Bonjour à tous,

 

Comme je l’avais expliqué précédemment, il y a un petit malin qui s’amuse à lancer des attaques par déni de service (ddos) sur The Abyss Project, généralement à 2 heure du matin une fois dans la semaine.

 

Faire ce type d’attaque relève du niveau élémentaire, car pour cela, vous n’avez besoin que d’un outil type apache bench.

La seul différence entre un benchmark et une attaque ddos avec ce type d’outil est le nombre de clients que l’on simule, car si on choisit de simuler 10000 clients d’un coup ça fait tout de suite mal sur la cible.

 

Pour illustrer le phénomène, voici ce qui arrive à mon serveur lorsqu’il se prend une attaque de cette ampleur :

anti-flood-nginx-01

Comme on le voit sur le graphique, il y a des coupures, ce n’est pas un bug de munin, c’est bel et bien le serveur qui se fige pendant quelques instants, et avec des load averages pareil sur un 3 cœurs, ça se comprend aisément.

 

Ça fait mal hein ? Les temps de réponse sont collectors aussi :

response

 

 

Bon, on va voir comment essayer bloquer ce type d’attaque, mais avant j’aimerais vous donner les résultats d’un Apache Bench avant application de la protection :

 

ubuntu@ip-172-31-44-125:~$ ab -n 2000 -c 150 http://www.abyssproject.net/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
 
Benchmarking www.abyssproject.net (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests
Server Software: nginx/1.6.0
Server Hostname: www.abyssproject.net
Server Port: 80
 
Document Path: /
Document Length: 40033 bytes
 
Concurrency Level: 150
Time taken for tests: 15.611 seconds
Complete requests: 2000
Failed requests: 0
Total transferred: 81176000 bytes
HTML transferred: 80066000 bytes
Requests per second: 128.11 [#/sec] (mean)
Time per request: 1170.839 [ms] (mean)
Time per request: 7.806 [ms] (mean, across all concurrent requests)
Transfer rate: 5077.99 [Kbytes/sec] received
 
Connection Times (ms)
min mean[+/-sd] median max
Connect: 168 186 131.0 169 1169
Processing: 521 956 289.1 945 1964
Waiting: 182 561 272.7 548 1616
Total: 689 1143 315.8 1119 2139
 
Percentage of the requests served within a certain time (ms)
50% 1119
66% 1263
75% 1345
80% 1387
90% 1556
95% 1706
98% 1997
99% 2118
100% 2139 (longest request)

 

Vu comme ça, le serveur tiens la charge, mais en lançant un coup de HTOP on se rend compte qu’on n’est pas loin de la catastrophe :

anti-flood-nginx-02

 

J’ai toutes les ressources de mon serveur qui sont pompées par une simple commande, c’est grave docteur ?

Tu m’étonne Hermione,  mais bon, personnellement j’ai un Reverse Proxy Nginx, je l’ai surtout installé pour ses performances, mais aujourd’hui, c’est son côté sécurité qui me sert.

Si vous n’avez pas de Reverse Proxy Nginx ou de serveur web Nginx, vous trouverez votre bonheur sur The Abyss Project !

 

Maintenant, on va se débarrasser de ce type d’attaque DDOS de façon définitive …

La syntaxe que je vais utiliser est compatible avec Nginx 1.6 :

 

Éditez votre fichier de configuration de Nginx :

nano /etc/nginx/nginx.conf

 

Et recherchez l’ouverture des balises http :

http {
XXXX_CONFIGURATION_XXXX
}

 

Rajoutez ces lignes au début :

#Connexions maximum par ip
limit_conn_zone $binary_remote_addr zone=limit_per_ip:10m;
limit_conn limit_per_ip 20;
 
#Nombre de requêtes/s maximum par ip
limit_req_zone $binary_remote_addr zone=allips:10m rate=200r/s;
limit_req zone=allips burst=200 nodelay;

 

Pour moi par exemple, le début de la section http ressemble à ça :

http {
 
#Connexions maximum par ip
limit_conn_zone $binary_remote_addr zone=limit_per_ip:10m;
limit_conn limit_per_ip 15;
 
#Nombre de requêtes/s maximum par ip
limit_req_zone $binary_remote_addr zone=allips:10m rate=150r/s;
limit_req zone=allips burst=150 nodelay;
 
include /etc/nginx/mime.types;
default_type application/octet-stream;

 

Bon, faites tout de même attention avec ces paramètres, si ils sont trop restrictifs ça pourrait empêcher une navigation correcte sur votre site pour les utilisateurs légitimes, n’hésitez pas à lâcher du lest si vous avez des problèmes.

Sauvegardez la configuration avec la combinaison de touche Ctrl+O et redémarrez Nginx :

service nginx restart

 

Maintenant, on refait un coup d’apache bench :

ubuntu@ip-172-31-44-125:~$ ab -n 2000 -c 150 http://www.abyssproject.net/
This is ApacheBench, Version 2.3 <$Revision: 1528965 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
 
Benchmarking www.abyssproject.net (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests
Server Software: nginx/1.6.0
Server Hostname: www.abyssproject.net
Server Port: 80
 
Document Path: /
Document Length: 212 bytes
 
Concurrency Level: 150
Time taken for tests: 6.260 seconds
Complete requests: 2000
Failed requests: 169
(Connect: 0, Receive: 0, Length: 169, Exceptions: 0)
Non-2xx responses: 1831
Total transferred: 7560645 bytes
HTML transferred: 7153749 bytes
Requests per second: 319.50 [#/sec] (mean)
Time per request: 469.480 [ms] (mean)
Time per request: 3.130 [ms] (mean, across all concurrent requests)
Transfer rate: 1179.51 [Kbytes/sec] received
 
Connection Times (ms)
min mean[+/-sd] median max
Connect: 168 187 131.3 169 1180
Processing: 168 219 133.4 174 1552
Waiting: 168 186 47.7 173 692
Total: 337 406 183.1 344 1720
 
Percentage of the requests served within a certain time (ms)
50% 344
66% 352
75% 363
80% 369
90% 696
95% 770
98% 1335
99% 1345
100% 1720 (longest request)
ubuntu@ip-172-31-44-125:~$

 

Ce qu’il est intéressant de noter, c’est l’apparition de la ligne Non-2xx responses :

Non-2xx responses:      1831

 

Cela signifie que Nginx à répondu par un code 403 pour éviter une surcharge et on voit tout de suite l’évolution au niveau des ressources consommées :

anti-flood-nginx-03

 

Pas mal hein ? Et cela ne gène pas la navigation sur le site pour les utilisateurs normaux ou les robots.

 

Vous pouvez également suivre l’article de Yannick Warnier qui permet de surveiller les accès sur Nginx avec Fail2Ban 😉

 

 

A propos de l'auteur

Nicolas Simond

Ingénieur Systèmes et Réseaux et guitariste hard rock et metal à mes heures perdues.
Je suis le créateur et l'unique rédacteur d'Abyss Project, c'est ici que je note la plupart de mes procédures et quelques divagations.

Si vous l'article vous a aidé, pensez à me payer un café :)

Subscribe
Notify of
guest

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

0 Commentaires
Inline Feedbacks
View all comments