1#!/usr/local/bin/perl -w 2 3=head1 NAME 4 5openvpn_multi - Plugin for monitoring OpenVPN users traffic 6 7=head1 CONFIGURATION 8 9 [openvpn_multi] 10 user root 11 env.statusfile /var/log/openvpn.status 12 13=head1 AUTHOR 14 15Copyright 2013 Pierre Schweitzer <pierre@reactos.org> 16 17=head1 LICENSE 18 19GNU GPL v2 or any later version 20 21=head1 MAGIC MARKERS 22 23 #%# family=auto 24 #%# capabilities=autoconf 25 26=cut 27 28use strict; 29use Munin::Common::Defaults; 30use Munin::Plugin; 31 32my $statusfile = ($ENV{'statusfile'} || '/var/log/openvpn.status'); 33 34sub config { 35 open FILE, $statusfile or die $!; 36 37 print "multigraph openvpn_users\n"; 38 print "graph_title OpenVPN traffic\n"; 39 print "graph_args --base 1024 --lower-limit 0\n"; 40 print "graph_vlabel Bytes Out (-) / In (+) per \${graph_period}\n"; 41 print "graph_category network\n"; 42 print "in.label recv\n"; 43 print "in.type DERIVE\n"; 44 print "in.min 0\n"; 45 print "in.graph no\n"; 46 print "in.cdef in,1,*\n"; 47 print "out.label Bps\n"; 48 print "out.type DERIVE\n"; 49 print "out.min 0\n"; 50 print "out.negative in\n"; 51 print "out.cdef out,1,*\n"; 52 53 while (<FILE>) { 54 next if ($_ =~ /CLIENT LIST/ || $_ =~ /Updated/ || $_ =~ /Common Name/ || $_ =~ /^UNDEF,/); 55 last if ($_ =~ /ROUTING TABLE/); 56 57 # client,IP:port,in,out,D M N hour Y 58 my @values = split(',', $_); 59 my $name = $values[0]; 60 my $fieldname = clean_fieldname($name); 61 62 print "multigraph openvpn_users.$fieldname\n"; 63 print "graph_title OpenVPN traffic for $name\n"; 64 print "graph_args --base 1024 --lower-limit 0\n"; 65 print "graph_vlabel Bytes Out (-) / In (+) per \${graph_period}\n"; 66 print "graph_category network\n"; 67 print "in.label recv\n"; 68 print "in.type DERIVE\n"; 69 print "in.min 0\n"; 70 print "in.graph no\n"; 71 print "in.cdef in,1,*\n"; 72 print "out.label Bps\n"; 73 print "out.type DERIVE\n"; 74 print "out.min 0\n"; 75 print "out.negative in\n"; 76 print "out.cdef out,1,*\n"; 77 } 78 close FILE; 79 80 exit 0; 81} 82 83sub autoconf { 84 if (-e $statusfile) { 85 print "yes\n"; 86 } else { 87 print "no\n"; 88 } 89 exit 0; 90} 91 92sub report { 93 my %in; 94 my %out; 95 my $tot_in = 0; 96 my $tot_out = 0; 97 98 my %previous_state = restore_state(); 99 my %new_state; 100 101 open FILE, $statusfile or die $!; 102 while (<FILE>) { 103 next if ($_ =~ /CLIENT LIST/ || $_ =~ /Updated/ || $_ =~ /Common Name/ || $_ =~ /^UNDEF,/); 104 last if ($_ =~ /ROUTING TABLE/); 105 106 # client,IP:port,in,out,D M N hour Y 107 my @values = split(',', $_); 108 my $name = $values[0]; 109 110 my $in = 0; 111 my $out = 0; 112 if (exists $previous_state{$name."_in"} && exists $previous_state{$name."_out"}) { 113 my $old_in = $previous_state{$name."_in"}; 114 my $old_out = $previous_state{$name."_out"}; 115 if ($old_in <= $values[2] && $old_out <= $values[3]) { 116 $in = $values[2] - $old_in; 117 $out = $values[3] - $old_out; 118 } 119 } 120 121 $in{$name} = $in; 122 $out{$name} = $out; 123 $tot_in += $in; 124 $tot_out += $out; 125 126 $new_state{$name."_in"} = $values[2]; 127 $new_state{$name."_out"} = $values[3]; 128 } 129 close FILE; 130 131 print "multigraph openvpn_users\n"; 132 if (exists $previous_state{"total.in"} && exists $previous_state{"total.out"}) { 133 my $old_tot_in = $previous_state{"total.in"}; 134 my $old_tot_out = $previous_state{"total.out"}; 135 if ($old_tot_in <= $tot_in && $old_tot_out <= $tot_out) { 136 print "in.value $tot_in\n"; 137 print "out.value $tot_out\n"; 138 } else { 139 print "in.value 0\n"; 140 print "out.value 0\n"; 141 } 142 } else { 143 print "in.value 0\n"; 144 print "out.value 0\n"; 145 } 146 147 $new_state{"total.in"} = $tot_in; 148 $new_state{"total.out"} = $tot_out; 149 150 save_state(%new_state); 151 152 for my $name (keys %in) { 153 my $in = $in{$name}; 154 my $out = $out{$name}; 155 my $fieldname = clean_fieldname($name); 156 157 print "multigraph openvpn_users.$fieldname\n"; 158 print "in.value $in\n"; 159 print "out.value $out\n"; 160 } 161 162 exit 0; 163} 164 165if ($ARGV[0]) { 166 my $arg = $ARGV[0]; 167 my %funcs = ( 168 config => \&config, 169 autoconf => \&autoconf, 170 ); 171 172 if (exists $funcs{$arg}) { 173 $funcs{$arg}->(); 174 } else { 175 die "Unknown argument '$arg'\n"; 176 } 177} else { 178 report(); 179} 180