From 5795fc1b5536b6506c26a976c3024114e88cbcb8 Mon Sep 17 00:00:00 2001 From: Alexander Marx Date: Wed, 3 Sep 2014 07:58:15 +0200 Subject: [PATCH] vpn-statistic: added new statistic page for OpenVPN Roadwarrior --- config/cfgroot/graphs.pl | 42 ++++++++++++++++++++ config/collectd/collectd.conf | 1 + config/collectd/collectd.vpn | 5 +++ config/menu/20-status.menu | 12 ++++++ config/rootfiles/common/apache2 | 2 + config/rootfiles/common/collectd | 1 + html/cgi-bin/netovpnrw.cgi | 68 ++++++++++++++++++++++++++++++++ html/cgi-bin/netovpnsrv.cgi | 68 ++++++++++++++++++++++++++++++++ html/cgi-bin/ovpnmain.cgi | 18 ++++++++- lfs/openvpn | 1 + src/misc-progs/openvpnctrl.c | 29 ++++++++++++++ 11 files changed, 245 insertions(+), 2 deletions(-) create mode 100644 config/collectd/collectd.vpn create mode 100644 html/cgi-bin/netovpnrw.cgi create mode 100755 html/cgi-bin/netovpnsrv.cgi diff --git a/config/cfgroot/graphs.pl b/config/cfgroot/graphs.pl index 487a4dd932..9695dedb9a 100644 --- a/config/cfgroot/graphs.pl +++ b/config/cfgroot/graphs.pl @@ -586,6 +586,48 @@ sub updateifgraph { $ERROR = RRDs::error; print "Error in RRD::graph for ".$interface.": ".$ERROR."\n" if $ERROR; } +sub updatevpngraph { + my $interface = $_[0]; + my $period = $_[1]; + RRDs::graph( + "-", + "--start", + "-1".$period, + "-aPNG", + "-i", + "-z", + "-W www.ipfire.org", + "--alt-y-grid", + "-w 600", + "-h 125", + "-r", + "-t ".$Lang::tr{'traffic on'}." ".$interface." ".$Lang::tr{'graph per'}." ".$Lang::tr{$period."-graph"}, + "-v ".$Lang::tr{'bytes per second'}, + "--color=SHADEA".$color{"color19"}, + "--color=SHADEB".$color{"color19"}, + "--color=BACK".$color{"color21"}, + "DEF:incoming=".$mainsettings{'RRDLOG'}."/collectd/localhost/openvpn-$interface/if_octets.rrd:rx:AVERAGE", + "DEF:outgoing=".$mainsettings{'RRDLOG'}."/collectd/localhost/openvpn-$interface/if_octets.rrd:tx:AVERAGE", + "CDEF:outgoingn=outgoing,-1,*", + "COMMENT:".sprintf("%-20s",$Lang::tr{'caption'}), + "COMMENT:".sprintf("%15s",$Lang::tr{'maximal'}), + "COMMENT:".sprintf("%15s",$Lang::tr{'average'}), + "COMMENT:".sprintf("%15s",$Lang::tr{'minimal'}), + "COMMENT:".sprintf("%15s",$Lang::tr{'current'})."\\j", + "AREA:incoming".$color{"color12"}."A0:".sprintf("%-20s",$Lang::tr{'incoming traffic in bytes per second'}), + "GPRINT:incoming:MAX:%8.1lf %sBps", + "GPRINT:incoming:AVERAGE:%8.1lf %sBps", + "GPRINT:incoming:MIN:%8.1lf %sBps", + "GPRINT:incoming:LAST:%8.1lf %sBps\\j", + "AREA:outgoingn".$color{"color13"}."A0:".sprintf("%-20s",$Lang::tr{'outgoing traffic in bytes per second'}), + "GPRINT:outgoing:MAX:%8.1lf %sBps", + "GPRINT:outgoing:AVERAGE:%8.1lf %sBps", + "GPRINT:outgoing:MIN:%8.1lf %sBps", + "GPRINT:outgoing:LAST:%8.1lf %sBps\\j", + ); + $ERROR = RRDs::error; + print "Error in RRD::graph for ".$interface.": ".$ERROR."\n" if $ERROR; +} # Generate the Firewall Graph for the current period of time for values given by collecd diff --git a/config/collectd/collectd.conf b/config/collectd/collectd.conf index 61327bf6c0..384c943600 100644 --- a/config/collectd/collectd.conf +++ b/config/collectd/collectd.conf @@ -92,3 +92,4 @@ include "/etc/collectd.precache" #include "/etc/collectd.thermal" include "/etc/collectd.custom" +include "/etc/collectd.vpn" diff --git a/config/collectd/collectd.vpn b/config/collectd/collectd.vpn new file mode 100644 index 0000000000..b4d08e0e3b --- /dev/null +++ b/config/collectd/collectd.vpn @@ -0,0 +1,5 @@ +LoadPlugin openvpn + + +StatusFile "/var/log/ovpnserver.log" + diff --git a/config/menu/20-status.menu b/config/menu/20-status.menu index b159ed6109..802885ee3a 100644 --- a/config/menu/20-status.menu +++ b/config/menu/20-status.menu @@ -40,6 +40,18 @@ 'title' => "$Lang::tr{'network other'}", 'enabled' => 1, }; + $substatus->{'53.networkovpn'} = { + 'caption' => "$Lang::tr{'openvpn client'}", + 'uri' => '/cgi-bin/netovpnrw.cgi', + 'title' => "$Lang::tr{'openvpn client'}", + 'enabled' => 1, + }; + $substatus->{'54.networkovpnsrv'} = { + 'caption' => "$Lang::tr{'openvpn server'}", + 'uri' => '/cgi-bin/netovpnsrv.cgi', + 'title' => "$Lang::tr{'openvpn server'}", + 'enabled' => 1, + }; $substatus->{'60.hardwaregraphs'} = { 'caption' => "$Lang::tr{'hardware graphs'}", 'uri' => '/cgi-bin/hardwaregraphs.cgi', diff --git a/config/rootfiles/common/apache2 b/config/rootfiles/common/apache2 index 474e7a7dc1..3eabe9f769 100644 --- a/config/rootfiles/common/apache2 +++ b/config/rootfiles/common/apache2 @@ -1419,6 +1419,8 @@ srv/web/ipfire/cgi-bin/modem-status.cgi srv/web/ipfire/cgi-bin/netexternal.cgi srv/web/ipfire/cgi-bin/netinternal.cgi srv/web/ipfire/cgi-bin/netother.cgi +srv/web/ipfire/cgi-bin/netovpnrw.cgi +srv/web/ipfire/cgi-bin/netovpnsrv.cgi srv/web/ipfire/cgi-bin/optionsfw.cgi srv/web/ipfire/cgi-bin/ovpnmain.cgi srv/web/ipfire/cgi-bin/p2p-block.cgi diff --git a/config/rootfiles/common/collectd b/config/rootfiles/common/collectd index 2b9fa285c7..5c2064dbdc 100644 --- a/config/rootfiles/common/collectd +++ b/config/rootfiles/common/collectd @@ -2,6 +2,7 @@ etc/collectd.conf etc/collectd.custom etc/collectd.precache etc/collectd.thermal +etc/collectd.vpn etc/rc.d/init.d/collectd etc/rc.d/rc0.d/K50collectd etc/rc.d/rc3.d/S29collectd diff --git a/html/cgi-bin/netovpnrw.cgi b/html/cgi-bin/netovpnrw.cgi new file mode 100644 index 0000000000..181ae33b3e --- /dev/null +++ b/html/cgi-bin/netovpnrw.cgi @@ -0,0 +1,68 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2014 Alexander Marx # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; +require "${General::swroot}/graphs.pl"; + +my %color = (); +my %mainsettings = (); +&General::readhash("${General::swroot}/main/settings", \%mainsettings); +&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); + +my @vpns=(); + +my @querry = split(/\?/,$ENV{'QUERY_STRING'}); +$querry[0] = '' unless defined $querry[0]; +$querry[1] = 'week' unless defined $querry[1]; + +if ( $querry[0] ne "" && $querry[0] ne "UNDEF"){ + print "Content-type: image/png\n\n"; + binmode(STDOUT); + &Graphs::updatevpngraph($querry[0],$querry[1]); +}else{ + &Header::showhttpheaders(); + &Header::openpage($Lang::tr{'host to net vpn'}, 1, ''); + &Header::openbigbox('100%', 'left'); + + my @vpngraphs = `find /var/log/rrd/collectd/localhost/openvpn-*/ -not -path *openvpn-UNDEF* -name *.rrd|sort`; + foreach (@vpngraphs){ + $_ =~ /(.*)\/openvpn-(.*)\/if_octets.rrd/; + push(@vpns,$2); + } + foreach (@vpns) { + &Header::openbox('100%', 'center', "$_ $Lang::tr{'graph'}"); + &Graphs::makegraphbox("netovpnrw.cgi",$_,"week"); + &Header::closebox(); + } + + my $output = ''; + + &Header::closebigbox(); + &Header::closepage(); +} diff --git a/html/cgi-bin/netovpnsrv.cgi b/html/cgi-bin/netovpnsrv.cgi new file mode 100755 index 0000000000..9d5f29a76a --- /dev/null +++ b/html/cgi-bin/netovpnsrv.cgi @@ -0,0 +1,68 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2014 Alexnder Marx # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; +require "${General::swroot}/graphs.pl"; + +my %color = (); +my %mainsettings = (); +&General::readhash("${General::swroot}/main/settings", \%mainsettings); +&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); + +my @vpns=(); + +my @querry = split(/\?/,$ENV{'QUERY_STRING'}); +$querry[0] = '' unless defined $querry[0]; +$querry[1] = 'week' unless defined $querry[1]; + +if ( $querry[0] ne ""){ + print "Content-type: image/png\n\n"; + binmode(STDOUT); + &Graphs::updatevpnn2ngraph($querry[0],$querry[1]); +}else{ + &Header::showhttpheaders(); + &Header::openpage($Lang::tr{'openvpn server'}, 1, ''); + &Header::openbigbox('100%', 'left'); + + my @vpngraphs = `find /var/log/rrd/collectd/localhost/openvpn-*-n2n/ -not -path *openvpn-UNDEF* -name *traffic.rrd|sort`; + foreach (@vpngraphs){ + $_ =~ /(.*)\/openvpn-(.*)\/if_octets-traffic.rrd/; + push(@vpns,$2); + } + foreach (@vpns) { + &Header::openbox('100%', 'center', "$_ $Lang::tr{'graph'}"); + &Graphs::makegraphbox("netovpnsrv.cgi",$_,"week"); + &Header::closebox(); + } + + my $output = ''; + + &Header::closebigbox(); + &Header::closepage(); +} diff --git a/html/cgi-bin/ovpnmain.cgi b/html/cgi-bin/ovpnmain.cgi index 969b2557ff..13ecbd5a9c 100644 --- a/html/cgi-bin/ovpnmain.cgi +++ b/html/cgi-bin/ovpnmain.cgi @@ -863,9 +863,12 @@ unless(-d "${General::swroot}/ovpn/n2nconf/$cgiparams{'NAME'}"){mkdir "${General print SERVERCONF "route $remsubnet[0] $remsubnet[1]\n"; print SERVERCONF "# tun Device\n"; print SERVERCONF "dev tun\n"; + print SERVERCONF "#Logfile for statistics\n"; + print SERVERCONF "status-version 1\n"; + print SERVERCONF "status /var/log/openvpn/$cgiparams{'NAME'}-n2n 10\n"; print SERVERCONF "# Port and Protokol\n"; print SERVERCONF "port $cgiparams{'DEST_PORT'}\n"; - + if ($cgiparams{'PROTOCOL'} eq 'tcp') { print SERVERCONF "proto tcp-server\n"; print SERVERCONF "# Packet size\n"; @@ -1151,6 +1154,14 @@ SETTINGS_ERROR: while ($file = glob("${General::swroot}/ovpn/ccd/*")) { unlink $file } +# Delete all RRD files for Roadwarrior connections + chdir('/var/ipfire/ovpn/ccd'); + while ($file = glob("*")) { + system ("/usr/local/bin/openvpnctrl -drrd $file"); + } + while ($file = glob("${General::swroot}/ovpn/ccd/*")) { + unlink $file + } if (open(FILE, ">${General::swroot}/ovpn/ovpn-leases.db")) { print FILE ""; close FILE; @@ -2304,7 +2315,10 @@ if ($confighash{$cgiparams{'KEY'}}[3] eq 'net') { # CCD end - +### +### Delete all RRD's for client +### + system ("/usr/local/bin/openvpnctrl -drrd $confighash{$cgiparams{'KEY'}}[1]"); delete $confighash{$cgiparams{'KEY'}}; my $temp2 = `/usr/bin/openssl ca -gencrl -out ${General::swroot}/ovpn/crls/cacrl.pem -config ${General::swroot}/ovpn/openssl/ovpn.cnf`; &General::writehasharray("${General::swroot}/ovpn/ovpnconfig", \%confighash); diff --git a/lfs/openvpn b/lfs/openvpn index 8c7c81a491..68c69a2e9c 100644 --- a/lfs/openvpn +++ b/lfs/openvpn @@ -83,6 +83,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) cd $(DIR_APP) && make install cd $(DIR_APP) && cp -Rvf $(DIR_SRC)/config/ovpn /var/ipfire -mkdir -vp /usr/lib/openvpn/plugins + -mkdir -vp /var/log/openvpn -mkdir -vp /var/ipfire/ovpn/ca -mkdir -vp /var/ipfire/ovpn/ccd -mkdir -vp /var/ipfire/ovpn/crls diff --git a/src/misc-progs/openvpnctrl.c b/src/misc-progs/openvpnctrl.c index 462ce77cce..da5ee2356e 100644 --- a/src/misc-progs/openvpnctrl.c +++ b/src/misc-progs/openvpnctrl.c @@ -73,6 +73,9 @@ void usage(void) printf(" -kn2n --kill-net-2-net\n"); printf(" kills all net2net connections\n"); printf(" you may pass a connection name to the switch to only start a specific one\n"); + printf(" -drrd --delete-rrd\n"); + printf(" Deletes the RRD data for a specific client\n"); + printf(" you need to pass a connection name (RW) to the switch to delete the directory (case sensitive)\n"); printf(" -d --display\n"); printf(" displays OpenVPN status to syslog\n"); printf(" -fwr --firewall-rules\n"); @@ -565,6 +568,28 @@ int killNet2Net(char *name) { return 0; } +int deleterrd(char *name) { + connection *conn = getConnections(); + + char rrd_file[STRING_SIZE]; + snprintf(rrd_file, STRING_SIZE - 1, "/var/log/rrd/collectd/localhost/openvpn-%s/if_octets.rrd", name); + + char rrd_dir[STRING_SIZE]; + snprintf(rrd_dir, STRING_SIZE - 1, "/var/log/rrd/collectd/localhost/openvpn-%s", name); + + while(conn) { + /* Find only RW-Connections with the given name. */ + if (((strcmp(conn->type, "host") == 0) && (strcmp(conn->name, name) == 0))) { + remove(rrd_file); + remove(rrd_dir); + return 0; + } + conn = conn->next; + } + + return 1; +} + void startAllNet2Net() { int exitcode = 0, _exitcode = 0; @@ -634,6 +659,10 @@ int main(int argc, char *argv[]) { else if( (strcmp(argv[1], "-kn2n") == 0) || (strcmp(argv[1], "--kill-net-2-net") == 0) ) { killNet2Net(argv[2]); return 0; + } + else if( (strcmp(argv[1], "-drrd") == 0) || (strcmp(argv[1], "--delete-rrd") == 0) ) { + deleterrd(argv[2]); + return 0; } else { usage(); return 1; -- 2.39.2