Fail2ban

Dashboard to have a Overview of the Fail2Ban logs collected via Promtail/Loki

Fail2ban screenshot 1

This is my try to create a Dashboard that visualize the Logs of Fail2Ban. It integrates with the GeoLite Database to display a Heatmap.

Since promtail got deprecated here is my Alloy Config:

yaml
// Get the fail2ban log and integrate GeoIP
local.file_match "fail2ban" {
        path_targets = [{
                __address__ = "localhost",
                __path__    = "/var/log/fail2ban.log",
                job         = "fail2ban",
        }]
}
loki.process "fail2ban" {
        forward_to = [loki.write.loki.receiver]

        stage.multiline {
                firstline     = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}"
                max_wait_time = "10s"
        }

        stage.regex {
                expression = "^(?s)(?P<time>\\S+? \\S+?) (fail2ban\\.)(?P<component>\\S+)\\s* \\[(?P<pid>\\S+)\\]: (?P<priority>\\S+)\\s* (?P<message>.*?)$"
        }

        stage.timestamp {
                source = "time"
                format = "2006-01-02 15:04:05,000"
        }

        stage.labels {
                values = {
                        component = null,
                        priority  = null,
                }
        }

        stage.output {
                source = "message"
        }
	stage.match {
                selector = "{job=\"fail2ban\"} |~ \"\\\\\\\\[\\\\\\\\S+\\\\\\\\] .*\""

                stage.regex {
                        expression = "(\\[(?P<jail>\\S+)\\] )?(?P<message>.*?)$"
                }

                stage.labels {
                        values = {
                                jail = null,
                        }
                }

                stage.output {
                        source = "message"
                }
        }

        stage.regex {
                expression = ".*?(?P<remote_addr>\\d+\\.\\d+\\.\\d+\\.\\d+).*"
        }

        stage.geoip {
                db      = "/GeoLite2-City.mmdb"
                source  = "remote_addr"
                db_type = "city"
        }
	stage.labels {
            values = {
                geoip_city_name          = "",
                geoip_country_name       = "",
                geoip_country_code       = "",
                geoip_continent_name     = "",
                geoip_continent_code     = "",
                geoip_location_latitude  = "",
                geoip_location_longitude = "",
                geoip_postal_code        = "",
                geoip_timezone           = "",
                geoip_subdivision_name   = "",
                geoip_subdivision_code   = "",
            }
        }

        stage.label_drop {
                values = ["filename"]
        }
}
loki.source.file "fail2ban" {
        targets               = local.file_match.fail2ban.targets
        forward_to            = [loki.process.fail2ban.receiver]
}
loki.write "loki" {
	endpoint {
		url = string.format(
			"http://%s/loki/api/v1/push",
			coalesce(sys.env("LOKI_HOST"), "loki:3100"),
		)
	}
}

I will also post my promtail config:

yaml
- job_name: fail2ban
  static_configs:
    - targets:
        - localhost
      labels:
        job: fail2ban
        __path__: /var/log/fail2ban.log
  pipeline_stages:
    - multiline:
        firstline: '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'
    - regex:
        expression: >-
          ^(?s)(?P<time>\S+? \S+?)
          (fail2ban\.)(?P<component>\S+)\s*
          \[(?P<pid>\S+)\]:
          (?P<priority>\S+)\s*
          (?P<message>.*?)$
    - timestamp:
        source: time
        format: '2006-01-02 15:04:05,000'
    - labels:
        component:
        priority:
    - output:
        source: message
    - match:
        selector: '{job="fail2ban"} |~ "\\\\[\\\\S+\\\\] .*"'
        stages:
          - regex:
              expression: '(\[(?P<jail>\S+)\] )?(?P<message>.*?)$'
          - labels:
              jail:
          - output:
              source: message
    - regex:
        expression: '.*?(?P<remote_addr>\d+\.\d+\.\d+\.\d+).*'
    - geoip:
        db: /GeoLite2-City.mmdb
        source: remote_addr
        db_type: city
    - labeldrop:
        - filename
Revisions
RevisionDescriptionCreated

Get this dashboard

Import the dashboard template

or

Download JSON

Datasource
Dependencies