Add newer version of fw_conntrack munin plugin
authorTom Hughes <tom@compton.nu>
Tue, 24 Sep 2013 23:21:19 +0000 (00:21 +0100)
committerTom Hughes <tom@compton.nu>
Tue, 24 Sep 2013 23:22:29 +0000 (00:22 +0100)
The version shipped with Ubuntu 12.04 doesn't work with newer
kernels where the conntrack tool must be used to access the
connection tracking data.

cookbooks/munin/files/default/plugins/fw_conntrack
cookbooks/munin/recipes/default.rb

index 1a1b59f0c5ec4d8ad0fe67bbb0f29538006989b3..c575dd8cc3242787229b88add145c8838416c97b 100755 (executable)
@@ -1,7 +1,4 @@
-#!/bin/sh
-# -*- sh -*-
-
-: << =cut
+#!/usr/bin/perl -w
 
 =head1 NAME
 
@@ -16,12 +13,12 @@ This plugin must run with root privileges
 
 /etc/munin/plugin-conf.d/global or other file in that dir must contain:
 
- [fw*]
+ [fw_*]
   user root
 
 =head1 NOTES
 
-ESTABLISHED+FIN_WAIT+TIME_WAIT+SYN_SENT+UDP is the most interesting
+ESTABLISHED+FIN_WAIT+TIME_WAIT+SYN_SENT+UDP are the most interesting
 connections.
 
 The total list also includes SYN_RECV, CLOSE, CLOSE_WAIT, LAST_ACK and
@@ -35,30 +32,18 @@ ESTABLISHED.
 ASSURED is after ACK is seen after SYN_RECV.  Therefore ASSURED is
 plotted but not UNREPLIED.
 
-NATed will almost always be the same as the total
-
-=head1 BUGS
-
-=over 4
-
-=item full connection table
-
-The connections tables can run full, but where is the limits found?
-If we can find them then we can send warnings to nagios.
-
-=back
+Note that the plugin depends on the netfilter "conntrack" userspace tool.
+It comes from http://conntrack-tools.netfilter.org/
 
 =head1 AUTHORS
 
-2004.05.05: Initial version by Nicolai Langfeldt, Linpro AS, Oslo, Norway
-
-=head2 CONTRIBUTORS
+=over
 
-=over 4
+=item 2004.05.05: Initial version by Nicolai Langfeldt, Linpro AS, Oslo, Norway
 
-=item Xavier
+=item 2004.05.06: Enhanced to count NATed connections after input from Xavier on munin-users list
 
-2004.05.06: Enhanced to count NATed connections after input from Xavier on munin-users list
+=item 2011.09.23: Perl version by Alex Tomlins
 
 =back
 
@@ -73,10 +58,30 @@ GPL
 
 =cut
 
