Les bouncers (les "videurs" comme en boite de nuit) appliquent les décisions récupérés depuis l'API de Crowdsec. Dans notre cas, notre bouncer installé sur le serveur Nginx va récupérer les décisions (communautaires et locales) sur le serveur Crowdsec Local API et bloquer les IP des attaquants.
Les bouncers ne nécessitent pas obligatoirement l'installation de Crowdsec sur la machine à protéger. Crowdsec est charge de détecter et de tracer quant aux bouncers ils sont en charge de bloquer.
Serveur Crowdsec Local API :
Serveur Nginx :
Vm malveillante (en charge de simuler des attaques) : Serveur Nginx :
Nous allons commencer avec un bouncer utilisant un mécanisme connu de ceux qui utilisent fail2ban : bloquer l'IP malveillante sur le firewall.
Pour installer ce bouncer, il faut vous rendre sur le hub Crowdsec https://hub.crowdsec.net/author/crowdsecurity/bouncers/cs-firewall-bouncer et suivre les instructions d'installation. Pour ma part, j'ai choisi le paquet s'appuyant sur Iptables.
Il faut maintenant déclarer le bouncer sur notre serveur CS LAPI :
# srv-nginx-01-fw est le nom du bouncer (choisi arbitrairement)
cscli bouncers add srv-nginx-01-fw
# Sortie
Api key for 'srv-nginx-01-fw':
### Copier la clé API ci-dessous ###
3b75d863c5fcc06d289990699eb1c1e9
Please keep this key since you will not be able to retrieve it!
# Vérification
cscli bouncers list
---------------------------------------------------------------------------------------------------------------------------------
NAME IP ADDRESS VALID LAST API PULL TYPE VERSION
---------------------------------------------------------------------------------------------------------------------------------
srv-nginx-01-fw ✔️ 2021-07-09T18:43:40+02:00
---------------------------------------------------------------------------------------------------------------------------------
Copiez la clé API, puis rendez-vous sur le serveur Nginx afin de modifier le fichier de configuration du bouncer au niveau de l'URL de connexion à l'API et de la clé API :
vim /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml :
(...)
# Modifiez l'URL
api_url: https://srv-cs-lapi.lab.lan:8080/
# Collez la clé
api_key: 3b75d863c5fcc06d289990699eb1c1e9
(...)
Relancez le bouncer et activez le au démarrage : service crowdsec-firewall-bouncer restart && systemctl enable crowdsec-firewall-bouncer.service
De nouveau sur le serveur CS LAPI, vérifiez la connexion du bouncer :
cscli bouncers list
----------------------------------------------------------------------------------------------------------------------------------------------------------------
NAME IP ADDRESS VALID LAST API PULL TYPE VERSION
----------------------------------------------------------------------------------------------------------------------------------------------------------------
srv-nginx-01-fw 192.168.1.203 ✔️ 2021-07-09T18:45:23+02:00 crowdsec-firewall-bouncer v0.0.13-debian-pra....
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Notre bouncer est donc maintenant connecté de manière sécurisée à notre serveur CS LAPI et fin prêt à bloquer des IP malveillantes.
Par défaut, les plages d'adresses privées sont "whitelistées". Afin de constater le blocage, nous allons commenter la plage 192.168.0.0/16 et déclarer les IP de nos serveurs.
Sur le serveur Nginx :
vim /etc/crowdsec/parsers/s02-enrich/whitelists.yaml :
name: crowdsecurity/whitelists
description: "Whitelist events from private ipv4 addresses"
whitelist:
reason: "private ipv4/ipv6 ip/ranges"
ip:
- "127.0.0.1"
- "::1"
- "192.168.1.202"
- "192.168.1.203"
cidr:
# - "192.168.0.0/16"
- "10.0.0.0/8"
- "172.16.0.0/12"
# expression:
# - "'foo.com' in evt.Meta.source_ip.reverse"
Sur la VM "bad-vm", on vérifie l'accès à notre serveur web :
Sur le serveur Nginx, on vérifie les décisions :
root@srv-nginx-01:~# cscli decisions list
No active decisions <-- Pas de décisions locales
root@srv-nginx-01:~# cscli decisions list --all <-- pour afficher les décisions récupérées depuis le serveur Crowdsec Central API.
+------+--------+-----------------------+-------------------------------------------+--------+---------+----+--------+------------------+----------+
| ID | SOURCE | SCOPE:VALUE | REASON | ACTION | COUNTRY | AS | EVENTS | EXPIRATION | ALERT ID |
+------+--------+-----------------------+-------------------------------------------+--------+---------+----+--------+------------------+----------+
| 1450 | CAPI | Ip:139.162.152.16/32 | crowdsecurity/http-backdoors-attempts | ban | | | 0 | 39m38.784615692s | 20 |
| 1451 | CAPI | Ip:178.20.157.98/32 | crowdsecurity/http-backdoors-attempts | ban | | | 0 | 39m38.793069325s | 20 |
| 1452 | CAPI | Ip:148.72.210.68/32 | crowdsecurity/http-backdoors-attempts | ban | | | 0 | 39m38.801407933s | 20 |
| 1453 | CAPI | Ip:185.51.228.241/32 | crowdsecurity/http-backdoors-attempts | ban | | | 0 | 39m38.811503324s | 20 |
| 1454 | CAPI | Ip:198.71.227.6/32 | crowdsecurity/http-backdoors-attempts | ban | | | 0 | 39m38.821115173s | 20 |
(...)
La dernière commande nous permet d'observer tout le bénéfice qu'apporte la fonctionnalité collaborative de Crowdsec en permettant de bloquer de manière préventive les IP malveillantes.
Concrètement, cela donne ceci avec Iptables :
root@srv-nginx-01:~# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP all -- anywhere anywhere match-set crowdsec-blacklists src
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
root@srv-nginx-01:~# ipset list crowdsec-blacklists
Name: crowdsec-blacklists
Type: hash:net
Revision: 6
Header: family inet hashsize 1024 maxelem 65536 timeout 300
Size in memory: 9368
References: 1
Number of entries: 100
Members:
222.186.180.142 timeout 85142
40.73.102.25 timeout 85143
46.0.203.166 timeout 85143
45.136.108.85 timeout 85143
(...)
De nouveau sur la VM "bad-vm", on installe le paquet "nikto" qui va nous permettre de simuler l'attaque (il faut avoir activer le dépôt non-free sur Debian). Une fois le paquet installé, on lance la commande suivante : nikto -host 192.168.1.203
Toujours depuis la "bad-vm", essayez d'accéder au service Web :
olivier@bad-vm:~$ curl --connect-timeout 1 http://192.168.1.203/
curl: (28) Connection timed out after 1016 milliseconds
Depuis le navigateur web de la VM attaquante :
On constate qu'on ne peut plus se connecter au service Web depuis la VM attaquante. Du côté du serveur CS LAPI cela donne :
Au niveau d'iptables sur le serveur Nginx :
root@srv-nginx-01:~# ipset list crowdsec-blacklists | grep 192.168.1.174
192.168.1.174 timeout 13535
Si l'on veut faire reproduire l'attaque, on peut supprimer manuellement le blocage. Sur le serveur Crowdsec LAPI :
root@srv-cs-lapi:~# cscli decisions list
+------+----------+------------------+-----------------------------------+--------+---------+----+--------+--------------------+----------+
| ID | SOURCE | SCOPE:VALUE | REASON | ACTION | COUNTRY | AS | EVENTS | EXPIRATION | ALERT ID |
+------+----------+------------------+-----------------------------------+--------+---------+----+--------+--------------------+----------+
| 1869 | crowdsec | Ip:192.168.1.174 | crowdsecurity/http-bad-user-agent | ban | | | 2 | 3h59m50.388448338s | 35 |
+------+----------+------------------+-----------------------------------+--------+---------+----+--------+--------------------+----------+
root@srv-cs-lapi:~# cscli decisions delete -i 192.168.1.174
INFO[11-07-2021 02:07:25 PM] 6 decision(s) deleted
root@srv-cs-lapi:~# cscli decisions list
No active decisions
Même si Crowdsec n'est pas trop compliqué dans sa mise en place, on peut se perdre dans les différents mécanismes mis en jeu. Afin de bien comprendre, je vais reprendre les évènements et les détailler dans l'ordre chronologique, de l'attaque simulée jusqu'à son blocage :
/etc/crowdsec/aquis.yaml
)/etc/crowdsec/parsers/
).Avec un serveur, Crowdsec seul avec un bouncer fera l'affaire et permettra de bénéficier des blocages préventifs communautaires tout en assurant la détection locale.
Dans une infrastructure avec plusieurs serveurs à protéger, un serveur centralisant les alertes et les décisions permettra de partager les alertes et les décisions locales en plus de celles récupérées sur le serveur Central API. Il permettra aussi d'avoir un seul point d'entrée pour consulter les logs, ce qui en fait un autre atout par rapport à fail2ban. Suivant le trafic sur la Local API, il faudra choisir la base de données en conséquence.
À travers cette première série d'articles, nous avons mis en place une base pour démarrer avec Crowdsec et comprendre les principaux mécanismes. D'autres articles suivront :)