#!/usr/bin/env python """ A Nagios plugin for checking whether or not an OpenVPN server is alive. We don't actually interact with the OpenVPN server; we merely send it a a magic (heretofore unexplained) byte sequence and ensure that we get some kind of response. """ from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser from datetime import datetime import socket # Define a few exit codes. EXIT_OK = 0 EXIT_CRITICAL = 2 parser = ArgumentParser(description = __doc__, formatter_class = ArgumentDefaultsHelpFormatter) # Required positional argument. parser.add_argument('host', metavar='HOST', help='host to check') parser.add_argument('-p', '--port', type=int, default=1194, help='port number to check') parser.add_argument('-t', '--tcp', action='store_true', default=False, help='use TCP instead of the default UDP') parser.add_argument('-w', '--timeout', type=int, default=15, help='set the timeout (in seconds)') parser.add_argument('-v', '--verbose', action='store_true', help='produce more verbose output') args = parser.parse_args() proto = (socket.SOCK_DGRAM, 'udp') if args.tcp: proto = (socket.SOCK_STREAM, 'tcp') if args.verbose: print("Checking %s:%d (%s)" % (args.host, args.port, proto[1])) sock = socket.socket(socket.AF_INET, proto[0]) # Default to success, change it if anything fails. status = EXIT_OK try: sock.settimeout(args.timeout) time_start = datetime.now() sock.connect((args.host, args.port)) # This is a magic byte sequence, most likely obtained from a packet # capture. Connections without a TLS auth key will actually return a # response when we send this; however, secured connections will not # (although nothing will fail). # # See, # # http://serverfault.com/questions/262474 # magic = b"\x38\x01\x00\x00\x00\x00\x00\x00\x00" sock.send(magic) # If the server uses a TLS auth key, the response will be empty # but at least it will come, preventing a timeout. reply = sock.recv(100) time_end = datetime.now() if args.verbose: # This will be gibberish, but at least you can see that the # server spit something out. hex_reply = ''.join(['%02x' % ord(byte) for byte in reply]) print('Received(hex): %s' % hex_reply) time_elapsed = time_end - time_start print('OK %.3fms' % (time_elapsed.total_seconds() * 1000)) except socket.timeout as e: print('ERROR: connection timed out (%d seconds)' % args.timeout) status = EXIT_CRITICAL except socket.gaierror as e: print('ERROR: ', str(e.args[1])) status = EXIT_CRITICAL except Exception as e: print('ERROR: ', str(e)) status = EXIT_CRITICAL sock.close() exit(status)