En el post en el que mostraba un ejemplo de configuración de traefik y un container para publicar una web, iniciaba con una lista de instalación. Dentro de esa lista se encontraba Fail2Ban.

La definición del archivo traefik.yml era el siguiente:

entryPoints:
  web:
    address: :80
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: :443
api:
  dashboard: true
  insecure: false
providers:
  docker:
    watch: true
    network: web
    exposedByDefault: false
accessLog:
  filePath: /var/log/access.log
  filters:
    statusCodes:
      - 400-499
    retryAttempts: true
  fields:
    names:
      StartUTC: drop
certificatesResolvers:
  letsencrypt:
    acme:
      email: tu_email@dominio.com.ar
      storage: /etc/traefik/letsencrypt/acme.json
      caServer: https://acme-v02.api.letsencrypt.org/directory
      tlsChallenge: true

Siendo que tenemos el dashboard activado con credenciales (explicado también en ese post), vamos a configurar Fail2Ban para evitar/reducir ataques de fuerza bruta.

La sección de la configuración que nos va a ser de utilidad es ésta:

accessLog:
  filePath: /var/log/access.log
  filters:
    statusCodes:
      - 400-499
    retryAttempts: true
  fields:
    names:
      StartUTC: drop

¿Qué significan esos parámetros?

  • Con filePath estamos especificando cuál será el path de los logs de acceso de Traefik (recordar que eso es absoluto dentro del container pero relativo para el host)
  • El uso del filtro statusCodes será para indicar qué logs serán usados luego por Fail2Ban.
  • El parámetro retryAttemps es para que se guarden todos los intentos y reintentos de autenticación.

Ahora nos toca ir hacia la configuración de Fail2Ban específica.

Como expliqué, para el ejemplo estoy usando Debian. Aquí, al instalar Fail2Ban encotramos que existe una primera y básica regla para usar con Traefik.

La podemos encontrar en /etc/fail2ban/filter.d y el archivo se llama traefik-auth.conf. El contenido es:

# Fail2ban filter configuration for traefik :: auth
# used to ban hosts, that were failed through traefik
#
# Author: CrazyMax
#
# To use 'traefik-auth' filter you have to configure your Traefik instance to write
# the access logs as describe in https://docs.traefik.io/configuration/logs/#access-logs
# into a log file on host and specifiy users for Basic Authentication
# https://docs.traefik.io/configuration/entrypoints/#basic-authentication
#
# Example:
#
# version: "3.2"
#
# services:
#   traefik:
#     image: traefik:latest
#     command:
#       - "--loglevel=INFO"
#       - "--accesslog=true"
#       - "--accessLog.filePath=/var/log/access.log"
# #       - "--accessLog.filters.statusCodes=400-499"
#       - "--defaultentrypoints=http,https"
#       - "--entryPoints=Name:http Address::80"
#       - "--entryPoints=Name:https Address::443 TLS"
#       - "--docker.domain=example.com"
#       - "--docker.watch=true"
#       - "--docker.exposedbydefault=false"
#       - "--api=true"
#       - "--api.dashboard=true"
#     ports:
#       - target: 80
#         published: 80
#         protocol: tcp
#         mode: host
#       - target: 443
#         published: 443
#         protocol: tcp
#         mode: host
#     labels:
#       - "traefik.enable=true"
#       - "traefik.port=8080"
#       - "traefik.backend=traefik"
#       - "traefik.frontend.rule=Host:traefik.example.com"
#       - "traefik.frontend.auth.basic.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/"
#     volumes:
#       - "/var/log/traefik:/var/log"
#       - "/var/run/docker.sock:/var/run/docker.sock"
#     restart: always
#

[Definition]

# Parameter "method" can be used to specifiy request method
req-method = \S+
# Usage example (for jail.local):
#   filter = traefik-auth[req-method="GET|POST|HEAD"]

failregex = ^<HOST> \- <usrre-<mode>> \[\] \"(?:<req-method>) [^\"]+\" 401\b

ignoreregex =

# Parameter "mode": normal (default), ddos or aggressive
# Usage example (for jail.local):
#   [traefik-auth]
#   mode = aggressive
#   # or another jail (rewrite filter parameters of jail):
#   [traefik-auth-ddos]
#   filter = traefik-auth[mode=ddos]
#
mode = normal

# part of failregex matches user name (must be available in normal mode, must be empty in ddos mode, and both for aggressive mode):
usrre-normal = (?!- )<F-USER>\S+</F-USER>
usrre-ddos = -
usrre-aggressive = <F-USER>\S+</F-USER>

Vamos a usar este filtro entonces, pero para que funcione tenemos que definir la acción que se ejecutará al aplicarse el filtro de forma efectiva.

Cambiamos de directorio a /etc/fail2ban/jail.d y creamos un archivo de texto (el nombre es arbitrario) traefik.conf con algo como esto:

[traefik-auth]
enabled = true
chain = DOCKER-USER
port = http,https
filter = traefik-auth
logpath = /path/al/container/traefik/log/access.log
maxretry = 3 
bantime  = 30m

Una vez que hayamos guardado el archivo, reiniciamos el servicio.

service fail2ban restart

Ahora intento ingresar más de 3 veces con un usuario incorrecto para luego recibir este mensaje.

Unite a la lista de suscriptores

Una vez por mes vas a recibir un mail con contenido que se relaciona con lo que vemos en el blog, que extiende o anticipa lo que hacemos en Twitch, y que también suele incluir anécdotas del MundoReal® y algún que otro link.

Es gratis, no tiene publicidad y con el double opt-in de Mailchimp.