You've already forked prometheus-fail2ban-exporter
							
							Merge branch 'add-metrics-on-basic-jail-configuration' into 'main'
Add metrics on basic jail configuration See merge request hectorjsmith/fail2ban-prometheus-exporter!42
This commit is contained in:
		
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							@@ -157,6 +157,9 @@ Exposed metrics:
 | 
				
			|||||||
* `jail_banned_total` (per jail) - Total number of banned IPs since fail2ban startup (includes expired bans)
 | 
					* `jail_banned_total` (per jail) - Total number of banned IPs since fail2ban startup (includes expired bans)
 | 
				
			||||||
* `jail_failed_current` (per jail) - Number of current failures
 | 
					* `jail_failed_current` (per jail) - Number of current failures
 | 
				
			||||||
* `jail_failed_total` (per jail) - Total number of failures since fail2ban startup
 | 
					* `jail_failed_total` (per jail) - Total number of failures since fail2ban startup
 | 
				
			||||||
 | 
					* `jail_config_ban_time` (per jail) - How long an IP is banned for in this jail (in seconds)
 | 
				
			||||||
 | 
					* `jail_config_find_time` (per jail) - How far back the filter will look for failures in this jail (in seconds)
 | 
				
			||||||
 | 
					* `jail_config_max_retry` (per jail) - The max number of failures allowed before banning an IP in this jail
 | 
				
			||||||
* `version` - Version string of the exporter and fail2ban
 | 
					* `version` - Version string of the exporter and fail2ban
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Sample**
 | 
					**Sample**
 | 
				
			||||||
@@ -186,6 +189,18 @@ f2b_jail_failed_current{jail="sshd"} 6
 | 
				
			|||||||
# TYPE f2b_jail_failed_total gauge
 | 
					# TYPE f2b_jail_failed_total gauge
 | 
				
			||||||
f2b_jail_failed_total{jail="recidive"} 7
 | 
					f2b_jail_failed_total{jail="recidive"} 7
 | 
				
			||||||
f2b_jail_failed_total{jail="sshd"} 125
 | 
					f2b_jail_failed_total{jail="sshd"} 125
 | 
				
			||||||
 | 
					# HELP f2b_config_jail_ban_time How long an IP is banned for in this jail (in seconds)
 | 
				
			||||||
 | 
					# TYPE f2b_config_jail_ban_time gauge
 | 
				
			||||||
 | 
					f2b_config_jail_ban_time{jail="recidive"} 604800
 | 
				
			||||||
 | 
					f2b_config_jail_ban_time{jail="sshd"} 600
 | 
				
			||||||
 | 
					# HELP f2b_config_jail_find_time How far back will the filter look for failures in this jail (in seconds)
 | 
				
			||||||
 | 
					# TYPE f2b_config_jail_find_time gauge
 | 
				
			||||||
 | 
					f2b_config_jail_find_time{jail="recidive"} 86400
 | 
				
			||||||
 | 
					f2b_config_jail_find_time{jail="sshd"} 600
 | 
				
			||||||
 | 
					# HELP f2b_config_jail_max_retries The number of failures allowed until the IP is banned by this jail
 | 
				
			||||||
 | 
					# TYPE f2b_config_jail_max_retries gauge
 | 
				
			||||||
 | 
					f2b_config_jail_max_retries{jail="recidive"} 5
 | 
				
			||||||
 | 
					f2b_config_jail_max_retries{jail="sshd"} 5
 | 
				
			||||||
# HELP f2b_up Check if the fail2ban server is up
 | 
					# HELP f2b_up Check if the fail2ban server is up
 | 
				
			||||||
# TYPE f2b_up gauge
 | 
					# TYPE f2b_up gauge
 | 
				
			||||||
