A script to quickly create IP Access firewall rules to block requests from all countries

Block All Countries

#!/bin/bash
#
# This script is used to create IP Access rules that will block
# all known countries. The idea would be to then allow certain IP.
# It requires:
#   jq  - to interpret the JSON output from Cloudflare API.
#   curl - to do the actual HTTP requests to the API servers.
################################################################################
#
# Provide your global key and the email address associated with it.
global_key=""
Email=""
#
# Provide the ZoneID. This can be found on the dashboard.
ZoneID=""
#
################################################################################
# !!!!! You should not have to modify anything beyond this point.  !!!!!!
################################################################################
#
# Create a couple arrays. One that holds all the two letter country codes.
# And another that holds all their name. Of course it is important that they are in the same order.
countries_codes=(AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS YE YT ZA ZM ZW T1 XX) countries_names=("Andorra" "United Arab Emirates" "Afghanistan" "Antigua and Barbuda" "Anguilla" "Albania" "Armenia" "Angola" "Antarctica" "Argentina" "American Samoa" "Austria" "Australia" "Aruba" "Åland Islands" "Azerbaijan" "Bosnia and Herzegovina" "Barbados" "Bangladesh" "Belgium" "Burkina Faso" "Bulgaria" "Bahrain" "Burundi" "Benin" "Saint Barthélemy" "Bermuda" "Brunei Darussalam" "Bolivia (Plurinational State of)" "Bonaire; Sint Eustatius and Saba" "Brazil" "Bahamas" "Bhutan" "Bouvet Island" "Botswana" "Belarus" "Belize" "Canada" "Cocos (Keeling) Islands" "Congo, Democratic Republic of the" "Central African Republic" "Congo" "Switzerland" "Côte d'Ivoire" "Cook Islands" "Chile" "Cameroon" "China" "Colombia" "Costa Rica" "Cuba" "Cabo Verde" "Curaçao" "Christmas Island" "Cyprus" "Czechia" "Germany" "Djibouti" "Denmark" "Dominica" "Dominican Republic" "Algeria" "Ecuador" "Estonia" "Egypt" "Western Sahara" "Eritrea" "Spain" "Ethiopia" "Finland" "Fiji" "Falkland Islands (Malvinas)" "Micronesia (Federated States of)" "Faroe Islands" "France" "Gabon" "United Kingdom of Great Britain and Northern Ireland" "Grenada" "Georgia" "French Guiana" "Guernsey" "Ghana" "Gibraltar" "Greenland" "Gambia" "Guinea" "Guadeloupe" "Equatorial Guinea" "Greece" "South Georgia and the South Sandwich Islands" "Guatemala" "Guam" "Guinea-Bissau" "Guyana" "Hong Kong" "Heard Island and McDonald Islands" "Honduras" "Croatia" "Haiti" "Hungary" "Indonesia" "Ireland" "Israel" "Isle of Man" "India" "British Indian Ocean Territory" "Iraq" "Iran (Islamic Republic of)" "Iceland" "Italy" "Jersey" "Jamaica" "Jordan" "Japan" "Kenya" "Kyrgyzstan" "Cambodia" "Kiribati" "Comoros" "Saint Kitts and Nevis" "Korea (Democratic People's Republic of)" "Korea, Republic of" "Kuwait" "Cayman Islands" "Kazakhstan" "Lao People's Democratic Republic" "Lebanon" "Saint Lucia" "Liechtenstein" "Sri Lanka" "Liberia" "Lesotho" "Lithuania" "Luxembourg" "Latvia" "Libya" "Morocco" "Monaco" "Moldova, Republic of" "Montenegro" "Saint Martin (French part)" "Madagascar" "Marshall Islands" "North Macedonia" "Mali" "Myanmar" "Mongolia" "Macao" "Northern Mariana Islands" "Martinique" "Mauritania" "Montserrat" "Malta" "Mauritius" "Maldives" "Malawi" "Mexico" "Malaysia" "Mozambique" "Namibia" "New Caledonia" "Niger" "Norfolk Island" "Nigeria" "Nicaragua" "Netherlands" "Norway" "Nepal" "Nauru" "Niue" "New Zealand" "Oman" "Panama" "Peru" "French Polynesia" "Papua New Guinea" "Philippines" "Pakistan" "Poland" "Saint Pierre and Miquelon" "Pitcairn" "Puerto Rico" "Palestine, State of" "Portugal" "Palau" "Paraguay" "Qatar" "Réunion" "Romania" "Serbia" "Russian Federation" "Rwanda" "Saudi Arabia" "Solomon Islands" "Seychelles" "Sudan" "Sweden" "Singapore" "Saint Helena, Ascension and Tristan da Cunha" "Slovenia" "Svalbard and Jan Mayen" "Slovakia" "Sierra Leone" "San Marino" "Senegal" "Somalia" "Suriname" "South Sudan" "Sao Tome and Principe" "El Salvador" "Sint Maarten (Dutch part)" "Syrian Arab Republic" "Eswatini" "Turks and Caicos Islands" "Chad" "French Southern Territories" "Togo" "Thailand" "Tajikistan" "Tokelau" "Timor-Leste" "Turkmenistan" "Tunisia" "Tonga" "Turkey" "Trinidad and Tobago" "Tuvalu" "Taiwan, Province of China" "Tanzania, United Republic of" "Ukraine" "Uganda" "United States Minor Outlying Islands" "United States of America" "Uruguay" "Uzbekistan" "Holy See" "Saint Vincent and the Grenadines" "Venezuela (Bolivarian Republic of)" "Virgin Islands (British)" "Virgin Islands (U.S.)" "Viet Nam" "Vanuatu" "Wallis and Futuna" "Samoa" "Yemen" "Mayotte" "South Africa" "Zambia" "Zimbabwe" "Tor Network" "Unknown")
#
# Check that jq and curl are available.
if (which jq && which curl) > /dev/null 2>&1; then
  :
