Marvin Pascale

[B.Log]

26 Febbraio 2022

Crowdsec e Docker compose

In questo articolo vedremo come mettere al sicuro uno stack docker gestito con docker compose.

L’architettura

In questo esempio vedremo come mettere in sicurezza un’infrastruttura costituita da un reverse proxy fatto con Nginx, un applicazione servita da Apache 2 e due container per Crowdsec (uno dei quali dedicato alla dashboard). Per rendere accessibili i log giocheremo con i volumi di docker.

Diamo un’occhiata al file docker-compose.yml

version: '3'

services:
  #the application itself : static html served by apache2.
  #the html can be found in ./app/
  app:
    image: httpd:alpine
    restart: unless-stopped
    volumes:
      - ./app/:/usr/local/apache2/htdocs/
    networks:
      - crowdsec_test

  #the reverse proxy that will serve the application
  #you can see nginx's config in ./reverse-proxy/nginx.conf
  reverse-proxy:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - 8000:80
    depends_on:
      - 'app'
    volumes:
      - ./reverse-proxy/nginx.conf:/etc/nginx/nginx.conf
      - logs:/var/log/nginx
    networks:
      - crowdsec_test

  #crowdsec : it will be fed nginx's logs
  #and later we're going to plug a firewall bouncer to it
  crowdsec:
    image: crowdsecurity/crowdsec:latest
    restart: unless-stopped
    environment:
      #this is the list of collections we want to install
      #https://hub.crowdsec.net/author/crowdsecurity/collections/nginx
      COLLECTIONS: "crowdsecurity/nginx"
      GID: "${GID-1000}"
    depends_on:
      - 'reverse-proxy'
    ports:
      - 127.0.0.1:8080:8080
    volumes:
      - ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.yaml
      - logs:/var/log/nginx
      - crowdsec-db:/var/lib/crowdsec/data/
      - crowdsec-config:/etc/crowdsec/
    networks:
      - crowdsec_test

  #metabase, because security is cool, but dashboards are cooler
  dashboard:
    #we're using a custom Dockerfile so that metabase pops with pre-configured dashboards
    build: ./crowdsec/dashboard
    restart: unless-stopped
    ports:
      - 3000:3000
    environment:
      MB_DB_FILE: /data/metabase.db
      MGID: "${GID-1000}"
    depends_on:
      - 'crowdsec'
    volumes:
      - crowdsec-db:/metabase-data/
    networks:
      - crowdsec_test

volumes:
  logs:
  crowdsec-db:
  crowdsec-config:

networks:
  crowdsec_test:

Per fare i test possiamo clonare questo progetto su GitHub . In questo repository troveremo tutto il necessario; le modifiche che ho apportato al file docker-compose.yml sono:

  • restart: unless-stopped
  • rimozione di ip “statici”
  • esposizione in locale della porta 8080 per il container crowdsec

Dopo aver clonato il progetto lo possiamo avviare

# docker-compose up -d

verifichiamo che sia tutto up e running

# docker-compose ps
                 Name                               Command               State           Ports
--------------------------------------------------------------------------------------------------------
example-docker-compose_app_1             httpd-foreground                 Up      80/tcp
example-docker-compose_crowdsec_1        /bin/sh -c /bin/sh docker_ ...   Up
example-docker-compose_dashboard_1       /app/run_metabase.sh             Up      0.0.0.0:3000->3000/tcp
example-docker-compose_reverse-proxy_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8000->80/tcp

e testiamo la nostra applicazione

# curl http://localhost:8000/
Hello world !%

quali parser saranno attivi?

# docker-compose exec crowdsec cscli metrics
INFO[26-02-2022 09:07:42 PM] Acquisition Metrics:
+----------------------------------------+------------+--------------+----------------+------------------------+
|                 SOURCE                 | LINES READ | LINES PARSED | LINES UNPARSED | LINES POURED TO BUCKET |
+----------------------------------------+------------+--------------+----------------+------------------------+
| file:/var/log/nginx/example.access.log |          1 |            1 | -              | -                      |
+----------------------------------------+------------+--------------+----------------+------------------------+
INFO[26-02-2022 09:07:42 PM] Parser Metrics:
+--------------------------------+------+--------+----------+
|            PARSERS             | HITS | PARSED | UNPARSED |
+--------------------------------+------+--------+----------+
| child-crowdsecurity/http-logs  |    3 |      1 |        2 |
| child-crowdsecurity/nginx-logs |    1 |      1 | -        |
| crowdsecurity/dateparse-enrich |    1 |      1 | -        |
| crowdsecurity/geoip-enrich     |    1 |      1 | -        |
| crowdsecurity/http-logs        |    1 | -      |        1 |
| crowdsecurity/nginx-logs       |    1 |      1 | -        |
| crowdsecurity/non-syslog       |    1 |      1 | -        |
| crowdsecurity/whitelists       |    1 |      1 | -        |
+--------------------------------+------+--------+----------+
INFO[26-02-2022 09:07:42 PM] Local Api Metrics:
+--------------------+--------+------+
|       ROUTE        | METHOD | HITS |
+--------------------+--------+------+
| /v1/watchers/login | POST   |    2 |
+--------------------+--------+------+

Crowdsec ha riconosciuto Nginx e Apache http server e sta già monitorando i log.

# docker-compose exec crowdsec cscli hub list
INFO[26-02-2022 09:08:48 PM] Loaded 23 collecs, 28 parsers, 36 scenarios, 3 post-overflow parsers
INFO[26-02-2022 09:08:48 PM] PARSERS:
-------------------------------------------------------------------------------------------------------------
 NAME                            📦 STATUS   VERSION  LOCAL PATH
