├── 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 |
--------------------------------------------------------------------------------