Failover3

From XpertDNS

http://www.gnu.org/licenses/gpl.txt

Failover Monitor3 is used to monitor website, and if it were to go down it would update DNS to redirect traffic to another IP address. This script has been designed to work with Dynamic DNS at XpertDNS.com. This version has been updated to support our new DynDNS API, MySQL, and multiple domains.

Tested on PHP4 and PHP5 - Requires cURL support

You will need to configure your Dynamic DNS on your account for the domains you wish to update. You can modify it to fit your needs.

Configure the script with the proper information and run this script in a cron job. You can run it as often as you like. In this example it will run every 5 minutes

*/5     *       *       *       *       php     /path/to/failover.php > /dev/null 2>&1

Download all files here: http://www.xpertdns.com/failover3.tgz

    Contents

    PHP Code

  • Config File: config.inc.php
  • <?php
    ### GPL
    # Failover Monitor3 is used to monitor website, and if it were to go 
    # down it would update DNS to redirect traffic to another IP address. 
    # This script has been designed for http://www.xpertdns.com.
    # Copyright (C) 2007  Michael Donnarumma  Xpert Group Technologies, Inc.
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    ###
    // PHP INIT/SECURITY STUFF
    ini_set('display_errors', 1);
    ini_set('display_startup_errors', 1);
    ini_set('log_errors', 1);
    ini_set('allow_url_fopen', 0);
    ini_set('session.use_cookies',0);
    ini_set('error_reporting', 0);	# no error reporting
    //ini_set('error_reporting', E_ALL); # debug error reporting
    
    ## Configuration Variables ##
    // Your Company Name
    $compname="XpertDNS";
    
    // XpertDNS Login
    $UNAME="user@domain";
    $PASSWORD="p455w0rd_h45h"; #https://www.xpertdns.com/md5form.php
    
    // Tolerance
    $tol = "3";     # How many consecutive failures before DNS is updated.
    
    // File Paths
    $filepath = './';                    # This will need to be a path where php can write a file to keep track previous server state.
    $logname = $filepath."failover.log";
    
    // Database config
    function mysqlconnect() {
    $mysql_host = 'localhost';
    $mysql_user = 'user';
    $mysql_pass = 'pass';
    $mysql_db = 'db';
    mysql_connect("$mysql_host", "$mysql_user", "$mysql_pass")
        or die("error connecting to database");
    mysql_select_db("$mysql_db")
        or die("error selecting database");
    }
    
    // Status Codes - Additional HTTP Status Codes can be configured here
    
    $code = array(
    1=> "HTTP/1.1 200 OK",
    2=> "HTTP/1.1 202 Accepted",
    3=> "HTTP/1.1 301 Moved Permanently",
    4=> "HTTP/1.1 302 Found",
    5=> "HTTP/1.1 401 Authorization Required",
    6=> "HTTP/1.1 403 Forbidden",
    7=> "HTTP/1.1 500 Internal Server Error",
    );
    
    $code = str_replace(" ", " ", $code); 
    
    function status_codes($code, $sel) {
      echo '<SELECT name=response>';
      foreach ($code as $key => $value)
      {
      echo '<OPTION value="'.$value.'"';
      if($value==$sel){ echo 'selected="selected"'; }
      echo '> '.$value.'';
      }
      echo '</select>'; 
    }
    ?>
    <link href="styles.css" rel="stylesheet" type="text/css">
    
    

  • Update Code: failover.php
  • <?php
    ### GPL
    # Failover Monitor3 is used to monitor website, and if it were to go 
    # down it would update DNS to redirect traffic to another IP address. 
    # This script has been designed for http://www.xpertdns.com.
    # Copyright (C) 2007  Michael Donnarumma  Xpert Group Technologies, Inc.
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    ###
    
    include("config.inc.php");
    
    ## Functions
    
    function keyword_search($ip,$url,$keyword,$port) {
     $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
    
    $header[] = "Host: $url\r\n";
    $header[] = "MIME-Version: 1.0\r\n";
    $header[] = "Content-type: text/html; charset=iso-8859-1\r\n";
    $header[] = "Content-transfer-encoding: text\r\n";
    
     $ch = curl_init();				    // Initialize curl handle
     curl_setopt($ch, CURLOPT_URL, $ip); 		    // Set server to post to
     curl_setopt($ch, CURLOPT_HTTPHEADER, $header);     // Set custom http header to post
     curl_setopt($ch, CURLOPT_FAILONERROR, 1);	    // Fail on errors
     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);	    // Allow redirects
     curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);	    // Return into a variable
     curl_setopt($ch, CURLOPT_PORT, $port);		    // Set the port number
     curl_setopt($ch, CURLOPT_TIMEOUT, 1);		    // Times out after 1s
     curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);  // Set user agent
     $document = curl_exec($ch);			    // Execute connect to site
     $search = array('@<script[^>]*?>.*?</script>@si',  // Strip out javascript
     '@<style[^>]*?>.*?</style>@siU',    		    // Strip style tags properly
     '@<[\/\!]*?[^<>]*?>@si',            		    // Strip out HTML tags
     '@<![\s\S]*?-[ \t\n\r]*>@',        		    // Strip multi-line comments including CDATA
     '/\s{2,}/',
     );
     $text = preg_replace($search, "\n", html_entity_decode($document));
     $pat[0] = "/^\s+/";
     $pat[2] = "/\s+\$/";
     $rep[0] = "";
     $rep[2] = " ";
     $res = preg_replace($pat, $rep, trim($text));
     if(stristr($res, $keyword) === FALSE) {
      return "1";
     }else{
      return "0";
     }
    }
    
    function faillog($logname, $l) {
     $d = date('Y-m-d H:i:s T');
     $data = "\n".$d." ".$l;
     if (!$file_handle = fopen($logname,"a")) { echo "Cannot open file"; }
     if (!fwrite($file_handle, $data)) { echo "Cannot write to file"; }
     fclose($file_handle);
    }
    
    function dns_get_headers($ip,$url,$port,$format=0) {
     $url_info=parse_url($url);
     $fp=fsockopen($ip, $port, $errno, $errstr, 1);
     if($fp) {
      $head = "HEAD ".@$url_info['path']."?".@$url_info['query'];
      $head .= " HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n";
      fputs($fp, $head);
      while(!feof($fp)) {
       if($header=trim(fgets($fp, 1024))) {
        if($format == 1) {
         $h2 = explode(':',$header);
         if($h2[0] == $header) {
          $headers['status'] = $header;
         } else {
          $headers[strtolower($h2[0])] = trim($h2[1]);
          }
         } else {
          $headers[] = $header;
         }
      }
     }
      return $headers;
     } else {
      return false;
     }
    }
    
    function dnsupdate($DYNID, $ip, $UNAME, $PASSWORD) {
     $path="dynid=$DYNID&ip=$ip&uname=$UNAME&password=$PASSWORD";
     $sessions = curl_init();
      curl_setopt($sessions, CURLOPT_URL,'https://www.xpertdns.com/dyndns.php');
      curl_setopt($sessions, CURLOPT_POST, 1);
      curl_setopt($sessions, CURLOPT_POSTFIELDS, $path);
      curl_setopt($sessions, CURLOPT_FOLLOWLOCATION,0);
      curl_setopt($sessions, CURLOPT_RETURNTRANSFER,1);
      $my_load_page = curl_exec($sessions);
      return $my_load_page;
    }
    
    function writestat($id, $curstatus){
     $sql = "UPDATE `site_mon` SET `status` = '$curstatus' WHERE `id` = $id";
     mysql_query($sql) or die('Query failed: ' . mysql_error());
    }
    
    ## Script Start ##
    
    // Initialize Variables
    mysqlconnect();
    $sql = "SELECT * FROM site_mon";
    $getsql = mysql_query($sql) or die('Query failed: ' . mysql_error());
    unset($dynidList);
    while ( $showdata = mysql_fetch_row($getsql) ) {
     $id = $showdata[0];
     $domainname = $showdata[1];
     $ipaddress = $showdata[2];
     $ipaddress2 = $showdata[3];
     $port = $showdata[4];
     $resp = $showdata[5];
     $domainname_id = $showdata[6];
     $status = $showdata[7];
     $keyword = $showdata[9];
    
    // Get current status of server
     if ($showdata[8] == "0" ) {
      $response = @dns_get_headers($ipaddress,"http://$domainname/",$port, 0);
      if (!$response) {
       $curstatus = "1";
      }elseif($response[0]=$resp){
       $curstatus = "0";
      }
     }else{
       $curstatus = keyword_search($ipaddress,$domainname,$keyword,$port);
     }
     
    // Site was online
     if($status=='0') {
      if($curstatus=='0') {
      }elseif($curstatus=='1'){
       writestat($id, $curstatus);
       if ($tol == $curstatus){
        echo "Host UP!";
    	$l = "$domainname UP! - Updating DNS";
        faillog($logname, $l);
        $dynidList[$ip][] = $domainname_id;
    	faillog($logname, $dyn);
       }
      }
      
    // Site was not online
     }elseif($status>='1') {
      if($curstatus=='1') {
       $tolstat = $status + 1;
       writestat($id, $tolstat);
       if ($tol == $status){
        $l = "$domainname DOWN! - Tolerance ($status/$tol) reached, Updating DNS";
        faillog($logname, $l);
        $ip = $ipaddress2;
        $dynidList[$ip][] = $domainname_id;
       }elseif($tol > $status){
        $l = "$domainname DOWN! - Tolerance ($status/$tol) not reached, waiting a bit longer";
        faillog($logname, $l);
       }elseif($tol < $status){
        $l = "$domainname DOWN! - Tolerance ($status/$tol) exceeded, waiting for server to become available";
        faillog($logname, $l);
       }
      }elseif($curstatus=='0'){
       if ($tol <= $status){
        $l = "$domainname UP! - Updating DNS";
        faillog($logname, $l);
        $ip = $ipaddress;
        $dynidList[$ip][] = $domainname_id;
        writestat($id, $curstatus);
       }elseif($tol > $status){
        $l = "$domainname UP! - Tolerance ($status/$tol) not reached, no need to update";
        faillog($logname, $l);
        writestat($id, $curstatus);
       }
      }
     }
    }
    
    // Send changes to DNS
    if(isset($dynidList)) {
     foreach ($dynidList as $ip => $domainname_id) {
      $idlist = implode(",", $domainname_id);
      $dyn = dnsupdate("$idlist", $ip, $UNAME, $PASSWORD);
      faillog($logname, $dyn);
     }
    }
    
    // Force Update
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'web') {
     header( "refresh: 1; index.php" );
     echo "Web Check Complete";
    } else {
    echo "Check Complete";
     exit;
    }
    ?>
    
    

  • Database Interface: index.php
  • <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
    <?php 
    ### GPL
    # Failover Monitor3 is used to monitor website, and if it were to go 
    # down it would update DNS to redirect traffic to another IP address. 
    # This script has been designed for http://www.xpertdns.com.
    # Copyright (C) 2007  Michael Donnarumma  Xpert Group Technologies, Inc.
    #
    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    ###
    
    include("config.inc.php"); 
    function head($compname){
     echo '<html><body><center><h1>'.$compname.' DNS Failover Station</h1>';
    }
    function footer(){
     echo '<br><a href="index.php?state=insert_data">New Record</a> | 
     <a href="index.php">Display Record</a> | 
     <a href="failover.php?state=web"> Force Check</a> 
     </center></html>';
    }
    
    //INSERT
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'insert_data') {
     head($compname); ?>
     <form id="insert" name="insert" method="post" action="<?=$_SERVER['PHP_SELF']?>">
      <table width="" border="0" cellspacing="0" cellpadding="0">
        <tr><th scope="col">Hostname</th><td><input type="text" name="host" /></td></tr>
        <tr><th scope="col">Primary IP</th><td class="alt"><input type="text" name="ip" /></td></tr>
        <tr><th scope="col">Replacement IP</th><td><input type="text" name="ip2" /></td></tr>
        <tr><th scope="col">Port</th><td class="alt"><input type="text" name="port" /></td></tr>
        <tr><th scope="col">Status Code</th><td><?php status_codes($code,""); ?></td></tr>
        <tr><th scope="col">DynID</th><td class="alt"><input type="text" name="dynid" /></td></tr>
    	<th scope="col">Keyword</th><td><input type="text" name="content" /></td></tr>
        <th scope="col">Content Search</th><td class="alt"><select name="cont_search">
        <option value="0" selected="selected" >Off</option>
        <option value="1" >On</option></select></td></tr>
      </table>
      <input name="state" type="hidden" value="insert_data_now">
      <input name="" type="submit"><input name="" type="reset">
     </form>
     <?php footer();
     exit;
    }
    
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'insert_data_now') {
     mysqlconnect();
     $sql = "INSERT INTO `site_mon` (`id`,`host`,`ip`,`ip2`,`port`,`response`,`dynid`,`status`,`cont_search`,`content`)"; 
     $sql .= "VALUES (NULL , '".$_REQUEST['host']."', '".$_REQUEST['ip']."', '".$_REQUEST['ip2']."', ";
     $sql .= "'".$_REQUEST['port']."', '".$_REQUEST['response']."', '".$_REQUEST['dynid']."', '0', ";
     $sql .= "'".$_REQUEST['cont_search']."', '".$_REQUEST['content']."')";
      if (mysql_query($sql) or die(mysql_error())){
       header( "Location: index.php" );
      }
     mysql_close();
     exit;
    }
    
    // DELETE
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'delete_data') {
     head($compname);
     mysqlconnect();
     $sql = "SELECT * FROM site_mon WHERE id='".$_REQUEST['rid']."'";
     $getsql = mysql_query($sql) or die('Query failed: ' . mysql_error());
     $showdata = mysql_fetch_row($getsql);
     $id = $showdata[0];
     $host = $showdata[1];
     $ip = $showdata[2];
     $ip2 = $showdata[3];
     $port = $showdata[4];
     $response = $showdata[5];
     $dynid = $showdata[6];
     $status = $showdata[7]; 
     if($showdata[8]) { $cont_search = "on"; }else{ $cont_search = "off"; }
     $content = $showdata[9]; ?>
     <table  id="mytable" cellspacing="0" border="0">
      <tr>
       <th scope="col">ID</th>
       <th scope="col">Hostname</th>
       <th scope="col">Primary IP</th>
       <th scope="col">Replacement IP</th>
       <th scope="col">Port</th>
       <th scope="col">Status Code</th>
       <th scope="col">Dyn ID</th>
       <th scope="col">Failures</th>
       <th scope="col">Keyword</th>
       <th scope="col">Content Search</th>
      </tr>
      <?php 
      echo "<tr>
             <td>$id</td>
    		 <td>$host</td>
    		 <td>$ip</td>
    		 <td>$ip2</td>
    		 <td>$port</td>
             <td>$response</td>
             <td>$dynid</td>
    		 <td>$status</td>
    		 <td>$content</td>
    		 <td>$cont_search</td>
    		</tr></table>"; ?>
     <br /><b><a href="index.php?state=delete_data_now&id=<?=$id?>">Delete</a> | <a href="index.php">Cancel</a></b><br />
     <?php
     footer();
     exit;
    }
    
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'delete_data_now') {
     head($compname);
     mysqlconnect();
     $sql = "DELETE FROM site_mon WHERE id='".$_REQUEST['id']."'";
      if (mysql_query($sql) or die(mysql_error())){
       header( "refresh: 3; index.php" );
       echo "Record Successfully Deleted";
      }
     mysql_close();
     footer();
     exit;
    }
    
    // EDIT
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'edit_data') {
     head($compname);
     mysqlconnect();
     $sql = "SELECT * FROM site_mon WHERE id='".$_REQUEST['rid']."'";
     $getsql = mysql_query($sql) or die('Query failed: ' . mysql_error());
     $showdata = mysql_fetch_row($getsql);
     $id = $showdata[0];
     $host = $showdata[1];
     $ip = $showdata[2];
     $ip2 = $showdata[3];
     $port = $showdata[4];
     $response = $showdata[5];
     $dynid = $showdata[6];
     $status = $showdata[7]; 
     $cont_search = $showdata[8];
     $content = $showdata[9];
     ?>
     <form id="edit" name="edit" method="post" action="<?=$_SERVER['PHP_SELF']?>">
      <table width="" border="0" cellspacing="0" cellpadding="0">
       <tr><th scope="col">Hostname</th><td class="alt"><input name="host" type="text" value="<?=$host?>" /></td></tr>
       <tr><th scope="col">Primary IP</th><td><input type="text" name="ip" value="<?=$ip?>" /></td></tr>
       <tr><th scope="col">Replacement IP</th><td class="alt"><input type="text" name="ip2" value="<?=$ip2?>" /></td></tr>
       <tr><th scope="col">Port</th><td><input type="text" name="port" value="<?=$port?>" /></td></tr>
       <tr><th scope="col">Status Code</th><td class="alt"><?php status_codes($code,$response); ?></td></tr>
       <tr><th scope="col">DynID</th><td><input type="text" name="dynid" value="<?=$dynid?>" /></td></tr>
       <tr><th scope="col">Failures</th><td class="alt"><input type="text" name="status" value="<?=$status?>" /></td></tr>
       <th scope="col">Keyword</th><td><input type="text" name="content" value="<?=$content?>" /></td></tr>
       <th scope="col">Content Search</th><td class="alt"><select name="cont_search">
       <option value="0" <? if($cont_search == "0"){ echo 'selected="selected"'; } ?> >Off</option>
       <option value="1" <? if($cont_search == "1"){ echo 'selected="selected"'; } ?> >On</option></select></td></tr>
      </table>
      <input name="id" type="hidden" value="<?=$id?>">
      <input name="state" type="hidden" value="edit_data_now">
      <input name="" type="submit"><input name="" type="reset">
     </form>
     <?php footer();
     exit;
    }
    
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'edit_data_now') {
     mysqlconnect();
     $sql = "UPDATE `site_mon` SET `host`='".$_REQUEST['host']."',`ip`='".$_REQUEST['ip']."',";
     $sql .= "`ip2`='".$_REQUEST['ip2']."',`port`='".$_REQUEST['port']."',`response`='".$_REQUEST['response']."',";
     $sql .= "`dynid`='".$_REQUEST['dynid']."',`status`='".$_REQUEST['status']."',`cont_search`='".$_REQUEST['cont_search']."',`content`='".$_REQUEST['content']."' WHERE `id`='".$_REQUEST['id']."'";
     if (mysql_query($sql) or die(mysql_error())){
      header( "refresh: 3; index.php" );
      echo "Record Edited Successfully";
     }
     mysql_close();
     exit;
    }
    
    // READ LOG
    if(isset($_REQUEST['state']) && $_REQUEST['state'] == 'log') {
     if($_REQUEST['clear'] == '1'){
      fopen($logname, 'w');
      header( "refresh: 0; index.php" );
      exit;
     }
     head($compname);
     $theData = file($logname);
     echo '<table id="logtable" cellspacing="0" border="0"><tr><td>';
     if(!empty($theData)) {
      foreach ($theData as $line_num => $line) {
       if($line_num != "0"){
        echo "Line #<b>{$line_num}</b> : " . htmlspecialchars($line) . "<br />\n";
       }
      }
     }else{
      echo "Empty Log";
     }
     echo '</td></tr></table><br><b><a href="index.php?state=log&clear=1">Clear Log</a></b><br>';
     footer();
     exit;
    }
    
    // DEFAULT
    if(!isset($_REQUEST['state'])) {
     head($compname); ?>
     <table id="mytable" cellspacing="0" border="0">
      <tr>
       <th scope="col">ID</th>
       <th scope="col">Hostname</th>
       <th scope="col">Primary IP</th>
       <th scope="col">Replacement IP</th>
       <th scope="col">Port</th>
       <th scope="col">Status Code</th>
       <th scope="col">Dyn ID</th>
       <th scope="col">Failures</th>
       <th scope="col">Keyword</th>
       <th scope="col">Content Search</th>
       <th scope="col"></th>
       <th scope="col"></th>
      </tr>
      <?php mysqlconnect();
      $sql = "SELECT * FROM site_mon";
      $getsql = mysql_query($sql) or die('Query failed: ' . mysql_error());
      $nbrow=0;
      while ( $showdata = mysql_fetch_row($getsql) ) {
      $nbrow++;
       $id = $showdata[0];
       $host = $showdata[1];
       $ip = $showdata[2];
       $ip2 = $showdata[3];
       $port = $showdata[4];
       $response = $showdata[5];
       $dynid = $showdata[6];
       $status = $showdata[7];
       if($showdata[8]) { $cont_search = "on"; }else{ $cont_search = "off"; }
       $content = $showdata[9];
    
       if ($nbrow % 2 == 0) { 
        $th='class="spec"';
        $td="";
       } else {
        $th='class="specalt"';
        $td='class="alt"';
       }
       echo "<tr><th scope=\"row\" $th>$id</th><td $td>$host</td><td $td>$ip</td>";
       echo "<td $td>$ip2</td><td $td>$port</td><td $td>$response</td><td $td>$dynid</td>";
       echo "<td $td>$status</td><td $td>$content</td><td $td>$cont_search</td>";
       echo "<td $td><a href=\"index.php?state=edit_data&rid=$id\">Edit</a></td>";
       echo "<td $td><a href=\"index.php?state=delete_data&rid=$id\">Delete</a></td></tr>";
      }
     echo '</table>';
     mysql_close();
     footer();
     exit;
    } ?>
    

  • Cascading Style Sheets: styles.css
  • Associated iamges reside in the images direcorty

    Image:bg_header.jpg

    Image:bullet1.gif

    Image:bullet2.gif

    /* CSS Document */
    body {
    	font: normal 11px auto "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    	color: #4f6b72;
    	background: #E6EAE9;
    }
    
    a {
    	color: #c75f3e;
    }
    
    #mytable {
    	width: 70%;
    	padding: 0;
    	margin: 0;
    }
    
    caption {
    	padding: 0 0 5px 0;
    	width: 700px;	 
    	font: italic 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    	text-align: right;
    }
    
    th {
    	font: bold 11px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    	color: #4f6b72;
    	border-right: 1px solid #C1DAD7;
    	border-bottom: 1px solid #C1DAD7;
    	border-top: 1px solid #C1DAD7;
    	letter-spacing: 2px;
    	text-transform: uppercase;
    	text-align: left;
    	padding: 6px 6px 6px 12px;
    	background: #CAE8EA url(images/bg_header.jpg) no-repeat;
    }
    
    th.nobg {
    	border-top: 0;
    	border-left: 0;
    	border-right: 1px solid #C1DAD7;
    	background: none;
    }
    
    td {
    	border-right: 1px solid #C1DAD7;
    	border-bottom: 1px solid #C1DAD7;
    	background: #fff;
    	padding: 6px 6px 6px 12px;
    	color: #4f6b72;
    }
    
    
    td.alt {
    	background: #F5FAFA;
    	color: #797268;
    }
    
    th.spec {
    	border-left: 1px solid #C1DAD7;
    	border-top: 0;
    	background: #fff url(images/bullet1.gif) no-repeat;
    	font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    }
    
    th.specalt {
    	border-left: 1px solid #C1DAD7;
    	border-top: 0;
    	background: #f5fafa url(images/bullet2.gif) no-repeat;
    	font: bold 10px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    	color: #797268;
    }
    
    h1 {
    	font: bold 16px auto "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
    	color: #4f6b72;
    }
    
    

    MySQL table

    -- 
    -- Table structure for table `site_mon`
    -- 
    
    CREATE TABLE `site_mon` (
      `id` int(6) NOT NULL auto_increment,
      `host` varchar(128) NOT NULL default '',
      `ip` varchar(12) NOT NULL default '',
      `ip2` varchar(12) NOT NULL default '',
      `port` int(6) NOT NULL default '80',
      `response` varchar(32) NOT NULL default '',
      `dynid` varchar(16) NOT NULL default '',
      `status` int(16) NOT NULL default '0',
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
    
    -- 
    -- Dumping data for table `site_mon`
    -- 
    
    INSERT INTO `site_mon` (`id`, `host`, `ip`, `ip2`, `port`, `response`, `dynid`, `status`) VALUES 
    (1, 'domain.com', '10.10.10.10', '11.11.11.11', 80, 'HTTP/1.1 200 OK', '50000', '0');