#!/usr/bin/perl -w =head1 NAME openvpn_multi - Plugin for monitoring OpenVPN users traffic =head1 CONFIGURATION [openvpn_multi] user root env.statusfile /var/log/openvpn.status =head1 AUTHOR Copyright 2013 Pierre Schweitzer =head1 LICENSE GNU GPL v2 or any later version =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf =cut use strict; use Munin::Common::Defaults; use Munin::Plugin; my $statusfile = ($ENV{'statusfile'} || '/var/log/openvpn.status'); sub config { open FILE, $statusfile or die $!; print "multigraph openvpn_users\n"; print "graph_title OpenVPN traffic\n"; print "graph_args --base 1024 --lower-limit 0\n"; print "graph_vlabel Bytes Out (-) / In (+) per \${graph_period}\n"; print "graph_category network\n"; print "in.label recv\n"; print "in.type DERIVE\n"; print "in.min 0\n"; print "in.graph no\n"; print "in.cdef in,1,*\n"; print "out.label Bps\n"; print "out.type DERIVE\n"; print "out.min 0\n"; print "out.negative in\n"; print "out.cdef out,1,*\n"; while () { next if ($_ =~ /CLIENT LIST/ || $_ =~ /Updated/ || $_ =~ /Common Name/ || $_ =~ /^UNDEF,/); last if ($_ =~ /ROUTING TABLE/); # client,IP:port,in,out,D M N hour Y my @values = split(',', $_); my $name = $values[0]; my $fieldname = clean_fieldname($name); print "multigraph openvpn_users.$fieldname\n"; print "graph_title OpenVPN traffic for $name\n"; print "graph_args --base 1024 --lower-limit 0\n"; print "graph_vlabel Bytes Out (-) / In (+) per \${graph_period}\n"; print "graph_category network\n"; print "in.label recv\n"; print "in.type DERIVE\n"; print "in.min 0\n"; print "in.graph no\n"; print "in.cdef in,1,*\n"; print "out.label Bps\n"; print "out.type DERIVE\n"; print "out.min 0\n"; print "out.negative in\n"; print "out.cdef out,1,*\n"; } close FILE; exit 0; } sub autoconf { if (-e $statusfile) { print "yes\n"; } else { print "no\n"; } exit 0; } sub report { my %in; my %out; my $tot_in = 0; my $tot_out = 0; my %previous_state = restore_state(); my %new_state; open FILE, $statusfile or die $!; while () { next if ($_ =~ /CLIENT LIST/ || $_ =~ /Updated/ || $_ =~ /Common Name/ || $_ =~ /^UNDEF,/); last if ($_ =~ /ROUTING TABLE/); # client,IP:port,in,out,D M N hour Y my @values = split(',', $_); my $name = $values[0]; my $in = 0; my $out = 0; if (exists $previous_state{$name."_in"} && exists $previous_state{$name."_out"}) { my $old_in = $previous_state{$name."_in"}; my $old_out = $previous_state{$name."_out"}; if ($old_in <= $values[2] && $old_out <= $values[3]) { $in = $values[2] - $old_in; $out = $values[3] - $old_out; } } $in{$name} = $in; $out{$name} = $out; $tot_in += $in; $tot_out += $out; $new_state{$name."_in"} = $values[2]; $new_state{$name."_out"} = $values[3]; } close FILE; print "multigraph openvpn_users\n"; if (exists $previous_state{"total.in"} && exists $previous_state{"total.out"}) { my $old_tot_in = $previous_state{"total.in"}; my $old_tot_out = $previous_state{"total.out"}; if ($old_tot_in <= $tot_in && $old_tot_out <= $tot_out) { print "in.value $tot_in\n"; print "out.value $tot_out\n"; } else { print "in.value 0\n"; print "out.value 0\n"; } } else { print "in.value 0\n"; print "out.value 0\n"; } $new_state{"total.in"} = $tot_in; $new_state{"total.out"} = $tot_out; save_state(%new_state); for my $name (keys %in) { my $in = $in{$name}; my $out = $out{$name}; my $fieldname = clean_fieldname($name); print "multigraph openvpn_users.$fieldname\n"; print "in.value $in\n"; print "out.value $out\n"; } exit 0; } if ($ARGV[0]) { my $arg = $ARGV[0]; my %funcs = ( config => \&config, autoconf => \&autoconf, ); if (exists $funcs{$arg}) { $funcs{$arg}->(); } else { die "Unknown argument '$arg'\n"; } } else { report(); }