-------------------------------------------------------------------------------------------------------------
 crowdsecurity/sshd-logs         ✔️  enabled  1.3      /etc/crowdsec/parsers/s01-parse/sshd-logs.yaml
 crowdsecurity/http-logs         ✔️  enabled  0.6      /etc/crowdsec/parsers/s02-enrich/http-logs.yaml
 crowdsecurity/dateparse-enrich  ✔️  enabled  0.1      /etc/crowdsec/parsers/s02-enrich/dateparse-enrich.yaml
 crowdsecurity/nginx-logs        ✔️  enabled  0.8      /etc/crowdsec/parsers/s01-parse/nginx-logs.yaml
 crowdsecurity/geoip-enrich      ✔️  enabled  0.2      /etc/crowdsec/parsers/s02-enrich/geoip-enrich.yaml
 crowdsecurity/whitelists        ✔️  enabled  0.2      /etc/crowdsec/parsers/s02-enrich/whitelists.yaml
 crowdsecurity/syslog-logs       ✔️  enabled  0.4      /etc/crowdsec/parsers/s00-raw/syslog-logs.yaml
-------------------------------------------------------------------------------------------------------------
INFO[26-02-2022 09:08:48 PM] SCENARIOS:
--------------------------------------------------------------------------------------------------------------------------
 NAME                                       📦 STATUS   VERSION  LOCAL PATH
--------------------------------------------------------------------------------------------------------------------------
 crowdsecurity/http-open-proxy              ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-open-proxy.yaml
 crowdsecurity/http-xss-probing             ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-xss-probing.yaml
 ltsich/http-w00tw00t                       ✔️  enabled  0.1      /etc/crowdsec/scenarios/http-w00tw00t.yaml
 crowdsecurity/http-generic-bf              ✔️  enabled  0.1      /etc/crowdsec/scenarios/http-generic-bf.yaml
 crowdsecurity/http-path-traversal-probing  ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-path-traversal-probing.yaml
 crowdsecurity/ssh-bf                       ✔️  enabled  0.1      /etc/crowdsec/scenarios/ssh-bf.yaml
 crowdsecurity/http-backdoors-attempts      ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-backdoors-attempts.yaml
 crowdsecurity/http-bad-user-agent          ✔️  enabled  0.4      /etc/crowdsec/scenarios/http-bad-user-agent.yaml
 crowdsecurity/http-probing                 ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-probing.yaml
 crowdsecurity/http-sensitive-files         ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-sensitive-files.yaml
 crowdsecurity/http-crawl-non_statics       ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-crawl-non_statics.yaml
 crowdsecurity/ssh-slow-bf                  ✔️  enabled  0.2      /etc/crowdsec/scenarios/ssh-slow-bf.yaml
 crowdsecurity/http-sqli-probing            ✔️  enabled  0.2      /etc/crowdsec/scenarios/http-sqli-probing.yaml
--------------------------------------------------------------------------------------------------------------------------
INFO[26-02-2022 09:08:48 PM] COLLECTIONS:
------------------------------------------------------------------------------------------------------------
 NAME                               📦 STATUS   VERSION  LOCAL PATH
------------------------------------------------------------------------------------------------------------
 crowdsecurity/base-http-scenarios  ✔️  enabled  0.5      /etc/crowdsec/collections/base-http-scenarios.yaml
 crowdsecurity/sshd                 ✔️  enabled  0.2      /etc/crowdsec/collections/sshd.yaml
 crowdsecurity/linux                ✔️  enabled  0.2      /etc/crowdsec/collections/linux.yaml
 crowdsecurity/nginx                ✔️  enabled  0.1      /etc/crowdsec/collections/nginx.yaml
------------------------------------------------------------------------------------------------------------
INFO[26-02-2022 09:08:48 PM] POSTOVERFLOWS:
--------------------------------------
 NAME  📦 STATUS  VERSION  LOCAL PATH
--------------------------------------
--------------------------------------

Possiamo sempre tenere sotto controllo i dati graficamente con la dashboard http://127.0.0.1:3000/ utilizzando l’username [email protected] e la password !!Cr0wdS3c_M3t4b4s3??

Bloccare gli attacchi

Ora che riusciamo a rilevare gli attacchi dobbiamo proteggerci e per far questo dobbiamo installare e configurare il buttafuori (bouncer). Installiamo il Crowdsec iptables bouncer sulla macchina host (nel mio caso una Rocky Linux 8.5)

# curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.rpm.sh | bash
# dnf install crowdsec-firewall-bouncer-iptables

come visto nell’articolo di Crowdsec centralizzato per poter segnalare al buttafuori gli ip malevoli è necessario generare una chiave api univoca

# docker-compose exec crowdsec cscli bouncers add HostFirewallBouncer
Api key for 'HostFirewallBouncer':

   81d55de358ef393e27768594057cf40b

Please keep this key since you will not be able to retrieve it!

editiamo il file /etc/crowdsec/cs-firewall-bouncer/cs-firewall-bouncer.yaml e impostiamo:

  • api_url
  • api_key
  • iptables_chains
  • disable_ipv6
mode: iptables
piddir: /var/run/
update_frequency: 10s
daemonize: true
log_mode: file
log_dir: /var/log/
log_level: info
api_url: http://172.20.0.4:8080/
api_key: 81d55de358ef393e27768594057cf40b
disable_ipv6: true
#if present, insert rule in those chains
iptables_chains:
 - DOCKER-USER

e riavviamo il bouncer

# systemctl restart crowdsec-firewall-bouncer.service

Spero che questa piccola guida vi sia da ispirazione per i vostri stack.


Le opinioni in quanto tali sono opinabili e nulla ti vieta di approfondire l’argomento.

Risorse: