I had a problem with Statuscake’s servers not being able to check my wp-login.php’s current up/down status as it turns out that Cloudflare was challenging the visits from their servers to see if they were human or not. Cloudflare allows you to use their API to add and remove multiple IPs from your whitelist and blacklist in their admin dashboard. The following PHP code can be used, with modification of the configuration at the top, to allow this to happen in bulk, which they don’t allow you to do from their website. Run it via the php console command “php filenamehere.php” and it will output the current script status throughout.
https://gist.github.com/Coopeh/931d5cb93587aa816bda553580bd8a56
<?php $time_start = microtime(true); // Add multiple IPs to blacklist, whitelist or unlist them on Cloudflare using CloudFlare API by AzzA // Ed Cooper 2015 - https://blog.ed.gs // Version 1.0 // Configure your API key and email address below $cfemailaddress = "[email protected]"; // Cloudflare email address $cfapikey = "1234123412341234123412341234"; // Cloudflare API key $type = "Whitelist"; // Use either Whitelist, Blacklist or Unlist as options // Use either $url, $ips or both, but make sure the URL address is a line break separated list of IPs, comment and uncomment the lines as needed $url = "https://www.statuscake.com/API/Locations/txt"; // Web address for line break separated list of IPs $ips = array("128.199.222.65","188.166.158.224","5.45.179.103","199.167.128.80","185.157.211.211","162.248.97.72","37.235.53.240","162.253.64.104","192.241.221.11","50.2.139.16","108.61.162.214","37.235.48.42","158.255.208.76","125.63.48.239","185.12.45.70","103.194.112.70","213.183.56.107","217.148.43.188","91.236.116.163","37.235.55.205","217.148.43.202","45.63.104.11","45.32.151.21","107.170.227.23","107.170.227.24","188.226.169.228","188.226.185.106","188.226.186.199","107.155.108.234","188.226.171.58","108.61.119.153","188.226.158.160","107.170.240.141","107.161.28.219","107.155.104.182","107.155.125.29","178.62.78.199","209.222.30.242","46.101.74.251","108.61.212.141","178.62.65.162","178.62.109.7","188.226.247.184","188.226.139.158","188.226.184.152","178.62.106.84","104.131.248.65","104.131.248.78","46.101.61.83","104.131.247.151","178.62.86.69","107.170.197.248","107.170.219.46","188.226.203.84","178.62.41.44","178.62.41.49","178.62.41.52","162.243.71.56","178.62.40.233","162.243.247.163","107.170.53.191","31.220.7.237","178.62.80.93","178.62.71.227","178.73.210.99","181.41.214.137","154.127.60.59","185.112.157.185","46.101.240.208","46.101.238.182","46.101.238.189","46.101.27.186","178.62.104.137","193.182.144.147","159.203.31.18","149.154.157.61","138.204.171.136","185.60.135.86","154.127.60.23","188.166.253.148","37.157.246.146","46.101.110.43","46.101.110.45","178.62.101.57","46.101.0.24","46.101.20.96","46.101.110.32","82.221.95.161","37.235.52.25","37.97.188.103","151.236.18.80","185.47.129.168","37.235.48.146","91.239.125.60","139.59.15.79","193.182.144.105","45.63.121.159","45.32.145.79","181.41.201.117","151.236.10.129","151.80.175.226","185.173.92.161","185.135.81.201","138.68.24.60","107.191.47.131","138.68.24.115","138.68.24.136","138.68.24.207","138.197.140.243","138.197.130.232","138.197.130.235","139.59.155.26","138.68.80.173","139.59.190.241","138.68.80.10","139.59.29.167","45.63.88.213","45.63.86.120","45.32.128.80","104.156.229.24","45.32.212.56","104.156.255.184","108.61.215.179","45.32.166.195","45.32.160.172","45.32.171.24","107.191.57.237","45.63.26.78","45.76.192.50","45.32.36.158","139.59.26.85","139.59.22.109","104.238.164.105","45.63.76.68","45.63.78.84","45.32.195.186","45.76.3.112","45.76.1.44","45.32.7.22","159.203.186.225","159.203.182.22","159.203.182.60","45.63.51.63","45.63.61.213","108.61.205.201","45.32.192.198","45.32.195.93","104.206.168.26","138.68.151.78","45.63.97.4","104.238.185.175","104.238.185.46","104.238.186.209","45.76.128.250","104.238.171.176","104.238.187.61","104.238.174.234","108.61.196.37","108.61.197.147","45.76.134.164","45.76.135.253","108.61.173.0","45.63.96.68","45.76.134.85","45.32.183.128","45.76.130.43","45.76.129.212","45.76.134.198","45.76.134.237","45.76.135.14","217.78.0.117","217.78.0.171","2a03:b0c0:1:a1::2d:6001","2001:19f0:7001:18cd:5400:00ff:fe03:86f7","2001:19f0:9002:18b:5400:00ff:fe46:338d","2001:19f0:6801:b6:5400:00ff:fe2d:9386","2a03:b0c0:0:1010::386:7001","2a03:b0c0:0:1010::39c:2001","2a03:b0c0:0:1010::539:9001","2001:19f0:5c01:1a9:5054:00ff:feb5:3dfd","2a03:b0c0:0:1010::385:4001","2604:a880:1:20::f64:c001","2a03:b0c0:1:d0::5e:f001","2001:19f0:7402:1ab:5054:00ff:fec5:d750","2a03:b0c0:1:d0::df:6001","2001:19f0:5801:20d:5054:00ff:fea5:ffcc","2a03:b0c0:1:d0::df:4001","2a03:b0c0:1:d0::df:b001","2a03:b0c0:0:1010::349:e001","2a03:b0c0:0:1010::3a5:1","2a03:b0c0:1:d0::df:3001","2604:a880:0:1010::d3d:a001","2a03:b0c0:1:d0::d0:3001","2604:a880:0:1010::56:6001","2a03:b0c0:1:d0::df:a001","2a03:b0c0:1:d0::5b:a001","2a03:b0c0:1:d0::5b:c001","2a03:b0c0:1:d0::5c:2001","2604:a880:0:1010::d32:6001","2604:a880:0:1010::d32:5001","2a03:b0c0:1:d0::2e5:1001","2a03:b0c0:1:d0::2e5:2001","2a03:b0c0:3:d0::173:b001","2a03:b0c0:3:d0::179:a001","2a03:b0c0:3:d0::179:b001","2a03:b0c0:1:d0::91:5001","2001:b60:1000:149:154:157:61:1","2a03:b0c0:3:d0::216:9001","2a03:b0c0:3:d0::216:a001","2a03:b0c0:1:d0::44f:1","2a03:b0c0:1:d0::1de:6001","2a03:b0c0:3:d0::b61:9001","2400:6180:100:d0::8e:e001","2a03:f80:972:193:182:144:105:1","2001:19f0:7001:76c:5400:00ff:fe2c:0bea","2001:19f0:6801:ba:5400:00ff:fe2e:556f","2001:19f0:ac01:1e2:5400:00ff:fe37:00e9","2001:19f0:ac01:195:5400:00ff:fe37:00ea","2001:19f0:ac01:1b7:5400:00ff:fe37:00eb","2001:19f0:ac01:1dc:5400:00ff:fe37:00ec","2001:19f0:5401:b8:5400:00ff:fe37:00fa","2001:19f0:5401:b6:5400:00ff:fe37:00fb","2001:19f0:5401:b7:5400:00ff:fe37:00fd","2001:19f0:9002:138:5400:00ff:fe37:02a1","2001:19f0:9002:17d:5400:00ff:fe37:02a2","2001:19f0:9002:17e:5400:00ff:fe37:02a3","2001:19f0:5801:20f:5400:00ff:fe37:027f","2001:19f0:5801:20e:5400:00ff:fe37:027e","2001:19f0:7001:18d6:5400:00ff:fe37:0412","2001:19f0:7001:18c4:5400:00ff:fe37:0413","2001:19f0:5c01:156:5400:00ff:fe37:080b","2001:19f0:5c01:163:5400:00ff:fe37:080c","2001:19f0:5c01:1a6:5400:00ff:fe37:080d","2001:19f0:6401:14a:5400:00ff:fe37:0870","2001:19f0:5:33f:5400:00ff:fe37:2d7b","2001:19f0:5:340:5400:00ff:fe37:2d7d","2001:19f0:5:342:5400:00ff:fe37:2d7f","2604:a880:400:d0::a27:6001","2604:a880:400:d0::a27:7001","2604:a880:400:d0::a27:8001","2001:19f0:6001:4ad:5400:00ff:fe37:2e33","2001:19f0:6001:27c:5400:00ff:fe37:2e79","2001:19f0:6401:12d:5400:00ff:fe37:2eb2","2001:19f0:6401:14c:5400:00ff:fe37:2eb7","2001:19f0:6401:93:5400:00ff:fe37:2eeb","2a03:b0c0:1:a1::821:b001","2001:19f0:7402:20f:5400:00ff:fe47:8333"); // Statuscake IPs // STOP EDITING NOW function get_data($url) { $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $data = curl_exec($ch); curl_close($ch); return $data; } class cloudflare_api { // The URL of the API private static $URL = array( 'USER' => 'https://www.cloudflare.com/api_json.html', 'HOST' => 'https://api.cloudflare.com/host-gw.html' ); // Timeout for the API requests in seconds const TIMEOUT = 5; // Stores the api key private $token_key; private $host_key; // Stores the email login private $email; /** * Make a new instance of the API client */ public function __construct() { $parameters = func_get_args(); switch (func_num_args()) { case 1: // a host API $this->host_key = $parameters[0]; break; case 2: // a user request $this->email = $parameters[0]; $this->token_key = $parameters[1]; break; } } public function setEmail($email) { $this->email = $email; } public function setToken($token_key) { $this->token_key = $token_key; } /** * CLIENT API * Section 3 * Access */ /** * 4.7a - Whitelist IPs * You can add an IP address to your whitelist. */ public function wl($ip) { $data = array( 'a' => 'wl', 'key' => $ip ); return $this->http_post($data); } /** * 4.7b - Blacklist IPs * You can add an IP address to your blacklist. */ public function ban($ip) { $data = array( 'a' => 'ban', 'key' => $ip ); return $this->http_post($data); } /** * 4.7c - Unlist IPs * You can remove an IP address from the whitelist and the blacklist. */ public function nul($ip) { $data = array( 'a' => 'nul', 'key' => $ip ); return $this->http_post($data); } /** * GLOBAL API CALL * HTTP POST a specific task with the supplied data */ private function http_post($data, $type = 'USER') { switch ($type) { case 'USER': $data['u'] = $this->email; $data['tkn'] = $this->token_key; break; case 'HOST': $data['host_key'] = $this->host_key; break; } $ch = curl_init(); curl_setopt($ch, CURLOPT_VERBOSE, 0); curl_setopt($ch, CURLOPT_FORBID_REUSE, true); curl_setopt($ch, CURLOPT_URL, self::$URL[$type]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_TIMEOUT, self::TIMEOUT); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $http_result = curl_exec($ch); $error = curl_error($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http_code != 200) { return array( 'error' => $error ); } else { $result = json_decode($http_result); echo $result->{'response'}->{'result'}->{'ip'}." - ".ucfirst($result->{'result'})."\n"; } } } $valid = array(); // Check if the URL is set in the parameters at the top then retrieve and validate the contents if (isset($url)) { $url = get_data($url); $comma = strpos($url, ","); $space = strpos($url, " "); $linebreak = strpos($url, "\n"); if ($comma !== false) { $url = explode(",", $url); echo "Comma detected\n"; } else if ($space !== false) { $url = explode(" ", $url); echo "Space detected\n"; } else if ($linebreak !== false) { $url = explode("\n", $url); echo "Line break detected\n"; } else { echo "Can't detect delimiter, is it a space, comma or new line?\n"; } if (is_array($url)) { foreach ($url as $contents) { if (filter_var($contents, FILTER_VALIDATE_IP)) { array_push($valid, $contents); } else { echo $contents." is not valid.\n"; } } } } // Check if any IPs are set in the parameters and validate the contents if (isset($ips)) { if (is_array($ips)) { foreach ($ips as $contents) { if (filter_var($contents, FILTER_VALIDATE_IP)) { array_push($valid, $contents); } else { echo $contents." is not valid.\n"; } } } } // What have we got? echo count($valid)." IPs detected. ".$type."ing with Cloudflare now...\n"; // Set the listing types $checkVars = array("Whitelist","Blacklist","Unlist"); // Check the listing type and get started if(in_array($type, $checkVars)){ // Run the $url IPs first if (isset($url)) { if (is_array($url)) { foreach ($url as $value) { $cf = new cloudflare_api($cfemailaddress, $cfapikey); if($type == "Whitelist") { $response = $cf->wl($value); } elseif($type == "Blacklist") { $response = $cf->ban($value); } elseif($type == "Unlist") { $response = $cf->nul($value); } print_r($response); } } } else { echo "No URL specified, trying IPs\n"; } // Run the $ips array second if (isset($ips)) { if (is_array($ips)) { foreach ($ips as $value) { $cf = new cloudflare_api($cfemailaddress, $cfapikey); if($type == "Whitelist") { $response = $cf->wl($value); } elseif($type == "Blacklist") { $response = $cf->ban($value); } elseif($type == "Unlist") { $response = $cf->nul($value); } print_r($response); } } } else { echo "No manual IPs specified\n"; } } else { echo "Unknown type, please check configuration\n"; } // Fin echo "Finished\n"; $time_end = microtime(true); $execution_time = ($time_end - $time_start); echo "Script running time:".round($execution_time)." seconds\n";
Thanks for sharing this article, it’s really helped.
Thanks for this. Would it be great to add the optional parameter “notes” to the script, so we’ll know that these are StatusCake rules.
Hi Cristian, thanks for the comment. I’ll look at adding this in the future, it wasn’t available when I created the script.
Great post. Only other addition is it doesn’t seem to handle running repeatedly. It errs out if Cloudflare already has the IP whitelisted.
Considering statuscake adds IPs now and then, it might be good to handle this (so cron can run this) or maybe grab the current whitelist and diff against what statuscake provides. I could try adding something and post back if you’re interested.
Hi Ryan, go for it! I don’t have much time recently to make any modifications, but it wouldn’t be overly difficult to make it query the existing IPs and do a for loop on those, any that aren’t already in there, input them.