f2b_up 1
 | 
					f2b_up 1
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,21 @@ var (
 | 
				
			|||||||
		"Total number of IPs banned by this jail (includes expired bans)",
 | 
							"Total number of IPs banned by this jail (includes expired bans)",
 | 
				
			||||||
		[]string{"jail"}, nil,
 | 
							[]string{"jail"}, nil,
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
						metricJailBanTime = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, "config", "jail_ban_time"),
 | 
				
			||||||
 | 
							"How long an IP is banned for in this jail (in seconds)",
 | 
				
			||||||
 | 
							[]string{"jail"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						metricJailFindTime = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, "config", "jail_find_time"),
 | 
				
			||||||
 | 
							"How far back will the filter look for failures in this jail (in seconds)",
 | 
				
			||||||
 | 
							[]string{"jail"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						metricJailMaxRetry = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, "config", "jail_max_retries"),
 | 
				
			||||||
 | 
							"The number of failures allowed until the IP is banned by this jail",
 | 
				
			||||||
 | 
							[]string{"jail"}, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
	metricVersionInfo = prometheus.NewDesc(
 | 
						metricVersionInfo = prometheus.NewDesc(
 | 
				
			||||||
		prometheus.BuildFQName(namespace, "", "version"),
 | 
							prometheus.BuildFQName(namespace, "", "version"),
 | 
				
			||||||
		"Version of the exporter and fail2ban server",
 | 
							"Version of the exporter and fail2ban server",
 | 
				
			||||||
@@ -98,6 +113,7 @@ func (c *Collector) collectJailMetrics(ch chan<- prometheus.Metric, s *socket.Fa
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for i := range jails {
 | 
						for i := range jails {
 | 
				
			||||||
		c.collectJailStatsMetric(ch, s, jails[i])
 | 
							c.collectJailStatsMetric(ch, s, jails[i])
 | 
				
			||||||
 | 
							c.collectJailConfigMetrics(ch, s, jails[i])
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,6 +139,36 @@ func (c *Collector) collectJailStatsMetric(ch chan<- prometheus.Metric, s *socke
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Collector) collectJailConfigMetrics(ch chan<- prometheus.Metric, s *socket.Fail2BanSocket, jail string) {
 | 
				
			||||||
 | 
						banTime, err := s.GetJailBanTime(jail)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.socketRequestErrorCount++
 | 
				
			||||||
 | 
							log.Printf("failed to get ban time for jail %s: %v", jail, err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(
 | 
				
			||||||
 | 
								metricJailBanTime, prometheus.GaugeValue, float64(banTime), jail,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						findTime, err := s.GetJailFindTime(jail)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.socketRequestErrorCount++
 | 
				
			||||||
 | 
							log.Printf("failed to get find time for jail %s: %v", jail, err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(
 | 
				
			||||||
 | 
								metricJailFindTime, prometheus.GaugeValue, float64(findTime), jail,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						maxRetry, err := s.GetJailMaxRetries(jail)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.socketRequestErrorCount++
 | 
				
			||||||
 | 
							log.Printf("failed to get max retries for jail %s: %v", jail, err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(
 | 
				
			||||||
 | 
								metricJailMaxRetry, prometheus.GaugeValue, float64(maxRetry), jail,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Collector) collectVersionMetric(ch chan<- prometheus.Metric, s *socket.Fail2BanSocket) {
 | 
					func (c *Collector) collectVersionMetric(ch chan<- prometheus.Metric, s *socket.Fail2BanSocket) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	var fail2banVersion = ""
 | 
						var fail2banVersion = ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,6 +118,21 @@ func (s *Fail2BanSocket) GetJailStats(jail string) (JailStats, error) {
 | 
				
			|||||||
	return stats, newBadFormatError(statusCommand, response)
 | 
						return stats, newBadFormatError(statusCommand, response)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Fail2BanSocket) GetJailBanTime(jail string) (int, error) {
 | 
				
			||||||
 | 
						command := fmt.Sprintf(banTimeCommandFmt, jail)
 | 
				
			||||||
 | 
						return s.sendSimpleIntCommand(command)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Fail2BanSocket) GetJailFindTime(jail string) (int, error) {
 | 
				
			||||||
 | 
						command := fmt.Sprintf(findTimeCommandFmt, jail)
 | 
				
			||||||
 | 
						return s.sendSimpleIntCommand(command)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Fail2BanSocket) GetJailMaxRetries(jail string) (int, error) {
 | 
				
			||||||
 | 
						command := fmt.Sprintf(maxRetriesCommandFmt, jail)
 | 
				
			||||||
 | 
						return s.sendSimpleIntCommand(command)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Fail2BanSocket) GetServerVersion() (string, error) {
 | 
					func (s *Fail2BanSocket) GetServerVersion() (string, error) {
 | 
				
			||||||
	response, err := s.sendCommand([]string{versionCommand})
 | 
						response, err := s.sendCommand([]string{versionCommand})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -132,6 +147,22 @@ func (s *Fail2BanSocket) GetServerVersion() (string, error) {
 | 
				
			|||||||
	return "", newBadFormatError(versionCommand, response)
 | 
						return "", newBadFormatError(versionCommand, response)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// sendSimpleIntCommand sends a command to the fail2ban socket and parses the response to extract an int.
 | 
				
			||||||
 | 
					// This command assumes that the response data is in the format of `(d, d)` where `d` is a number.
 | 
				
			||||||
 | 
					func (s *Fail2BanSocket) sendSimpleIntCommand(command string) (int, error) {
 | 
				
			||||||
 | 
						response, err := s.sendCommand(strings.Split(command, " "))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return -1, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if lvl1, ok := response.(*types.Tuple); ok {
 | 
				
			||||||
 | 
							if banTime, ok := lvl1.Get(1).(int); ok {
 | 
				
			||||||
 | 
								return banTime, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -1, newBadFormatError(command, response)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newBadFormatError(command string, data interface{}) error {
 | 
					func newBadFormatError(command string, data interface{}) error {
 | 
				
			||||||
	return fmt.Errorf("(%s) unexpected response format - cannot parse: %v", command, data)
 | 
						return fmt.Errorf("(%s) unexpected response format - cannot parse: %v", command, data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,9 @@ const (
 | 
				
			|||||||
	pingCommand          = "ping"
 | 
						pingCommand          = "ping"
 | 
				
			||||||
	statusCommand        = "status"
 | 
						statusCommand        = "status"
 | 
				
			||||||
	versionCommand       = "version"
 | 
						versionCommand       = "version"
 | 
				
			||||||
 | 
						banTimeCommandFmt    = "get %s bantime"
 | 
				
			||||||
 | 
						findTimeCommandFmt   = "get %s findtime"
 | 
				
			||||||
 | 
						maxRetriesCommandFmt = "get %s maxretry"
 | 
				
			||||||
	socketReadBufferSize = 1024
 | 
						socketReadBufferSize = 1024
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user