#!/bin/bash # -*- sh -*- : <<=cut =head1 NAME reaction - Plugin to monitor reaction blacklists =head1 APPLICABLE SYSTEMS All systems with "reaction" (https://reaction.ppom.me) and "jq". =head1 CONFIGURATION The following is the default configuration [reaction] env.reaction /usr/bin/reaction env.config /etc/reaction env.socket /run/reaction/reaction.sock The plugin needs read and write access to the reaction control socket, so it usually has to run as root: [reaction] user root Warning or critical thresholds can be configured via environment variables either globally ("warning" and "critical") or separately for each field ("foo_warning" or "foo_critical"). =head1 INTERPRETATION This plugin shows a graph with one line per reaction stream/filter, each showing the number of currently banned addresses (that is, addresses with a pending unban action) for that filter. In addition, a line with the total number of banned addresses is displayed. =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf =head1 AUTHOR Bernard Cafarelli =head1 LICENSE GPLv2 =cut . "$MUNIN_LIBDIR/plugins/plugin.sh" ############################## # Configurable variables reaction=${reaction:-/usr/bin/reaction} config=${config:-/etc/reaction} socket=${socket:-/run/reaction/reaction.sock} ############################## # Functions # List configured "stream filter" pairs, one per line list_filters() { "$reaction" test-config -c "$config" -f json 2>/dev/null \ | jq -r '.streams | to_entries[] as $s | ($s.value.filters // {} | keys[]) as $f | "\($s.key) \($f)"' } # Count currently banned addresses (those with a pending action) per filter, # printed as "stream filter count" lines banned_counts() { "$reaction" show -s "$socket" -f json 2>/dev/null \ | jq -r 'to_entries[] as $s | $s.value | to_entries[] as $f | "\($s.key) \($f.key) " + ([$f.value | to_entries[] | select((.value.actions // {}) | length > 0)] | length | tostring)' } # Print the munin values values() { local counts counts=$(banned_counts) list_filters | while read -r stream filter; do fieldname=$(clean_fieldname "${stream}_${filter}") num=$(echo "$counts" | awk -v s="$stream" -v f="$filter" \ '$1==s && $2==f {print $3; found=1} END {if (!found) print 0}') echo "${fieldname}.value ${num}" done } # Print the munin config config() { echo 'graph_title Hosts blacklisted by reaction' echo 'graph_info This graph shows the number of hosts blacklisted by reaction' echo 'graph_category network' echo 'graph_vlabel Number of hosts' echo 'graph_args --base 1000 -l 0' echo 'graph_total total' list_filters | while read -r stream filter; do fieldname=$(clean_fieldname "${stream}_${filter}") echo "${fieldname}.label ${stream}.${filter}" echo "${fieldname}.draw LINE2" print_thresholds "${fieldname}" warning critical done } # Print autoconfiguration hint autoconf() { if [ -x "$reaction" ]; then if "$reaction" show -s "$socket" >/dev/null 2>&1; then echo "yes" else echo "no (reaction daemon does not respond)" fi else echo "no (${reaction} not found or not executable)" fi exit } ############################## # Main case $1 in config) config ;; autoconf) autoconf ;; *) values ;; esac