else
  echo "You must have jq and curl installed to run this script." 1>&2
  exit 1
fi
#
# Test the input parameters.
if [ -z "$global_key" -o -z "$Email" ]; then
  echo "Error, you must provide both your global key and the email address associated with it." 1>&2
  exit 1
fi
 
if [ -z "$ZoneID" ]; then
  echo "Error, you must provide a ZoneID." 1>&2
  exit 1
fi
#
# Set up a temporary file.
tmp_file=/tmp/block_contries.$$
trap 'rm -f $tmp_file' 0   # This removes the file when the script exits.
#
# Now, loop over all the countries and create the firewall rule.
let i=0
while [ $i -lt ${#countries_codes[*]} ]; do
  echo -n "Creating firewall rule for ${countries_names[$i]}(${countries_codes[$i]}) - "
  curl -sX POST "https://api.cloudflare.com/client/v4/zones/$ZoneID/firewall/access_rules/rules" \
       -H "X-Auth-Key: $global_key" -H "X-Auth-Email: $Email" -H "Content-Type: application/json" \
       -d "{\"mode\":\"block\", \"configuration\":{\"target\":\"country\", \"value\":\"${countries_codes[$i]}\"}, \"notes\":\"${countries_names[$i]}\"}" > $tmp_file
 
  success=$(jq -r .success < $tmp_file)
  if [ "$success" != "true" ]; then
    echo "Failed."
    errors=$(jq -r .errors < $tmp_file)
    messages=$(jq -r .messages < $tmp_file)
 
    if [ ! -z "$errors" ]; then
     echo "$errors"
    fi
 
    if [ ! -z "$messages" ]; then
      echo "$messages"
    fi
    exit 1
  else
    echo "Succeeded."
  fi
 
  let i+=1
done

Remove All IP Access Rules (Note, it will remove all of them, and not just the ones created by the script above, so use at your own risk)

#!/bin/bash
#
# This script is used to remove all IP Access rules.
# It requires:
#   jq  - to interpret the JSON output from Cloudflare API.
#   curl - to do the actual HTTP requests to the API servers.
################################################################################
#
# Provide your global key and the email address associated with it.
global_key=""
Email=""
#
# Provide the ZoneID. This can be found on the dashboard.
ZoneID=""
#
################################################################################
# !!!!! You should not have to modify anything beyond this point.  !!!!!!
################################################################################
#
# Check that jq and curl are available.
if (which jq && which curl) > /dev/null 2>&1; then
  :
else
  echo "You must have jq and curl installed to run this script." 1>&1
  exit 1
fi
#
# Test the input parameters.
if [ -z "$global_key" -o -z "$Email" ]; then
  echo "Error, you most provide both your global key and the email address associated with it." 1>&2
  exit 1
fi
 
if [ -z "$ZoneID" ]; then
  echo "Error, you must provide a ZoneID." 1>&2
  exit 1
fi
#
# Set up a temporary file to confirm status code.
tmp_file=/tmp/block_countries.$$
out_file=/tmp/block_countries_out.$$
trap 'rm -f $tmp_file $out_file' 0    # This will remove the files when the script exits.
#
# First, get the ids of all IP Access rules and put them into the $out_file. You have to get
# all of them first, otherwise, deleting them will change what is being read.
let page=1
let total_pages=99  # This is set to the real value after the first call to the API
while [ "$page" -le "$total_pages" ]; do
  curl -sX GET "https://api.cloudflare.com/client/v4/zones/$ZoneID/firewall/access_rules/rules?page=${page}&per_page=1000" \
         -H "X-Auth-Key: $global_key" -H "X-Auth-Email: $Email" -H "Content-Type: application/json" > $tmp_file
  success=$(jq -r .success < $tmp_file)
  if [ "$success" != "true" ]; then
    errors=$(jq -r .errors < $tmp_file)
    messages=$(jq -r .messages < $tmp_file)
 
    if [ ! -z "$errors" ]; then
     echo "$errors"
    fi
 
    if [ ! -z "$messages" ]; then
      echo "$messages"
    fi
    exit 1
  fi
  total_pages=$(jq -r '.result_info.total_pages' < $tmp_file)
  jq -r '.result[] | .id' < $tmp_file >> $out_file
  let page+=1
done
#
# Now, loop over all rules ids and delete them.
cat $out_file | while read id; do
  echo -n "Deleting rule $id - "
  curl -sX DELETE "https://api.cloudflare.com/client/v4/zones/$ZoneID/firewall/access_rules/rules/$id" \
       -H "X-Auth-Key: $global_key" -H "X-Auth-Email: $Email" -H "Content-Type: application/json" > $tmp_file
 
  success=$(jq -r .success < $tmp_file)
  if [ "$success" != "true" ]; then
    echo "Failed."
    errors=$(jq -r .errors < $tmp_file)
    messages=$(jq -r .messages < $tmp_file)
 
    if [ ! -z "$errors" ]; then
     echo "$errors"
    fi
 
    if [ ! -z "$messages" ]; then
      echo "$messages"
    fi
    exit 1
  else
    echo "Succeeded."
  fi
done

Last updated