#!/bin/sh set -e sleeptime='10' tmpfile='/var/tmp/node_exporter/.pfctl_exporter.prom.tmp' dstfile='/var/tmp/node_exporter/pfctl_exporter.prom' counters_pat='/var/tmp/node_exporter/.counters.pat' tracking_pat='/var/tmp/node_exporter/.tracking.pat' create_patterns() { echo x - ${counters_pat} sed -E 's/^ *X//' >${counters_pat} << ' COUNTERS' X^match .* X^bad_offset .* X^fragment .* X^short .* X^normalize .* X^memory .* X^bad_timestamp .* X^congestion .* X^ip_option .* X^proto_cksum .* X^state_mismatch .* X^state_insert .* X^state_limit .* X^src_limit .* X^synproxy .* X^map_failed .* X^max_states_per_rule .* X^max_src_states .* X^max_src_nodes .* X^max_src_conn .* X^max_src_conn_rate .* X^overload_table_insertion .* X^overload_flush_states .* X^synfloods_detected .* COUNTERS echo x - ${tracking_pat} sed -E 's/^ *X//' >${tracking_pat} << ' TRACKING' X^current_entries .* X^searches .* X^inserts .* X^removals .* TRACKING } startup() { local jail="$1" if [ -z "${jail}" ] || ! jpath=$(jls -j "${jail}" path 2>/dev/null) ; then echo "Jail not specified or not running" 1>&2 return 1 fi if ! [ -c "${jpath}/dev/pf" ] ; then echo "No /dev/pf in ${jpath}!" 1>&2 return 1 fi if [ -s "${jpath}/sbin/pfctl" ] && [ -s "{jpath}/libexec/ld-elf.so.1" ] ; then J_LD_LIBRARY_PATH='/lib' pfctl='/sbin/pfctl' elif [ "${jpath%%/root}" = "$jpath" ] && [ -s "${jpath}/root/sbin/pfctl" ] && [ -s "{jpath}/root/libexec/ld-elf.so.1" ]; then J_LD_LIBRARY_PATH='/root/lib' pfctl='/root/libexec/ld-elf.so.1 /root/sbin/pfctl' else echo "pfctl binary and/or supporting libraries not found in ${jpath}." return 1 fi } jail_collect_stats() { local jail="$1" LD_LIBRARY_PATH="${J_LD_LIBRARY_PATH}" jexec "${jail}" $pfctl -vvsi 2>/dev/null | \ tr '-' '_' | \ /usr/bin/sed -E -e 's/([^ ]) ([^ ])/\1_\2/g' -e 's/^ *//g' | \ cut -f 1,2 -w | \ tr '\t' ' ' } jail_parse_stats() { local jail="$1" local stats="$2" # State tracking table IFS="$(printf "\n\r")" for l in $(echo "$stats" | grep -f ${tracking_pat} | head -"$(wc -l < ${tracking_pat} | tr -d ' ')") ; do unset IFS set -- $l name=$1 ; value=$2 echo "jail_pf_states_${name}{name=\"${jail}\"} ${value}" done # Source tracking table IFS="$(printf "\n\r")" for l in $(echo "$stats" | grep -f ${tracking_pat} | tail -"$(wc -l < ${tracking_pat} | tr -d ' ')") ; do unset IFS set -- $l name=$1 ; value=$2 echo "jail_pf_sources_${name}{name=\"${jail}\"} ${value}" done # Syncookies IFS="$(printf "\n\r")" tags="name=\"${jail}\"" for l in $(echo "$stats" | grep -E 'highwater|lowwater|mode|active') ; do unset IFS set -- $l name=$1 ; value=${2%%_%} [ "$name" = 'highwater' ] && name='highwater_pct' [ "$name" = 'lowwater' ] && name='lowwater_pct' tags="${tags},${name}=\"${value}\"" done IFS="$(printf "\n\r")" for l in $(echo "$stats" | grep -E 'syncookies|halfopen') ; do unset IFS set -- $l name=${1##syncookies_} ; value=$2 echo "jail_pf_syncookies_${name}{${tags}} ${value}" done # Counters IFS="$(printf "\n\r")" for l in $(echo "$stats" | grep -f ${counters_pat}) ; do unset IFS set -- $l name=$1 ; value=$2 echo "jail_pf_counters{name=\"${jail}\",counter=\"${name}\"} ${value}" done } echo "$(date) - Starting up" create_patterns if [ ! -s ${tracking_pat} ] || [ ! -s ${counters_pat} ] ; then echo "Pattern files not found in $(pwd)" exit 1 fi while sleep "$sleeptime" ; do for j in $(jls name) ; do echo "Running for ${j}.." 1>&2 if startup "$j" ; then if stats="$(jail_collect_stats "$j")" ; then jail_parse_stats "$j" "$stats" >> "$tmpfile" else echo "$(date) - Failed to collect stats for ${j} - did jail disappear?" fi else echo "Skipping ${j}.." 1>&2 fi done if [ "$?" -eq 0 ] ; then mv "$tmpfile" "$dstfile" else rm -f "$dstfile" fi echo "Sleeping.." 1>&2 done rm -f ${counters_pat} ${tracking_pat}