-case $1 in
-    config)
-
-        cat <<EOF
+use strict;
+use Munin::Plugin;
+
+my $conntrack = '/usr/sbin/conntrack';
+my $nf_conntrack_file = '/proc/net/nf_conntrack';
+my $ip_conntrack_file = '/proc/net/ip_conntrack';
+my @conntrack_max_files = qw(
+        /proc/sys/net/nf_conntrack_max
+        /proc/sys/net/netfilter/nf_conntrack_max
+        /proc/sys/net/ipv4/ip_conntrack_max
+        /proc/sys/net/ipv4/netfilter/ip_conntrack_max
+);
+
+if ( defined($ARGV[0]) and $ARGV[0] eq "autoconf" ) {
+    if ( -x $conntrack or -r $nf_conntrack_file or -r $ip_conntrack_file) {
+        print "yes\n";
+    } else {
+        print "no\n";
+    }
+    exit 0;
+}
+
+if ( defined($ARGV[0]) and $ARGV[0] eq "config" ) {
+    print <<EOF;
 graph_title Connections through firewall
 graph_vlabel Connections
 graph_category network
@@ -106,86 +111,58 @@ total.label Total
 total.type GAUGE
 total.graph no
 EOF
-        if [ -f /proc/sys/net/ipv4/ip_conntrack_max ] ; then
-            MAX=`cat /proc/sys/net/ipv4/ip_conntrack_max`
-        elif [ -f /proc/sys/net/ipv4/netfilter/ip_conntrack_max ]; then
-            MAX=`cat /proc/sys/net/ipv4/netfilter/ip_conntrack_max`
-        fi
-        if [ -n "$MAX" ]; then
-           echo total.warning `expr $MAX \* 8 / 10`
-           echo total.critical `expr $MAX \* 9 / 10`
-       fi
-        exit 0
-       ;;
-    autoconf)
-        if [ -r /proc/net/ip_conntrack -o -r /proc/net/nf_conntrack ] ; then
-           echo yes
-           exit 0
-       else
-           echo no
-           exit 0
-       fi
-esac
-
-# Do the work, perform the deed
-
-# INPUT /proc/net/ip_conntrack:
-# tcp      6 225790 ESTABLISHED src=10.0.0.4 dst=198.144.194.12 sport=48580 dport=6667 src=198.144.194.12 dst=80.111.68.163 sport=6667 dport=48580 [ASSURED] use=1
-# tcp      6 431918 ESTABLISHED src=10.0.0.2 dst=209.58.150.153 sport=33018 dport=6667 src=209.58.150.153 dst=80.111.68.163 sport=6667 dport=33018 [ASSURED] use=1
-# tcp      6 123109 ESTABLISHED src=10.0.0.5 dst=198.144.194.12 sport=33846 dport=6667 [UNREPLIED] src=198.144.194.12 dst=80.111.68.163 sport=6667 dport=33846 use=1
-# udp      17 53 src=80.111.68.163 dst=62.179.100.29 sport=34153 dport=53 src=62.179.100.29 dst=80.111.68.163 sport=53 dport=34153 [ASSURED] use=1
-#
-# INPUT /proc/net/nf_conntrack:
-# ipv4     2 tcp      6 424416 ESTABLISHED src=192.168.1.53 dst=196.203.198.11 sport=1584 dport=22146 packets=13659 bytes=5426603 src=196.203.198.11 dst=83.24.222.252 sport=22146 dport=1584 packets=14757 bytes=15342572 [ASSURED] mark=0 use=1
-
-if [ -f /proc/net/ip_conntrack ]; then
-  cat /proc/net/ip_conntrack | awk '
-  BEGIN  { STATE["ESTABLISHED"]=STATE["FIN_WAIT"]=STATE["TIME_WAIT"]=0;
-          TOTAL=ASSURED=NOREPLY=NATED=STATE["SYN_SENT"]=STATE["UDP"]=0; }
-  /^tcp/ { STATE[$4]++; }
-  /^udp/ { STATE["UDP"]++; }
-  /ASSURED/ { ASSURED++; }
-  {
-      TOTAL++;
-      src1 = substr($5, 5); src2 = substr($9, 5);
-      dst1 = substr($6, 5); dst2 = substr($10, 5);
-      if (src1 != dst2 || dst1 != src2) NATED++;
-  }
-  END    { print "established.value " STATE["ESTABLISHED"];
-           print "fin_wait.value " STATE["FIN_WAIT"];
-          print "time_wait.value " STATE["TIME_WAIT"];
-          print "syn_sent.value " STATE["SYN_SENT"];
-          print "udp.value " STATE["UDP"];
-          print "assured.value " ASSURED;
-          print "nated.value " NATED;
-          print "total.value " TOTAL;
-        }'
-else
-  cat /proc/net/nf_conntrack | awk '
-  BEGIN  { STATE["ESTABLISHED"]=STATE["FIN_WAIT"]=STATE["TIME_WAIT"]=0;
-          TOTAL=ASSURED=NOREPLY=NATED=STATE["SYN_SENT"]=STATE["UDP"]=0; }
-  / tcp / { STATE[$6]++; }
-  / udp / { STATE["UDP"]++; }
-  /ASSURED/ { ASSURED++; }
-  {
-      TOTAL++;
-      src1 = substr($7, 5); src2 = substr($14, 5);
-      dst1 = substr($8, 5); dst2 = substr($15, 5);
-      if (src1 != dst2 || dst1 != src2) NATED++;
-  }
-  END    { print "established.value " STATE["ESTABLISHED"];
-           print "fin_wait.value " STATE["FIN_WAIT"];
-          print "time_wait.value " STATE["TIME_WAIT"];
-          print "syn_sent.value " STATE["SYN_SENT"];
-          print "udp.value " STATE["UDP"];
-          print "assured.value " ASSURED;
-          print "nated.value " NATED;
-          print "total.value " TOTAL;
-        }'
-fi
-
-# Hum, the total.value should be possible to do as a cdef.
-# Or to use the builtin "total" support.
-
-#  LocalWords:  expr
-
+    my $max;
+    foreach (@conntrack_max_files) {
+        if ( -r $_) {
+            chomp($max = `cat $_`);
+            last;
+        }
+    }
+    if ($max) {
+        print "total.warning ", $max * 8 / 10, "\n";
+        print "total.critical ", $max * 9 / 10, "\n";
+    }
+    exit 0;
+}
+
+my $command;
+if ( -x $conntrack) {
+    $command = "$conntrack -L -o extended -f ipv4 2>/dev/null; $conntrack -L -o extended -f ipv6 2>/dev/null";
+} elsif ( -r $nf_conntrack_file ) {
+    $command = "cat $nf_conntrack_file";
+} else {
+    $command = "cat $ip_conntrack_file";
+}
+
+my %state = (
+    'ESTABLISHED' => 0,
+    'FIN_WAIT' => 0,
+    'TIME_WAIT' => 0,
+    'SYN_SENT' => 0,
+    'UDP' => 0,
+    'ASSURED' => 0,
+    'NATTED' => 0,
+    'TOTAL' => 0
+);
+open CMD, "$command|";
+while (<CMD>) {
+    $state{'TOTAL'} ++;
+    $state{'UDP'} ++ if /udp /;
+    $state{'ASSURED'} ++ if /ASSURED/;
+    if (/tcp \s*\d+\s+\d+\s+(\S+)/) {
+         $state{$1} ++;
+    }
+    if (/src=(\S+)\s+dst=(\S+)\s+sport.*src=(\S+)\s+dst=(\S+)/) {
+        $state{'NATTED'} ++ if $1 ne $4 or $2 ne $3;
+    }
+}
+close CMD;
+
+print "established.value $state{'ESTABLISHED'}\n";
+print "fin_wait.value $state{'FIN_WAIT'}\n";
+print "time_wait.value $state{'TIME_WAIT'}\n";
+print "syn_sent.value $state{'SYN_SENT'}\n";
+print "udp.value $state{'UDP'}\n";
+print "assured.value $state{'ASSURED'}\n";
+print "nated.value $state{'NATTED'}\n";
+print "total.value $state{'TOTAL'}\n";
index eac718fc004b2c23ab1e50be8246a53f334f449c..41d722e0cdc64113ce703c9117f8423df1be0350 100644 (file)
@@ -102,6 +102,8 @@ munin_plugin "entropy"
 munin_plugin "forks"
 
 if node[:kernel][:modules].include?("nf_conntrack")
+  package "conntrack"
+
   munin_plugin "fw_conntrack"
   munin_plugin "fw_forwarded_local"
 else