Querying Nagios NRPE Client via PHP

I recently had the idea to write an agent for a few windows servers to execute some custom commands so I could graph the data in Cacti.  I have dabbled in making my own Windows SNMP extension agents in the past (and I love SNMP) and while they work well; I really didn’t want anything that complicated.

Now not being someone to re-invent the wheel unless I have to, I started looking around at a few other existing agents.  A few of the requirements I had in mind were that I didn’t want the communication in plain text, it needs to be somewhat secure (password or ACL), it needs to be fairly easy to install and configure custom commands, and most importantly I need to be able to easily communicate with the agent over PHP.  After finding agent after agent that did 1 or 2 of my requirements, I settled on the Nagios NRPE Agent.  While it does have some quirks, it does satisfy the first 3 of my requirements, so all I would have to work out is the 4th.  The NRPE Agent can use SSL to communicate between the monitoring server and the agent.  While it does not have the ability to require a password, it does allow me to set an ACL on the agent to specify the IP addresses allowed to communicate to it.  Configuration is just editing a text config file to add my custom commands, which is really simple.  It also makes it pretty easy to push any new updates to my servers.

As for the 4th requirement, communicating with the agent from PHP.  I wanted to do this, so I could write some Cacti Script Server scripts, and not have to launch a new process to then query the agent.  For NRPE, you normally would have to run the check_nrpe executable with the command line arguments for the command.  This was messy and an extra step which would add some latency and slow down my polling.  I looked around, and really couldn’t find much info on the protocol NRPE uses between the client and host.  I did finally manage to find a perl script that did basically what I wanted, or at least laid out the basics of the required packet for me, so I didn’t have to resort to Wireshark to figure it out.  The only thing required was to figure out exactly what it was doing, and then implement the same thing in PHP.  The perl script was a few hundred lines of code, and had 4-5 required libraries, which was something I was going to have to do away with.

A few of the tidbits I gleamed.  I first made the mistake of attempting to use fsockopen to create the SSL connection, but for SSL to work with NRPE, it seems to require the use of the ADH cipher.  Just trying to do a straight up SSL2 or SSL3 connection is going to fail with an error about the cipher (check the agent log).  This didn’t pose much of a problem though, since PHP also has lots of nice built-in functions for dealing with SSL streams, and its really easy to change the cipher used with those functions.   This also makes it easy, since I really don’t have to deal with certificates or anything else you would normally need to do with SSL.  The next thing is that the NRPE agent expects the packet to always be the exact same size no matter the command.  We are basically going to have to pad the command with nulls to be 1024 in length, we then add all our CRC checksums and other misc headers to this.  Overall the packet itself is very simplistic, and doesn’t include anything really complicated to create.

Anyway, on to some code.  This is the simple script I wrote to test querying the agent.

Overall it took very little code to create the communication which made me extremely pleased.  It turned out to much much smaller than the perl code I was originally working with.  This will ofcourse have to be modified to conform to the Cacti Script Server usage, but that is really the easy part.  Once I get a few templates completed (for the normal NRPE commands) and I will post them for everyone to use.

February 18, 2012 · Jimmy · Comments Closed
Posted in: Cacti