├── README.md └── statusCakeMonitor.rename.me.php /README.md: -------------------------------------------------------------------------------- 1 | StatusCake-CloudFlare 2 | ===================== 3 | 4 | Using Statuscake's monitoring and Cloudflare to achieve high availability. 5 | 6 | A PHP web hook to handle down notifications from Statuscake. If a Down notification is received, it'll change the A record of a domain on cloudflare to a backup IP set by you. 7 | 8 |

9 | License: MIT
10 | Dependencies: Web Server, PHP, php-curl lib 11 |

12 | 13 | Setup:
14 | 1. I suggest you rename the php file to something obscure.
15 | 2. Add / change the global vars section. It consists of credentials and other information that needs to be modified to your needs.
16 | 3. Upload this script to the desired server, make sure the script is accessible via the internet.
17 | 4. On StatusCake:
18 | Go into group contacts and add the ping URL. This URL is the URL of your PHP script that you just uploaded to your server in step 3.
19 | Make sure the domains you're monitoring has the correct contact group (a group that contains the ping URL). 20 | 5. It's recommended that you have more than the PHP script as an alert type, so you can switch it back to the primary server once it's up. With this setup, a website shouldn't have a downtime of more than ~6 minutes, assuming your DNS provider does not cache queries. 21 |

22 | You can reach me on twitter . 23 |

24 | If you're looking for UptimeRobot + Cloudflare, you can find it here . 25 | 26 | -------------------------------------------------------------------------------- /statusCakeMonitor.rename.me.php: -------------------------------------------------------------------------------- 1 | "8.8.8.8,1" ); 19 | 20 | sets the domain google.com's backup IP adress to 8.8.8.8 and enabling cloudflare proxy (orange cloud) 21 | 22 | */ 23 | 24 | $CF_domains = array( 25 | "google.com" => "8.8.8.8,0", 26 | "www.google.com" => "8.8.4.4,1" 27 | ); 28 | 29 | //API key to your cloudflare account 30 | $CF_key = ""; 31 | 32 | //Cloudflare email address 33 | $CF_email= ""; 34 | 35 | 36 | //end of global vars 37 | ////////////////////////////////////////////////////////// 38 | //global functions 39 | 40 | //checks if the domain exists in $CF_domains and that it's up via HTTP 41 | function checkDomain ($domains, $domain){ 42 | foreach ( $domains as $key => $value ){ 43 | if (strcmp($key, $domain) == 0 ){ 44 | $vars=explode(",",$domains["$domain"]); 45 | $ip=$vars[0]; 46 | if (checkHost($ip)) { 47 | return true; 48 | } else { 49 | echo "backup server unreachable via HTTP\n"; 50 | return false; 51 | } 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | 58 | //checks if host returns "HTTP/1.1 200 OK" within a reasonable time frame 59 | function checkHost ($host) { 60 | $ch = curl_init(); 61 | curl_setopt($ch, CURLOPT_URL, $host); 62 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 63 | //curl_setopt($ch, CURLOPT_VERBOSE, 1); 64 | curl_setopt($ch, CURLOPT_HEADER, 1); 65 | curl_setopt($ch,CURLOPT_TIMEOUT,5); 66 | $result=curl_exec($ch); 67 | 68 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 69 | $header = substr($result, 0, $headerSize); 70 | if (strpos($header, "HTTP/1.1 200 OK") !== false){ 71 | return TRUE; 72 | } else { 73 | return FALSE; 74 | } 75 | 76 | } 77 | 78 | //interacts with CF API to switch to the backup IP 79 | function cfBkup ($domains, $domain, $subdomain, $cfkey, $cfemail){ 80 | $vars=explode(",",$domains["$subdomain"]); 81 | //get DNSID 82 | $ch= curl_init("https://www.cloudflare.com/api_json.html"); 83 | curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 84 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 85 | $postVars= array('a' => 'rec_load_all', 'tkn' => "$cfkey", 'email' => "$cfemail", 'z' => "$domain"); 86 | curl_setopt($ch, CURLOPT_POST, 1); 87 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postVars)); 88 | $results= json_decode(curl_exec($ch), TRUE); 89 | curl_close($ch); 90 | // var_dump ($results); 91 | $dnsList=$results['response']['recs']['objs']; 92 | // var_dump ($dnsList); 93 | $DNSID=""; 94 | for ($i=0; $i < sizeof($dnsList); $i++){ 95 | if ( strcmp($dnsList[$i]['name'], $subdomain) == 0 && strcmp($dnsList[$i]['type'], "A") == 0 ){ 96 | $DNSID=$dnsList[$i]['rec_id']; 97 | break; 98 | } 99 | } 100 | if (strcmp($DNSID, "" )!= 0){ 101 | // echo "DNSID: ".$DNSID; 102 | $ch= curl_init("https://www.cloudflare.com/api_json.html"); 103 | curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 104 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 105 | $postVars=array ('a' => "rec_edit", 'tkn' => "$cfkey", 'id' => "$DNSID", 'email' => "$cfemail", 106 | 'z' => "$domain", 'type' => "A", 'name' => "$subdomain", 'content' => "$vars[0]", 'service_mode' => "$vars[1]", 'ttl' => "1"); 107 | curl_setopt($ch, CURLOPT_POST, 1); 108 | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postVars)); 109 | $results= json_decode(curl_exec($ch), TRUE); 110 | //var_dump ($results); 111 | 112 | $result=$results['result']; 113 | echo "result:".$result; 114 | if (strcmp($result, "success") != 0){ 115 | echo "an error occured in record edit for domain: ".$subdomain; 116 | } else { 117 | //maybe write some logs saying it's successful or some sort of notification saying the record has been changed 118 | } 119 | } else { echo "error in finding DNSID"; }; 120 | } 121 | 122 | //end of global functions 123 | //////////////////////////////////////////////////////// 124 | 125 | if (strcmp(md5($SS_username.$SS_key),$token) != 0){ 126 | //header('Location: http://speedtest.tele2.net/1000GB.zip'); 127 | echo "token validation failed"; 128 | die; 129 | } 130 | 131 | if (!empty($_POST['URL']) && !empty($_POST['Status'])){ 132 | //strip http:// 133 | $checkDomain=str_replace("http://","",urldecode($_POST['URL'])); 134 | 135 | echo "checkdomain: ".$checkDomain."\n\n"; 136 | //check to see if $checkURL is in the $CF_domain list and make sure it's a down alert 137 | if ( checkDomain($CF_domains, $checkDomain) && strcmp($_POST['Status'], "Down") == 0){ 138 | //do more stuff here for subdomains 139 | $FQDN=explode(".",$checkDomain); 140 | $FQDN=$FQDN[sizeof($FQDN)-2].".".$FQDN[sizeof($FQDN)-1]; 141 | 142 | //if your FQDN is seperated by 2 periods (ex: something.co.uk), uncomment the line below 143 | // $FQDN=$FQDN[sizeof($FQDN)-3].".".$FQDN[sizeof($FQDN)-2].".".$FQDN[sizeof($FQDN)-1]; 144 | 145 | echo $FQDN; 146 | cfBkup ($CF_domains, $FQDN, $checkDomain, $CF_key, $CF_email); 147 | } else { echo "invalid url, alert type, or the backup server is unreachable";}; 148 | }else {echo "missing required post variables";} 149 | --------------------------------------------------------------------------------