Cloudflare has upgraded their API to version 4 some while ago.
https://api.cloudflare.com/#user-level-firewall-access-rule-properties
I want to use the new APIs to block IP addresses using fail2ban. Using curl directly is a bit cumbersome, so I created a few php helper scripts. They can also be used in other projects.
Thanks to andrieslouw at github https://gist.github.com/andrieslouw/3c833332cbf66f95ca6751f82013acf5 I didn’t have to reinvent the wheel. He has created the backbones of the php scripts.
I’ve gone a bit further – I added a search where by supplying an IP address and the script can locate the object ID and delete it from the Firewall access list.
I also added some connection time-out and error checkings. They are not 100% nuclear-proof. Maybe you can help enhancing it.
Please note I am using “User Level” rules. On CF there are also Account and Organization level rule so you may need to amend the URL to suit your need.
There are 3 scripts:
- cf_getaccesslist.php – dump the firewall access list in json format. This is good for checking your firewall or for debugging
- cf_blockip.php – block an ip by supplying an ip address as argument
- cf_unblockip.php – unblock an ip by supplying an ip address as argument
Simply amend the $authemail and $authkey in each script and run them in php.
cf_getaccesslist.php
<?php // Obtain a dump of the Cloudflare access list in json format // Usage: // php cf_getaccesslist.php // Defining variables $authemail = "[email protected]"; $authkey = "YOUR-CLOUDFLARE-API-KEY"; $apiurl = "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules"; $httphead = array( 'X-Auth-Email: '.$authemail, 'X-Auth-Key: '.$authkey, 'Content-Type: application/json' ); //------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ function getaccesslist() { global $httphead,$apiurl; $data = array( 'match'=>'all', 'order'=>'mode', 'direction'=>'desc', ); // Build query string $qrydata = http_build_query($data); // https://stackoverflow.com/questions/2138527/php-curl-http-post-sample-code $ch = curl_init(); // We setup a http GET by the CURLOPT_URL option and provide an URL curl_setopt($ch, CURLOPT_URL, $apiurl."?".$qrydata); curl_setopt($ch, CURLOPT_HTTPHEADER, $httphead); //Tell cURL that it should only spend 5 seconds //trying to connect to the URL in question. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //A given cURL operation should only take 5 seconds max. curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Tell cURL to return the response output as a string. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // OK - go ahead and run curl $response = curl_exec($ch); curl_close($ch); // Debug response echo $response; // if you wish to process the output further, // the following line converts the json response into an associative array $r = json_decode($response, true); } //------------------------------------------------------------------------------------------ getaccesslist(); ?>
cf_blockip.php
<?php // Blocking an IP address on Cloudflare's firewall access rule // Usage: // cf_blockip.php [ipv4address] // e.g. php cf_unblock.php 192.168.10.200 // If successful it will return a status message //--------------------------------------------------------------------------------------- $authemail = "[email protected]"; $authkey = "YOUR-CLOUDFLARE-API-KEY"; $apiurl = "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules"; $httphead = array( 'X-Auth-Email: '.$authemail, 'X-Auth-Key: '.$authkey, 'Content-Type: application/json' ); //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- function cf_blockip($ipaddress) { global $httphead, $apiurl; $config = array( 'target'=>'ip', 'value'=>$ipaddress ); $data = array( 'mode'=>'block', 'configuration'=>$config, 'notes'=>'This is a block rule created by API4' ); $postdata = json_encode($data); //echo $postdata . "\r\n"; // https://stackoverflow.com/questions/2138527/php-curl-http-post-sample-code // initialise curl $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiurl); curl_setopt($ch, CURLOPT_HTTPHEADER, $httphead); // We setup a http POST, and provide %postdata curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata); //Tell cURL that it should only spend 5 seconds //trying to connect to the URL in question. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //A given cURL operation should only take //5 seconds max. curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Tell cURL to return the response output as a string. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // OK - go ahead and run curl $response = curl_exec($ch); curl_close($ch); // Uncomment the following line to see $response // echo $response; // convert $response to an associative array and place into $r $r = json_decode($response, true); // $r['success'] holds a boolean value - which is unprintable // We will force the output of the boolean value using ? operator echo "Block status on IP " . $ipaddress ." : " . ($r['success'] ? 'True' : 'False'); if ($r['success'] == False ) { echo " : ERROR : " . $r['errors'][0]['message']; } echo "\r\n"; } //--------------------------------------------------------------------------------------- // Getting IP input from argument $ip = $argv[1]; // call the function to block the ip cf_blockip($ip); ?>
cf_unblockip.php
<?php // Deleting an access rule on Cloudflare based on an IP address // Usage: // cf_unblockip.php [ipv4address] // e.g. php cf_unblock.php 192.168.10.200 // If successful it will return the ID of the CF access rule // Defining variables $authemail = "[email protected]"; $authkey = "YOUR-CLOUDFLARE-API-KEY"; $apiurl = "https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules"; $httphead = array( 'X-Auth-Email: '.$authemail, 'X-Auth-Key: '.$authkey, 'Content-Type: application/json' ); //------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ function cfunban($block_rule_id){ // https://gist.github.com/andrieslouw/3c833332cbf66f95ca6751f82013acf5 global $httphead,$apiurl; $ch = curl_init(); // We setup a special, http DELETE action curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); curl_setopt($ch, CURLOPT_URL, $apiurl. "/". $block_rule_id); curl_setopt($ch, CURLOPT_HTTPHEADER, $httphead); //Tell cURL that it should only spend 10 seconds //trying to connect to the URL in question. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //A given cURL operation should only take //30 seconds max. curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Tell cURL to return the response output as a string. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // OK - go ahead and run curl $return = curl_exec($ch); curl_close($ch); if ($return === false){ return false; }else{ $return = json_decode($return,true); if(isset($return['success']) && $return['success'] == true){ return $return['result']['id']; }else{ return false; } } } //------------------------------------------------------------------------------------------ function getcfid($ipaddress) { global $httphead,$apiurl; $data = array( //'mode'=>'block', 'configuration.target'=>'ip', 'configuration.value'=>$ipaddress, ); // Build query string data $qrydata = http_build_query($data); // https://stackoverflow.com/questions/2138527/php-curl-http-post-sample-code $ch = curl_init(); // We setup a http GET by the CURLOPT_URL option and provide an URL curl_setopt($ch, CURLOPT_URL, $apiurl."?".$qrydata); curl_setopt($ch, CURLOPT_HTTPHEADER, $httphead); //Tell cURL that it should only spend 5 seconds //trying to connect to the URL in question. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); //A given cURL operation should only take //5 seconds max. curl_setopt($ch, CURLOPT_TIMEOUT, 5); //Tell cURL to return the response output as a string. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($ch); curl_close($ch); // Debug response // echo $response; $r = json_decode($response, true); if ($r['result_info']['count'] > 0) { // echo $r['result'][0]['id']; return $r['result'][0]['id']; } else { die ("ERROR: The IP was not found in the list. \r\n"); return False; } } //------------------------------------------------------------------------------------------ // Getting IP input $ip = $argv[1]; // Get the CF ID of the ip in the access list $cfid=getcfid($ip); echo "\r\n"; // Use the $cfid and delete the access rule $result=cfunban($cfid); echo $result; echo "\r\n"; ?>
No Comments Yet