Add/Remove Multiple IPs to Cloudflare’s Blacklist/Whitelist

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";

5 Comments

    • 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

css.php