Skip to content

Instantly share code, notes, and snippets.

@krobertson
Created August 31, 2011 01:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krobertson/1182622 to your computer and use it in GitHub Desktop.
Save krobertson/1182622 to your computer and use it in GitHub Desktop.
First past at the Nagios NRPE packet in ruby

Fire up the ruby server with:

ruby server.rb 49644

Then call check_nrpe with:

check_nrpe -H localhost -p 49644 -c check_awesome

Or with parameters, like:

check_nrpe -H localhost -p 49644 -c check_awesome -a param1 param2

require 'zlib'
module Nagios
class NrpePacket
NRPE_PACKET_VERSION_3 = 3
NRPE_PACKET_VERSION_2 = 2
NRPE_PACKET_VERSION_1 = 1
QUERY_PACKET = 1
RESPONSE_PACKET = 2
MAX_PACKETBUFFER_LENGTH = 1024
MAX_PACKET_SIZE = 12 + 1024
attr_accessor :packet_version, :crc32, :result_code, :buffer
def initialize(unpacked=nil)
@packet_version = NRPE_PACKET_VERSION_2
@random = 1
if unpacked
@packet_version = unpacked[0]
@packet_type = unpacked[1]
@crc32 = unpacked[2]
@result_code = unpacked[3]
@buffer = unpacked[4]
@random = unpacked[5]
end
end
def packet_type
case @packet_type
when QUERY_PACKET then :query
when RESPONSE_PACKET then :response
end
end
def packet_type=(type)
case type
when :query then @packet_type = QUERY_PACKET
when :response then @packet_type = RESPONSE_PACKET
else
raise "Invalid packet type"
end
end
def calculate_crc32
Zlib::crc32(self.to_bytes(0))
end
def validate_crc32
raise 'Invalid CRC32' unless @crc32 == self.calculate_crc32
end
def to_bytes(use_crc32=self.calculate_crc32)
[ @packet_version, @packet_type, use_crc32, @result_code, @buffer, @random].pack("nnNna#{MAX_PACKETBUFFER_LENGTH}n")
end
def self.read(io)
bytes = io.read(MAX_PACKET_SIZE)
values = bytes.unpack("nnNnA#{MAX_PACKETBUFFER_LENGTH}n")
packet = self.new(values)
packet.validate_crc32
packet
end
end
end
require 'socket'
require 'openssl'
require 'packet'
class ClientQuitError < RuntimeError; end
port = ARGV.shift || 0 # default is to use the next available port
server = TCPServer.new(port)
context = OpenSSL::SSL::SSLContext.new "SSLv23_server"
context.ciphers = 'ADH'
ssl_server = OpenSSL::SSL::SSLServer.new server, context
port = server.addr[1]
addrs = server.addr[2..-1].uniq
puts "*** listening on #{addrs.collect{|a|"#{a}:#{port}"}.join(' ')}"
loop do
socket = ssl_server.accept
Thread.start do # one thread per client
s = socket
port = s.peeraddr[1]
name = s.peeraddr[2]
addr = s.peeraddr[3]
puts "\n*** recieving from #{name}:#{port}"
begin
packet = Nagios::NrpePacket.read s
puts "#{addr} [#{Time.now}]: #{packet.buffer}"
response_packet = Nagios::NrpePacket.new
response_packet.packet_type = :response
response_packet.result_code = 0
response_packet.buffer = "OK - looks good"
s.write response_packet.to_bytes
rescue ClientQuitError
puts "*** #{name}:#{port} disconnected"
rescue Exception => e
puts "ERROR (#{e.class}): #{e.message}\n#{e.backtrace.join("\n")}"
ensure
s.close # close socket on error
end
puts "*** done with #{name}:#{port}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment