Skip to content

www.rolfje.com

Add iptables to your node-exporter metrics

Posted on 2025-12-012025-10-25 By rolfje No Comments on Add iptables to your node-exporter metrics

This time quick and simple trick to make your node_exporter report on the number of blocked and allowed packets by iptables. It involves a tiny script, and a small configuration change to the node_exporter. Here we go:

On your linux machine, as root, create the file /opt/iptables_metrics.sh with the following content:

#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C

OUTDIR="/var/lib/node_exporter"
OUTFILE="${OUTDIR}/iptables.prom"
TMP="$(mktemp "${OUTFILE}.XXXXXX")"

emit() { printf '%s\n' "$*" >>"$TMP"; }

emit "# HELP iptables_packets_total Total packets by verdict across all chains (filter table)."
emit "# TYPE iptables_packets_total counter"
emit "# HELP iptables_bytes_total Total bytes by verdict across all chains (filter table)."
emit "# TYPE iptables_bytes_total counter"

parse_family() {
  local cmd="$1" fam="$2"

  if ! command -v "$cmd" >/dev/null 2>&1; then
    emit "# ${fam}: $cmd not found"
    return
  fi

  # capture output (avoid pipe subshell); ignore stderr to handle permission warnings
  local out
  if ! out="$($cmd -t filter -L -v -n -x 2>/dev/null)"; then
    emit "# ${fam}: cannot list rules (need CAP_NET_ADMIN/root?)"
    return
  fi
  [ -n "$out" ] || { emit "# ${fam}: empty ruleset"; return; }

  # do all math in awk, print final metrics
  printf '%s\n' "$out" | awk -v fam="$fam" '
    BEGIN { accp=accb=rejp=rejb=drpp=drpb=0 }
    /^Chain / {
      if (match($0, /\(policy ([A-Z]+) ([0-9]+) packets, ([0-9]+) bytes\)/, m)) {
        pol=m[1]; pk=m[2]; by=m[3];
        if (pol=="ACCEPT") { accp+=pk; accb+=by }
        else if (pol=="REJECT") { rejp+=pk; rejb+=by }
        else if (pol=="DROP")   { drpp+=pk; drpb+=by }
      }
      next
    }
    # rule lines: pkts bytes TARGET ...
    /^[[:space:]]*[0-9]+[[:space:]]+[0-9]+[[:space:]]+[!-~]+/ {
      pk=$1; by=$2; tgt=toupper($3);
      if (tgt=="ACCEPT") { accp+=pk; accb+=by }
      else if (tgt=="REJECT") { rejp+=pk; rejb+=by }
      else if (tgt=="DROP")   { drpp+=pk; drpb+=by }
      # targets like DOCKER, RETURN, f2b-sshd are chain jumps → not counted here
    }
    END {
      printf "iptables_packets_total{family=\"%s\",verdict=\"accept\"} %d\n", fam, accp
      printf "iptables_packets_total{family=\"%s\",verdict=\"reject\"} %d\n", fam, rejp
      printf "iptables_packets_total{family=\"%s\",verdict=\"drop\"} %d\n", fam, drpp
      printf "iptables_bytes_total{family=\"%s\",verdict=\"accept\"} %d\n", fam, accb
      printf "iptables_bytes_total{family=\"%s\",verdict=\"reject\"} %d\n", fam, rejb
      printf "iptables_bytes_total{family=\"%s\",verdict=\"drop\"} %d\n", fam, drpb
    }' >>"$TMP"
}

parse_family iptables  ipv4
parse_family ip6tables ipv6

chmod 644 "$TMP"
mv -f "$TMP" "$OUTFILE"

Make sure the output directory is present and writeable by root: sudo mkdir -p /var/lib/node_exporter

Now, search for your node exporter service file, this is usually called /etc/systemd/system/node_exporter.service . Edit this file and make sure node_exporter scans the /var/lib/node_exporter directory:

[Unit]
Description=Node Exporter Prometheus Metrics
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
ExecStart=/opt/node_exporter/node_exporter \
  --collector.textfile.directory=/var/lib/node_exporter

[Install]
WantedBy=default.target

Now the only thing missing is triggering the iptables_metrics.sh script. Simply make it run every minute by adding it to your crontab. Open the crontab editor with sudo crontab -e and add the following line at the end of the crontab entries:

* * * * * /opt/iptables_metrics.sh >> /var/log/iptables_metrics.log 2>&1

Please note that output is written to /var/log/iptables_metrics.log without any size limit, you might want to check that log file every once in a while. If all goes well, there should be no log entries in that file.

When everything is setup correctly, you will see the file /var/lib/node_exporter/iptables.prom appear with the following contents:

# HELP iptables_packets_total Total packets by verdict across all chains (filter table).
# TYPE iptables_packets_total counter
# HELP iptables_bytes_total Total bytes by verdict across all chains (filter table).
# TYPE iptables_bytes_total counter
iptables_packets_total{family="ipv4",verdict="accept"} 10409167
iptables_packets_total{family="ipv4",verdict="reject"} 1
iptables_packets_total{family="ipv4",verdict="drop"} 0
iptables_bytes_total{family="ipv4",verdict="accept"} 4554837838
iptables_bytes_total{family="ipv4",verdict="reject"} 60
iptables_bytes_total{family="ipv4",verdict="drop"} 0
iptables_packets_total{family="ipv6",verdict="accept"} 0
iptables_packets_total{family="ipv6",verdict="reject"} 0
iptables_packets_total{family="ipv6",verdict="drop"} 0
iptables_bytes_total{family="ipv6",verdict="accept"} 0
iptables_bytes_total{family="ipv6",verdict="reject"} 0
iptables_bytes_total{family="ipv6",verdict="drop"} 0

This data will be picked up by your node_exporter and should show up when you do a curl localhost:9100/metrics.

Please note that if you use fail2ban or docker, the counters can reset. For instance, fail2ban can take an ip address out of jail and modify the rules, thereby removing a rule and thus a counter. If you use rates in your monitoring setup (victoria metrics or prometheus), this will not be a problem, as a “rate” can handle resets.

This simple trick also lets you add other data you can gather with a script. Put it in a separate file with a logical name in the /var/lib/node_exporter folder and it will become parts of your metrics endpoint.

I hope this simple trick helps, cheers!

Software Tags:linux, metrics, programming

Post navigation

Previous Post: Finding HomeAssistant Entities in Prometheus

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

         

Recent Comments

  • rolfje on Exit WordPress
  • rolfje on Methode Buijs uitgelegd
  • LinkedIn is at Peak Enshittifaction – Will Chatham's Blog on Linked-In not really Opt-in?
  • Hans j on 1N4148 diode as RF switch
  • Roaming Rhonda on DLNA on OSX, done right

Tags

Apple backup design DIY DRM eclipse environment fix Fun gmail google hacking hamradio Hardware helicopter iphone ipod iTunes Java Keynote linux maven modelling music news opinion oracle osx photo photography programming repair review security Software T-Mobile technology Time Machine Twitter Ubuntu usability Utilities vacation windows Workshop

Categories

  • Apple (105)
  • Divorce (1)
  • Electronics (3)
  • Fun (57)
  • Games (7)
  • Hardware (72)
  • Microsoft (18)
  • Racing (14)
  • Software (136)
  • Uncategorized (68)
  • Workshop (20)

Archives

Brought to you without adds, banners, cookies or tracking. This one is on me. Yes, life can be this good. Pay it forward.

Copyright © 2025 www.rolfje.com.

Powered by PressBook WordPress theme