CRON job for failover on pfSense
-
Hi,
I wrote a small script for webserver failover that I run as a CRON job on the pfSense system. The script checks if a remote website is running and in case it is down, a local backup server is started and DNS settings are adjusted. When the remote server is running again, the local server is shutdown (after a timeout based on the TTL of the remote server in order to allow DNS propagation).
My question is: (a) am I not overloading the pfSense system (Netgate SG-3100) by running this script in CRON, (b) does this have a negative effect on the security of the gateway?
While the script works fine, I have set CRON to only run it every 15 minutes (higher frequency would be nice though).
For anybody interested in the script, I include it in the post.
regards.
<?php // requirements: an account on DNS server to change A records, a backup server with SSH access, keyless login to backup server, the correct firewall and proxy settings for providing access to the backup server // // params // $hosts = array('mydomain.com','www.mydomain.com','my.mydomain.com'); // the URL's to be redirected $svr_ip = '192.168.1.10'; // the IP address of the backup server $svr_mac = 'e8:2c:b3:fc:3d:1b'; // the Mac address of the backup server $port = 22; // the ssh port of the backup server $rsa_dir = '/root/.ssh'; // the key location on pfSense system $ssh_user = 'user2'; // the user account on backup server $rem_svr = 'remote.mydomain.com'; // the URL to monitor $rem_port = 443; // the service port on the remote server $dns_usr = 'user1'; // the user account on DNS server $dns_pwd = 'mypasswd'; // the password on DNS server $dns_svr = 'https://eurodyndns.org/update/'; // the URL of the DNS update service $dns_ttl = 15; // the TTL of the domain $status = '/root/failover.on'; // the file indicating the status $ip_svr = 'http://checkip.dyndns.com/'; // URL to obtain external IP address $reboot = '/sbin/shutdown'; // shutdown command on backup server // // check is site in online // if(!$socket =@ fsockopen($rem_svr, $rem_port, $errno, $errstr, 30)) { // // check if site is already in offline mode // if (!file_exists($status)) { // // wake backup server // $wake = new WakeOnLan; $wake->WakeUp($svr_mac,$svr_ip); // // update DNS server // $ext = file_get_contents($ip_svr); preg_match('/\b(?:\d{1,3}\.){3}\d{1,3}\b/', $ext, $m); $addr = $m[0]; $up = new UpdateDNS; foreach ($hosts as $host) { $up->update($addr,$host,$dns_usr,$dns_pwd,$dns_svr); } date_default_timezone_set("Europe/Brussels"); file_put_contents($status,time()); } } else { if (file_exists($status)) { // // site recovered: get address of the site (in case it has changed) // $addr = gethostbyname($rem_svr); // // update DNS server // $up = new UpdateDNS; foreach ($hosts as $host) { $up->update($addr,$host,$dns_usr,$dns_pwd, $dns_svr); } // // remove failover flag // unlink($status); // // shutdown backup server // $conn = ssh2_connect($svr_ip, $port, array('hostkey'=>'ssh-rsa')); if (ssh2_auth_pubkey_file($conn, $ssh_user, $rsa_dir.'/id_rsa.pub', $rsa_dir.'/id_rsa')) { $res = ssh2_exec($conn, 'sudo '.$reboot."+".(2*$dns_ttl)); } } } class UpdateDNS { public static function update($addr,$fqdn,$user,$pwd,$dns_svr) { $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_TIMEOUT, 120); curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$pwd); curl_setopt($ch, CURLOPT_URL, $dns_svr . '?hostname=' . $fqdn . '&myip=' . $addr); $res = curl_exec($ch); curl_close($ch); } } class WakeOnLAN { public static function wakeUp($macAddressHexadecimal, $broadcastAddress) { $macAddressHexadecimal = str_replace(':', '', $macAddressHexadecimal); if (!ctype_xdigit($macAddressHexadecimal)) { throw new \Exception('Mac address invalid, only 0-9 and a-f are allowed'); } $macAddressBinary = pack('H12', $macAddressHexadecimal); $magicPacket = str_repeat(chr(0xff), 6).str_repeat($macAddressBinary, 16); if (!$fp = fsockopen('udp://' . $broadcastAddress, 7, $errno, $errstr, 2)) { throw new \Exception("Cannot open UDP socket: {$errstr}", $errno); } fputs($fp, $magicPacket); fclose($fp); } } ?>