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 :
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 :
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 :
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 :
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 😉