DHCPd/pools+snmp and mail alert
2010/09/28 | 14:56This guide will show you a way of using DHCPd-pools and DHCPd-snmp for mailalerts if your leases are getting thin. A nicer way would be to do it in Cacti, but I’ve noticed that DHCPd-snmp lies in Cacti. I don’t know why yet, but dhcpd-pools seems to work.
EDIT: DHCPd-snmp lies when there is more than 1 range in a pool, then it will split the pools into two graphs with same name instead of combining them. DHCPd-pools on the other hand understands this and combines them into a bigger pool 🙂
Thanks to Kerolasa I updated this guide with new code working with v2.13 of dhcpd-pools. I still had to remove dynamic-bootp though
First of you need to download and install DHCPd-pools:
[bash]
sudo -s
apt-get install build-essential php5-cli libapache2-mod-php5
wget http://downloads.sourceforge.net/project/dhcpd-pools/dhcpd-pools-2.13.tgz&ts=1285676384&use_mirror=sunet
mkdir dhcp-snmp
cd dhcp-snmp
wget http://forums.cacti.net/download/file.php?id=7162&sid=215afb35532615dfd7e1493787e8face
unzip file.php\?id\=7162
#let this be for now
cd ..
tar xvf dhcpd-pools-2.13.tgz
cd dhcpd-pools-2.13
./configure
make
make install
sudo mkdir /home/checkDHCP
sudo touch /home/checkDHCP/changePercent.php
sudo touch /home/checkDHCP/checkDHCP.sh
sudo touch /home/checkDHCP/ignoredIPs
sudo touch /home/checkDHCP/ignoredIPs.php
sudo touch /home/checkDHCP/index.php
sudo echo "50" > /home/checkDHCP/percent.txt
sudo touch /home/checkDHCP/removeIPfromIgnored.php
sudo touch /home/checkDHCP/runScript.php
sudo touch /home/checkDHCP/sampleoutput.txt
sudo touch /home/checkDHCP/searchlog.txt
sudo touch /home/checkDHCP/sendFile
sudo chown -R www-data:www-data /home/checkDHCP
[/bash]
Now we can begin to code.
These files just contain values, let them be empty.
sendFile.txt
ignoredIPs.txt
checkDHCP.sh
[bash]
#!/bin/bash
#Skapat av Viktor Åström 2010-09-16
#Vars ligger alla filer
installDir="/home/checkDHCP"
percent=`cat $installDir/percent.txt`;
cp /etc/dhcp3/dhcpd.conf $installDir/dhcpd.conf
$installDir/dhcp2snmpconf.pl $installDir/dhcpd.conf > $installDir/dhcpd-snmp.conf
grep -Ev ‘#|leases:’ $installDir/dhcpd-snmp.conf > $installDir/test
sed ‘/^$/d’ $installDir/test > $installDir/test2
sort -n -k2 $installDir/test2 > $installDir/dhcpd-snmp2.conf
#Sedding dynamic-bootp is sadly still necessary, without it the output is all jibberish
sed s/dynamic-bootp-//g $installDir/dhcpd-snmp2.conf > $installDir/test
mv $installDir/test $installDir/dhcpd-snmp2.conf
rm $installDir/test
rm $installDir/test2
sed s/dynamic-bootp// $installDir/dhcpd.conf > $installDir/test
mv $installDir/test $installDir/dhcpd.conf
#sed s/range-// $installDir/dhcpd.conf > $installDir/test
#mv $installDir/test $installDir/dhcpd.conf
#Run dhcpd-pools to create sampleoutput files, the second file is for overview
/usr/local/bin/dhcpd-pools -c $installDir/dhcpd.conf -l /var/lib/dhcp3/dhcpd.leases -o $installDir/sampleoutput.txt
/usr/local/bin/dhcpd-pools -c $installDir/dhcpd.conf -l /var/lib/dhcp3/dhcpd.leases -o $installDir/sampleoutput2.txt -s p -r -f H
#Whom to send the email to
namn="your@email.com yournext@email.com"
#Find all instances where percent is above your chosen value
awk ‘ $8 > ‘"$percent"’ ‘ $installDir/sampleoutput.txt > $installDir/sendFile.txt
#Remove the first line
sed ‘1d’ < $installDir/sendFile.txt > $installDir/tmpfile ; mv $installDir/tmpfile $installDir/sendFile.txt
#Remove the two last lines
sed ‘$d’ < $installDir/sendFile.txt > $installDir/tmpfile ; mv $installDir/tmpfile $installDir/sendFile.txt
sed ‘$d’ < $installDir/sendFile.txt > $installDir/tmpfile ; mv $installDir/tmpfile $installDir/sendFile.txt
for ignoredIP in $(cat $installDir/ignoredIPs.txt); do
sed "/$ignoredIP/d" $installDir/sendFile.txt > $installDir/test
mv $installDir/test $installDir/sendFile.txt
done
cat $installDir/sendFile.txt | awk ‘{print $3}’ > $installDir/test2
cat $installDir/sendFile.txt | awk ‘{print "Searching for: "$3$4$5" found in "}’ > $installDir/test4
cat $installDir/sendFile.txt | awk ‘{print " MAX:"$6,"CUR:"$7, "PERCENT:"$8"%"}’ > $installDir/test
mv $installDir/test $installDir/sendFile.txt
for findIP in $(cat $installDir/test2); do
if [ "$(cat $installDir/dhcpd-snmp.conf | fgrep -i $findIP)" ]; then
cat $installDir/dhcpd-snmp.conf | fgrep -i $findIP >> $installDir/foundIPs.txt
paste -d "" $installDir/test4 $installDir/foundIPs.txt $installDir/sendFile.txt > $installDir/test3
fi
done
#Clean up
rm $installDir/foundIPs.txt
rm $installDir/test2
mv $installDir/test3 $installDir/sendFile.txt
rm $installDir/test4
#We only want to e-mail if more than 1 line in the file
if [ "$(cat $installDir/sendFile.txt | wc -l)" -gt 0 ]; then
for mailto in $namn; do
cat $installDir/sendFile.txt | /usr/bin/mail -s "DHCP-Telefoni lease warning > $percent%" $mailto
done
else
echo "No IP-ranges are above: " $percent"%" > $installDir/sendFile.txt
fi
exit 0
[/bash]
changePercent.php
[php]
<?php
$searchedFor = $_GET[‘search’];
if(ctype_digit($searchedFor))
{
$test = fopen("percent.txt","rw") or exit("Unable to open file!");
if (($searchedFor > 1) && ($searchedFor <= 100)) {
file_put_contents(‘percent.txt’, $searchedFor);
}
else
{
echo "please enter a value between 1-100";
}
fclose($test);
exec(‘sh checkDHCP.sh’);
}
header( ‘Location: http://192.168.1.254/checkTelefoniDHCP’ ) ;
?>
[/php]
ignoredIPs.php
[php]
<?php
$array = file(‘ignoredIPs.txt’);
$addItem = $_GET[‘search’];
if(valid_ip($addItem))
{
$addItem = "$addItem\n";
array_push ($array,$addItem);
natsort($array);
file_put_contents(‘ignoredIPs.txt’, $array);
exec(‘sh checkDHCP.sh’);
}
header( ‘Location: http://192.168.1.254/checkTelefoniDHCP’ ) ;
?>
<?php
function valid_ip($ip) {
return preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" .
"(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $ip);
}
?>
[/php]
index.php
[php]
<html>
<head>
<title>Telefoni checkDHCP</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<div id="menu">
<h2>
DHCP-Telefoni-warning
</h2>
<?PHP
if ($_SERVER[‘PHP_AUTH_USER’] == "admin")
{
echo "<form action=\"ignoredIPs.php\" method=\"get\">\n";
echo "<fieldset>\n";
echo "<legend>1.Add single IP (beginning of range) to ignorelist:</legend>\n";
echo "<input type=\"text\" name=\"search\" id=\"search\">\n";
echo "<input type=\"submit\" value=\"Ok\" name=\"Ok\" id=\"addIPs\"> <input type=\"reset\" value=\"Reset\" name=\"Ok\" id=\"resetaddIPs\">\n";
echo "</fieldset>\n";
echo "</form>\n";
echo "<form action=\"removeIPfromIgnored.php\" method=\"get\">\n";
echo "<fieldset>\n";
echo "<legend>2.Remove IP from ignored list:</legend>\n";
echo "<input type=\"text\" name=\"search\" id=\"search\">\n";
echo "<input type=\"submit\" value=\"Ok\" name=\"Ok\" id=\"removeIPs\"> <input type=\"reset\" value=\"Reset\" name=\"Ok\" id=\"resetRemoveIPs\">\n";
echo "</fieldset>\n";
echo "</form>\n";
echo "<form action=\"changePercent.php\" method=\"get\">\n";
echo "<fieldset>\n";
echo "<legend>3.Change percent warning</legend>\n";
echo "<input type=\"text\" name=\"search\" id=\"search\">\n";
echo "<input type=\"submit\" value=\"Ok\" name=\"Ok\" id=\"changePercent\"> <input type=\"reset\" value=\"Reset\" name=\"Ok\" id=\"resetChangePercent\">\n";
echo "</fieldset>\n";
echo "</form>\n";
}
?>
</div>
<div id="iprange">
<h2>
<?PHP
$test = fopen("percent.txt","r") or exit("Unable to open file!");
echo "<div>These IP-ranges are ".fgets($test)."% full or more!</div>\n";
fclose($test);
?>
</h2>
<pre>
<?PHP
include("sendFile.txt");
?>
</pre>
</div>
<div id="ignoredip">
<h2>
Ignored IPs
</h2>
<pre>
<?PHP
include("ignoredIPs.txt");
?>
</pre>
</div>
<div id="output">
<?PHP
include("sampleoutput2.txt");
?>
</div>
<div id="header">
<ul>
<li id="selected"><a href="http://192.168.1.254/checkTelefoniDHCP">checkDHCP Telefoni</a></li>
<li><a href="http://192.168.1.254/manual.php">Manual</a></li>
</ul>
</div>
<div id="signature">
//Coded by Viktor Å
</div>
<div id="poolnames">
<h2>
Pool Names
</h2>
<pre>
<?PHP
include("dhcpd-snmp2.conf");
?>
</pre>
</div>
</body>
</html>
[/php]
manual.php
[php]
<html>
<head>
<title>Manual – Telefoni checkDHCP</title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<div id="manual">
<h2>Manual – Telefoni checkDHCP</h2>
This script used dhcpd-pools & cacti-dhcp to generate a list of all available DHCP-pools on the server. It then merges the lists and checks if any of the lines in sampleoutput.txt is above the specified range. If so it sends an e-mail to NOC with a warning.
<br>
The menu is only for changing percent or adding a IPrange to ignore.
<br>
1. Add IP to ignore, this make the script ignore that IP-range and no e-mails will be sent.
<br>
2. Remove IP from ignore (mostly for testing).
<br>
3. Change the percent to send warnings on.
<br>
<h2>
FIELDS
</h2>
<b>shared net name</b>
<br>
Name of the shared-network for the range.
<br>
<b>first ip</b>
<br>
First IP in lease pool range.
<br>
<b>last ip</b>
<br>
Last IP in lease pool range.
<br>
<b>max</b>
<br>
Number of IPs which exist in a pool, shared network or all together.
<br>
<b>cur</b>
<br>
Number of leases currently in use.
<br>
<b>percent</b>
<br>
Percent of IPs currently in use compared to max.
<br>
<b>touch</b>
<br>
Number of IPs which appear in the lease file, but whos leases have expired. A touched IP is either expired or abandoned. The touched IP count is somewhat misleading when you try to determine if an IP pool is big enough; it is a better indicator of whether a pool is too large.
<br>
<b>t+c</b>
<br>
The sum of Touched and Currently in-use leases.
<br>
<b>t+c perc</b>
<br>
Percent of IPs either touched or currently in use, compared to max.
<br>
<b>bu</b>
<br>
Failover pair can allocate these addresses. The count appears only if there is failover configuration.
<br>
<b>bu perc</b>
<br>
Percent of addresses that failover pair can allocate. The percent appears only if there is failover configuration.
<br><br>
//Coded by Viktor Å
</div>
<div id="header">
<ul>
<li><a href="http://192.168.1.254/checkTelefoniDHCP">checkDHCP Telefoni</a></li>
<li id="selected"><a href="http://192.168.1.254/manual.php">Manual</a></li>
</ul>
</div>
[/php]
removeIPfromIgnored.php
[php]
<?php
$lines = file(‘ignoredIPs.txt’);
$searchedFor = $_GET[‘search’];
if(valid_ip($searchedFor))
{
foreach ($lines as $line_num => $line)
{
if(stristr($line, $searchedFor)) {
print "<div>{$line} was removed from the ignorelist.</div>\n";
unset($lines[$line_num]);
file_put_contents(‘ignoredIPs.txt’, implode("", $lines));
$result = 1;
}
}
exec(‘sh checkDHCP.sh’);
}
header( ‘Location: http://192.168.1.254/checkTelefoniDHCP’ ) ;
?>
<?php
function valid_ip($ip) {
return preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])" .
"(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $ip);
}
?>
[/php]
runScript.php
[php]
<?php
exec(‘sh checkDHCP.sh’);
header( ‘Location: http://192.168.1.254/checkTelefoniDHCP’ ) ;
?>
[/php]
style.css
[css]
<style type="text/css">
body {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
color: black;
background-color: white;
}
input {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
color: black;
background-color: white;
}
div {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
background:white;
color: black;
}
* {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
color: black;
background-color:white;
}
h2 {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 15px;
}
iframe {
background-color: white;
height: 100%;
width: 100%;
}
a:link { color: blue; text-decoration: none; }
a:visited { color: blue; text-decoration: none; }
a:active { color: blue; text-decoration: none; }
a:hover { color: blue; text-decoration: underline; }
fieldset {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
background:white;
color:black;
position:relative;
}
legend {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
background:white;
color:black;
padding:1px 2px;
}
#header ul {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
list-style: none;
padding: 0;
margin: 0;
}
#header li {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
display: inline;
margin: 0 2px 0 0;
}
#header a {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
padding: 0 1em;
text-decoration: none;
color: blue;
background: white;
}
#header a:hover {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
background: white;
color: blue;
text-decoration: underline;
}
#header #selected {
}
#header #selected a {
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
padding-bottom: 2px;
text-decoration: underline;
font-weight: bold;
color: blue;
background: white;
}
#menu { position:absolute; width:340px; height:305px; z-index:1; left:30px; top:50px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
#iprange { position:absolute; width:350px; height:140px; z-index:1; left:30px; top:330px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
#ignoredip { position:absolute; width:350px; height:250px; z-index:1; left:30px; top:460px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
#output { position:absolute; width:600px; height:750px; z-index:1; left:1060px; top:50px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
#signature { position:absolute; width:200px; height:100px; z-index:1; left:30px; top:710px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
#manual { position:absolute; width:1000px; height:1000px; z-index:1; left:30px; top:50px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
#poolnames { position:absolute; width:650px; height:750px; z-index:1; left:390px; top:50px; clip: rect(0 100% 100% 0); text-align: left;layer-background-color: transparent; background-color: transparent; overflow: auto}
</style>
[/css]
Ok, now we need to make apache access these pages and protect it. Also make sure www-data is owner (just in case anything got owned as other user while creating them).
[bash]
sudo chown -R www-data:www-data /home/checkDHCP
#But make sure to secure the php files:
chown root:root /home/checkDHCP/*.php
vim /etc/apache2/conf.d/dhcp-warning
Alias /checkInternetDHCP /home/checkDHCP
<Directory /home/checkDHCP>
Options FollowSymLinks Indexes
AllowOverride All
<Limit GET POST>
order deny,allow
deny from all
allow from 192.168.1.254
</Limit>
DirectoryIndex index.php
<Files *.txt>
Order allow,deny
Deny from all
</Files>
</Directory>
#Now restart apache
/etc/init.d/apache restart
[/bash]
Now we need to setup DHCPd-snmp (atleast the script) so my script can get the headers from it. This is easily done by:
[bash]
cd dhcp-snmp
sudo chmod +x dhcp2snmpconf.pl
./dhcp2snmpconf.pl /etc/dhcp3/dhcpd.conf > /home/checkDHCP/dhcpd-snmp.conf
[/bash]
You can now reach the webpage at http://your.ip/checkInternetDHCP.
You can also put this script running under cron, just:
[bash]
su www-data
crontab -e
#Lets run the script every second hour between 8-22
0 2,8-22 * * * /home/checkDHCP/checkDHCP.sh
[/bash]
This is how all looks like in the end (I’ve omitted the beginning of the IP ranges and the aliases for security reasons):
And this is how it looks like when you receive the e-mail:
FAQ:
1. You need to have a working sendmail, try it out manually if you have troubles getting mails sent. /usr/bin/mail is contained in the package mailutils I think. So apt-get install mailutils.
2. dhcpd-pools still can’t handle dynamic-bootp lines (even with 2.13), if you have those in your dhcp3.conf file you must remove them, I modified my checkDHCP.sh:
[bash]
replace
/usr/local/bin/dhcpd-pools -c /etc/dhcp3/dhcpd.conf -l /var/lib/dhcp3/dhcpd.leases -o $installDir/sampleoutput.txt
with
cp /etc/dhcp3/dhcpd.conf $installDir/dhcpd.conf_backup
cat $installDir/dhcpd.conf_backup | sed s/dynamic-bootp// > $installDir/test2
/usr/local/bin/dhcpd-pools -c $installDir/test2 -l /var/lib/dhcp3/dhcpd.leases -o $installDir/sampleoutput.txt
[/bash]