read
While working on monitoring critical services at $company, I have recently had a requirement to monitor an OpenVPN instance to ensure that it is available when required. In order to do so, I have compiled a “quick and dirty” plugin for OpsView / Nagios. This script was compiled in a number of hours using Wireshark to capture the initial client -> server handshake which was then binary encoded and replayed via Perl.
Again, this is crude service check, but it may assist someone in the future.
#!/usr/bin/perl
#
# Filaname: check_openvpn
# Created: 2012-06-15
# Website: http://blog.kernelpicnic.net
#
# Description:
# This script is for verifying the status of an OpenVPN daemon. It has been
# written to integrate directly with Nagios / Opsview.
#
# Usage:
# check_openvpn [OPTIONS]...
#
# -H, --hostname Host to check
# -p, --port Port number to check
# -h, --help Display help.
#
#############################################################################
# Custom library path for Nagis modules.
use lib qw ( /usr/local/nagios/p erl / lib );
# Enforce sanity.
use strict ;
use warnings ;
# Required modules.
use Getopt:: Long qw(:config no_ignore_case) ;
use Nagios:: Plugin ;
use IO:: Socket ;
# Define defaults.
my $help = 0 ;
my $timeout = 5 ;
# Ensure required variables are set.
my ( $hostname , $port );
my $options = GetOptions (
" hostname|H=s " => $hostname ,
" timeout|t=s " => $timeout ,
" port|p=s " => $port ,
" help|h " => $help ,
);
# Check if help has been requested.
if ( $help || ! $hostname || ! $port ) {
printf (" n ");
printf (" Usage: check_openvpn [OPTIONS]...nn ");
printf (" -H, --hostname Host to checkn ");
printf (" -p, --port Port number to checkn ");
printf (" -h, --help This help pagen ");
printf (" -t, --timeout Socket timeoutn ");
printf (" n ");
exit ( - 1 );
}
# Setup a new Nagios::Plugin object.
my $nagios = Nagios:: Plugin -> new ();
# Define the check string to send to the OpenVPN server - as binary due
# to non-printable characters.
my $check_string = " 001110000011001010010010011011101000000100010001110 "
. " 100110110101010110011000000000000000000000000000000 "
. " 0000000000 ";
# Attempt to setup a socket to the specified host.
my $host_sock = IO::Socket:: INET -> new (
Proto => ' udp ',
PeerAddr => $hostname ,
PeerPort => $port ,
);
# Ensure we have a socket.
if ( ! $host_sock ) {
$nagios -> nagios_exit ( UNKNOWN , " Unable to bind socket ");
}
# Fire off the check request.
$host_sock -> send ( pack (" B* ", $check_string ));
# Wait for $timeout for response for a response, otherwise, fail.
my $response ;
eval {
# Define how to handle ALARM.
local $SIG { ALRM } = sub {
$nagios -> nagios_exit ( CRITICAL , " No response received ");
};
# Set the alarm for the given timeout value.
alarm ( $timeout );
# Check for response.
$host_sock -> recv ( $response , 1 )
or $nagios -> nagios_exit ( CRITICAL , " No response received ");
# Alright, response received, cancel alarm.
alarm ( 0 );
1 ;
};
# Reply received, return okay.
$nagios -> nagios_exit ( OK , " Response received from host ");