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/perl/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");
Blog Logo

Peter Adkins


Published

Image

KernelPicnic

Back to Overview