From 91cba8080cf936d6da8d6fd506951cae38aa0134 Mon Sep 17 00:00:00 2001 From: Hector Date: Sat, 6 Feb 2021 12:24:31 +0000 Subject: [PATCH] feat: export number of banned ips Export the number of banned IPs stored in the fail2ban database as well as the number of bad IPs. Update the queries used to collect data to better handle cases where the database table for bad/banned IPs is empty. The new query always lists all jails, even when the count is zero. --- db/db.go | 13 +++++++++++-- exporter.go | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/db/db.go b/db/db.go index f7146df..cd425c4 100644 --- a/db/db.go +++ b/db/db.go @@ -5,7 +5,8 @@ import ( "log" ) -const queryBadIpsPerJail = "SELECT jail, COUNT(1) FROM bips GROUP BY jail" +const queryBadIpsPerJail = "SELECT j.name, (SELECT COUNT(1) FROM bips b WHERE j.name = b.jail) FROM jails j" +const queryBannedIpsPerJail = "SELECT j.name, (SELECT COUNT(1) FROM bans b WHERE j.name = b.jail) FROM jails j" type Fail2BanDB struct { DatabasePath string @@ -23,8 +24,16 @@ func MustConnectToDb(databasePath string) *Fail2BanDB { } } +func (db *Fail2BanDB) CountBannedIpsPerJail() (map[string]int, error) { + return db.RunJailNameToCountQuery(queryBannedIpsPerJail) +} + func (db *Fail2BanDB) CountBadIpsPerJail() (map[string]int, error) { - stmt, err := db.sqliteDB.Prepare(queryBadIpsPerJail) + return db.RunJailNameToCountQuery(queryBadIpsPerJail) +} + +func (db *Fail2BanDB) RunJailNameToCountQuery(query string) (map[string]int, error) { + stmt, err := db.sqliteDB.Prepare(query) defer db.mustCloseStatement(stmt) if err != nil { diff --git a/exporter.go b/exporter.go index 0fa3803..19b2d7d 100644 --- a/exporter.go +++ b/exporter.go @@ -18,6 +18,11 @@ var ( "Was the last fail2ban query successful.", nil, nil, ) + metricBannedIpsPerJail = prometheus.NewDesc( + prometheus.BuildFQName(namespace, "", "banned_ips"), + "Number of banned IPs stored in the database (per jail).", + []string{"jail"}, nil, + ) metricBadIpsPerJail = prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "bad_ips"), "Number of bad IPs stored in the database (per jail).", @@ -31,6 +36,7 @@ type Exporter struct { func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- metricUp ch <- metricBadIpsPerJail + ch <- metricBannedIpsPerJail } func (e *Exporter) Collect(ch chan<- prometheus.Metric) { @@ -38,6 +44,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { metricUp, prometheus.GaugeValue, 1, ) collectBadIpsPerJailMetrics(ch) + collectBannedIpsPerJailMetrics(ch) } func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) { @@ -53,6 +60,19 @@ func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) { } } +func collectBannedIpsPerJailMetrics(ch chan<- prometheus.Metric) { + jailNameToCountMap, err := db.CountBannedIpsPerJail() + if err != nil { + log.Print(err) + } + + for jailName, count := range jailNameToCountMap { + ch <- prometheus.MustNewConstMetric( + metricBannedIpsPerJail, prometheus.GaugeValue, float64(count), jailName, + ) + } +} + func main() { log.Print("starting fail2ban exporter")