528 - Más herramientas para proteger tu Linux
Dos herramientas para proteger tu servidor #linux , la clásica #fail2ban y #crowdsec ambas para intentar evitar ataques de terceros e intentos de acceso
Después del episodio del podcast número 526, titulado sobre seguridad en Docker y selfhosted, no te creas que me quedé muy tranquilo. En ningún caso, quería dar la impresión que servidor Linux es inaccesible. Mas bien, el objetivo, era dar importancia a cada uno de los actores que intervienen en la ecuación. Y es que básicamente, en la gran mayoría de las ocasiones, el responsable es el octavo pasajero, se trata de un error de capa 8, es decir, que normalmente somos los usuarios, que descuidamos nuestras obligaciones. Así, que para ayudarte con esto, en este episodio te quiero hablar de dos herramientas mas para proteger tu Linux. Ya sea un servidor que esté expuesto a Internet como tu propio equipo.
Ya te habrás imaginado, que esto tiene mas sentido para equipos expuestos a internet, pero esto no quita, que cualquier equipo sea susceptible de un ataque. Sin embargo, lo está claro que un servidor que tiene servicios expuestos a internet, es mas susceptible, que otro que está desconectado de internet, e incluso completamente desconectado.
Más herramientas para proteger tu Linux
Un poquito de background
Hace ya algún tiempo que tengo instaladas las herramientas que en este episodio del podcast te quiero comentar. Sin embargo, durante estos últimos días, les he estado dando algo mas de cariño. Mas que nada, por tener las cosas frescas, antes de contarlas.
La cuestión, que he estado diferentes pruebas, pero sobre todo lo que he estado haciendo ha sido banearme una y otra vez. Tan es así, que en un momento determinado, estaba tan preocupado, que no sabía si había terminado con mi VPS… Hasta que me di cuenta de que estaba baneado.
Sobre fail2ban
La primera de las herramientas de las que te quiero hablar es fail2ban. Esta es una vieja conocida de atareao.es. En concreto te hablé sobre ella en un artículo titulaod bloquear accesos indeseables en tu servidor. Pero también, te hablé en el episodio 292 del podcast, titulado seguridad básica en tu servidor, o incluso en uno episodio dedicado a securizar y homogeneizar la Raspberry.
Sin embargo, en casi todos estos artículos y episodios del podcast, lo encontrarás instalado directamente sobre la máquina. Sin embargo, con la migración de muchos de mis servicios a Docker, este también se vino con ellos, aunque no como yo esperaba.
Actualmente estoy utilizando Traefik como mi proxy inverso de referencia para poner todos mis servicios en funcionamiento de forma eficiente. Así en el episodio 439, te hablé sobre Dashboards, Flatnotes y Traefik con fail2ban.
En este episodio te comentaba que se había implementado un plugin que hacía las cosas de fail2ban, pero utilizando directamente Traefik. Es decir, ante algunas de las acciones que se pudieran hacer directamente este plugin, se encargaba de denegar el acceso.
fail2ban como complemento
Utilizar fail2ban como complemento de Traefik, me resulta sumamente interesante, en tanto en cuanto no es necesario dar mas acceso al socket de Docker, del necesario, pero sobre todo, porque fail2ban no tiene que tocar los iptables, simplemente se tienes que hacer cargo de denegar el servicio. Esto, ya lo comenté en el episodio anterior del podcast.
Sin embargo, este complemento de Traefik, es un quiero y no puedo, es un principio de lo que puede llegar a ser, pero que todavía no es. Ahora mismo, solo impide o permite el acceso a determinadas direcciones, realmente muy flojo y decepcionante.
Sinceramente, espero, que en futuras versiones, esto se mejore, para no tener que gestionar las iptables únicamente para esto.
Igual que te digo esto, también te tengo que decir que además de esto, puedes encontrar todo tipo de complementos para Traefik, para mejorar sinceramente la seguridad y mucho mas. Desde complementos que impiden el acceso desde la red Tor, como otros complementos que bloquean acceso en función del origen.
Tengo que confesarte que existen una barbaridad de complementos, y todavía no he tenido la oportunidad de revisarlos todos, pero es una auténtica pasada.
fail2ban en Docker
Después de haber tenido fail2ban
directamente en la máquina, finalmente decidí implementarlo en Docker, e integrarlo con Traefik
, para de esta manera evitar accesos indeseados.
Dicho esto, tengo que decirte que hasta el momento, lo único que he conseguido ha sido banearme a mi en varias ocasiones, y que como te decía anteriormente asustarme, porque no conseguía acceder de ninguna de las maneras.
Lo que si me sorprende es la cantidad de intentos de acceso que hay vía ssh, por supuesto utilizando usuario y contraseña. Esta es la principal razón para recomendarte que deshabilites este acceso y siempre accedas vía clave público-privada.
El docker-compose.yml
, que estoy utilizando es el esiguiente,
version: "3.7"
services:
fail2ban:
image: crazymax/fail2ban:latest
container_name: fail2ban
init: true
network_mode: "host"
cap_add:
- NET_ADMIN
- NET_RAW
environment:
- TZ=Europe/Madrid
volumes:
- ./data:/data
- /var/log:/var/log/:ro
- traefik_logs:/traefik_logs/:ro
volumes:
traefik_logs:
external: true
Aquí lo interesante es que tienes que montar el volumen traefik_logs
, que es donde van los logs de Traefik como un volumen externo. En cuanto al jail
para Traefik, es el siguiente,
[traefik-auth]
enabled = true
chain = DOCKER-USER
ignoreip = XXX.XXX.XXX.XXX
port = http,https
filter = traefik-auth
mode = aggressive
logpath = /traefik_logs/access.log
bantime = 24h
findtime = 1h
maxretry = 2
[traefik-auth-ddos]
filter = traefik-auth[mode=ddos]
[traefik-botsearch]
enabled = true chain = DOCKER-USER port = http,https filter = traefik-botsearch logpath = /traefik_logs/access.log bantime = 24h findtime = 1h maxretry = 2
Fíjate que aquí he incluído mi IP, para evitar que me vuelva a banear.
Por otro lado, en el caso del docker-compose.yml
de Traefik el volumen, lo tengo definido de la siguiente forma,
services:
traefik:
..
volumes:
- logs:/var/log/traefik
volumes:
logs: {}
Con esto tengo resuelto tanto los intentos de acceso vía ssh
, como los intentos de acceso a los distintos sitios. A partir de aquí, simplemente se trata de ir añadiendo reglas específicas para cada uno de los servicios que tenemos, ya sea WordPress, Filebrowser, etc.
Admeás utilizando just
, tengo un par de comandos que me dan información sobre lo que sucede, así como quitarme el baneo,
unban ip:
docker exec fail2ban fail2ban-client set traefik-auth unbanip {{ip}}
stats:
docker exec fail2ban fail2ban-client status sshd
docker exec fail2ban fail2ban-client status traefik-auth
docker exec fail2ban fail2ban-client status traefik-botsearch
docker exec fail2ban fail2ban-client status wordpress
Crowdsec
Sobre Crowdsec tienes un interesante conjunto de artículos de Héctor en bujarra.como, y en particular el primero de ellos dedica a proteger nuestras máquinas con Crowdsec.
Si no conoces Crowdsec, indicarte que se trata de una herramienta que detecta y bloquea accesos a máquinas, con independencias de que sea una red interna, que una máquina en internet, un Linux, un Windows, un contenedor… Lo que sea.
Así, esta herramienta está vigilante, de forma que ya sea que detecte un ataque de denegación de servicio, que detecte un escaneo de puertos, o de vulnerabilidades, o accesos incorrectos, o lo que sea, bloqueará el acceso.
Crowdsec y Traefik
Como te decía con fail2ban
, lo que no me gusta es que altera los iptables. Sin embargo, Crowdsec, precisamente la ventaja que tiene es que se integra con Traefik, y no necesita ni acceso al socket de Docker, ni acceso al host, ni nada, de nada… simplemente, necesita acceso a los logs de Traefik. Una maravilla.
Así, mi configuración del docker-compose.yml
, es la siguiente,
version: '3.8'
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
container_name: crowdsec
init: true
environment:
GID: "${GID-1000}"
COLLECTIONS: "crowdsecurity/linux crowdsecurity/traefik"
volumes:
- ./config/acquis.yml:/etc/crowdsec/acquis.yaml
- crowdsec-db:/var/lib/crowdsec/data/
- crowdsec-config:/etc/crowdsec/
- traefik_logs:/var/log/traefik/:ro
networks:
- proxy
restart: unless-stopped
bouncer-traefik:
image: docker.io/fbonalair/traefik-crowdsec-bouncer:latest
container_name: bouncer-traefik
init: true
environment:
CROWDSEC_BOUNCER_API_KEY: XXXXXXXXXXXXXXXXXXXXXX
CROWDSEC_AGENT_HOST: crowdsec:8080
networks:
- proxy # same network as traefik + crowdsec
depends_on:
- crowdsec
restart: unless-stopped
volumes:
crowdsec-db:
crowdsec-config:
traefik_logs: # this will be the name of the volume from trarfic logs
external: true # remove if traefik is running on same stack
networks:
proxy:
external: true
Configuración con Traefik
La configuración con traefik, es algo mas compleja, ya que tienes que declarar en varios sitios. Por un lado, en la configuración estática, que en mi caso es la siguiente, traefik.yml
,
api:
dashboard: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
permanent: true
middlewares:
- crowdsec-bouncer@file
https:
address: ":443"
http:
middlewares:
- crowdsec-bouncer@file
serversTransport:
maxIdleConnsPerHost: 1
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
network: proxy
file:
directory: /conf
watch: true
log:
level: INFO
filePath: "/var/log/traefik/traefik.log"
accessLog:
filePath: "/var/log/traefik/access.log"
bufferingSize: 100
fields:
defaultMode: keep
names:
ClientUsername: keep
headers:
defaultMode: keep
names:
Content-Type: keep
X-Forwarded-For: keep
filters:
statusCodes:
- "300-302"
- "400-409"
retryAttempts: true
minDuration: "10ms"
certificatesResolvers:
myresolver:
acme:
email: lorenzo.carbonell.cerezo@gmail.com
storage: acme.json
httpChallenge:
entryPoint: http
experimental:
plugins:
fail2ban:
moduleName: "github.com/tomMoulard/fail2ban"
version: "v0.6.6"
Mientras que la configuración dinámica es como sigue,
http:
middlewares:
crowdsec-bouncer:
forwardauth:
address: http://bouncer-traefik:8080/api/v1/forwardAuth
trustForwardHeader: true
http2https:
redirectScheme:
scheme: https
permanent: true
test-errors:
errors:
status:
- "400-499"
- "500-599"
service: serviceError
query: "/{status}.html"
my-torblock:
plugin:
torblock:
enabled: true
traefik-real-ip:
plugin:
traefik-real-ip:
excludednets:
- "1.1.1.1/24"
my-fail2ban:
plugin:
fail2ban:
loglevel: "INFO"
blacklist:
ip:
- 192.168.0.0/24
rules:
urlregexps:
- regexp: "/whoami"
mode: allow
- regexp: "/do-not-access"
mode: block
- regexp: "/no"
mode: block
- regexp: "/yes"
mode: allow
bantime: "3h"
findtime: "10m"
maxretry: 4
enabled: true
whitelist:
ip:
- ::1
- 127.0.0.1
Algunas herramientas complementarias
En mi caso, utilizo just
, para la ejecución y mantenimiento de scripts. Para el caso de Crowdsec
decisions:
docker exec crowdsec cscli decisions list
metrics:
docker exec crowdsec cscli metrics
alerts:
docker exec crowdsec cscli alerts list
Más información,
Espero que te haya gustado este nuevo episodio del podcast. Si puedes, te agradecería una valoración en iVoox y/o en Apple Podcast.