<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://briansnelson.com/index.php?action=history&amp;feed=atom&amp;title=Bash_Script_to_Enable_Under-Attack_in_Cloudflare</id>
		<title>Bash Script to Enable Under-Attack in Cloudflare - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://briansnelson.com/index.php?action=history&amp;feed=atom&amp;title=Bash_Script_to_Enable_Under-Attack_in_Cloudflare"/>
		<link rel="alternate" type="text/html" href="https://briansnelson.com/index.php?title=Bash_Script_to_Enable_Under-Attack_in_Cloudflare&amp;action=history"/>
		<updated>2026-06-04T02:40:59Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.24.1</generator>

	<entry>
		<id>https://briansnelson.com/index.php?title=Bash_Script_to_Enable_Under-Attack_in_Cloudflare&amp;diff=1077&amp;oldid=prev</id>
		<title>Brian: Created page with &quot;==Bash Script to Monitor PHP Process and Enable Under Attack Mode in Cloudflare==  Does your domain hit max_children often due to high attacks from bots/scrapers?  Did you kno...&quot;</title>
		<link rel="alternate" type="text/html" href="https://briansnelson.com/index.php?title=Bash_Script_to_Enable_Under-Attack_in_Cloudflare&amp;diff=1077&amp;oldid=prev"/>
				<updated>2026-03-20T01:36:21Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;quot;==Bash Script to Monitor PHP Process and Enable Under Attack Mode in Cloudflare==  Does your domain hit max_children often due to high attacks from bots/scrapers?  Did you kno...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Bash Script to Monitor PHP Process and Enable Under Attack Mode in Cloudflare==&lt;br /&gt;
&lt;br /&gt;
Does your domain hit max_children often due to high attacks from bots/scrapers?&lt;br /&gt;
&lt;br /&gt;
Did you know you can enable under-attack via the api?&lt;br /&gt;
&lt;br /&gt;
===API Enable Under-Attack Mode via Cloudflare===&lt;br /&gt;
 &lt;br /&gt;
 #!/usr/bin/env bash&lt;br /&gt;
 #&lt;br /&gt;
 # cf-phpfpm-attack-toggle.sh&lt;br /&gt;
 # Toggle Cloudflare Under Attack mode based on PHP-FPM max_children usage.&lt;br /&gt;
 &lt;br /&gt;
 ### CONFIG #########################################################&lt;br /&gt;
 &lt;br /&gt;
 # Cloudflare&lt;br /&gt;
 CF_API_TOKEN=&amp;quot;[Input your API Token]&amp;quot;&lt;br /&gt;
 CF_DOMAIN=&amp;quot;[Input your Domain]&amp;quot;             # your domain&lt;br /&gt;
 CF_NORMAL_LEVEL=&amp;quot;medium&amp;quot;            # normal security level&lt;br /&gt;
 CF_ATTACK_LEVEL=&amp;quot;under_attack&amp;quot;      # attack mode level &lt;br /&gt;
 &lt;br /&gt;
 # PHP-FPM&lt;br /&gt;
 PHP_FPM_POOL_CONF=&amp;quot;[Input Pool Config Location]&amp;quot;  # adjust for your distro&lt;br /&gt;
 PHP_FPM_PROCESS_NAME=&amp;quot;php-fpm&amp;quot;              # e.g. php-fpm, php-fpm82, php-fpm8.2&lt;br /&gt;
 PHP_USER=&amp;quot;[Input your user]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 # Thresholds&lt;br /&gt;
 HIGH_USAGE_PCT=90   # enable Under Attack if &amp;gt;= this % of max_children in use&lt;br /&gt;
 LOW_USAGE_PCT=50    # disable Under Attack if &amp;lt;= this % of max_children in use&lt;br /&gt;
 &lt;br /&gt;
 # State file to avoid flapping&lt;br /&gt;
 STATE_FILE=&amp;quot;/var/run/cf_under_attack.state&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 #################################################################### &lt;br /&gt;
  &lt;br /&gt;
 set -euo pipefail&lt;br /&gt;
 &lt;br /&gt;
 log() {&lt;br /&gt;
   echo &amp;quot;[$(date -Is)] $*&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 get_zone_id() {&lt;br /&gt;
   curl -s -X GET &amp;quot;https://api.cloudflare.com/client/v4/zones?name=${CF_DOMAIN}&amp;quot; \&lt;br /&gt;
    -H &amp;quot;Authorization: Bearer ${CF_API_TOKEN}&amp;quot; \&lt;br /&gt;
    -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  | jq -r '.result[0].id'&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 get_cf_security_level() {&lt;br /&gt;
  local zone_id=&amp;quot;$1&amp;quot;&lt;br /&gt;
  curl -s -X GET &amp;quot;https://api.cloudflare.com/client/v4/zones/${zone_id}/settings/security_level&amp;quot; \&lt;br /&gt;
    -H &amp;quot;Authorization: Bearer ${CF_API_TOKEN}&amp;quot; \&lt;br /&gt;
    -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
  | jq -r '.result.value'&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 set_cf_security_level() {&lt;br /&gt;
   local zone_id=&amp;quot;$1&amp;quot;&lt;br /&gt;
   local level=&amp;quot;$2&amp;quot;&lt;br /&gt;
   curl -s -X PATCH &amp;quot;https://api.cloudflare.com/client/v4/zones/${zone_id}/settings/security_level&amp;quot; \&lt;br /&gt;
     -H &amp;quot;Authorization: Bearer ${CF_API_TOKEN}&amp;quot; \&lt;br /&gt;
     -H &amp;quot;Content-Type: application/json&amp;quot; \&lt;br /&gt;
     --data &amp;quot;{\&amp;quot;value\&amp;quot;:\&amp;quot;${level}\&amp;quot;}&amp;quot; \&lt;br /&gt;
   | jq -r '.success'&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 get_max_children() {&lt;br /&gt;
   # reads first pm.max_children in pool conf&lt;br /&gt;
   awk -F'=' '/^[[:space:]]*pm\.max_children[[:space:]]*=/ {gsub(/[[:space:]]/, &amp;quot;&amp;quot;, $2); print $2; exit}' \&lt;br /&gt;
     &amp;quot;${PHP_FPM_POOL_CONF}&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 get_current_children_count() {&lt;br /&gt;
   # count running php-fpm workers (exclude master)&lt;br /&gt;
   #  ps -o cmd= -C &amp;quot;${PHP_FPM_PROCESS_NAME}&amp;quot; 2&amp;gt;/dev/null | grep &amp;quot;sitesent&amp;quot; | wc -l&lt;br /&gt;
   local count&lt;br /&gt;
   count=$(ps -o cmd= -C &amp;quot;${PHP_FPM_PROCESS_NAME}&amp;quot; 2&amp;gt;/dev/null | grep &amp;quot;${PHP_USER}&amp;quot; | wc -l)&lt;br /&gt;
   #Fix for math bug of if no process 0 are active&lt;br /&gt;
    echo $(( count + 1 ))&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 get_state() {&lt;br /&gt;
   if [[ -f &amp;quot;${STATE_FILE}&amp;quot; ]]; then&lt;br /&gt;
     cat &amp;quot;${STATE_FILE}&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
     echo &amp;quot;normal&amp;quot;&lt;br /&gt;
   fi&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 set_state() {&lt;br /&gt;
   echo &amp;quot;$1&amp;quot; &amp;gt; &amp;quot;${STATE_FILE}&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 main() {&lt;br /&gt;
   # Get PHP-FPM usage&lt;br /&gt;
   local max_children&lt;br /&gt;
   max_children=$(get_max_children || echo 0)&lt;br /&gt;
   if [[ &amp;quot;${max_children}&amp;quot; -le 0 ]]; then&lt;br /&gt;
     log &amp;quot;ERROR: Could not determine pm.max_children from ${PHP_FPM_POOL_CONF}&amp;quot;&lt;br /&gt;
     exit 1&lt;br /&gt;
   fi&lt;br /&gt;
 &lt;br /&gt;
 local current_children&lt;br /&gt;
 current_children=$(get_current_children_count) &lt;br /&gt;
 &lt;br /&gt;
   local usage_pct&lt;br /&gt;
   usage_pct=$(( current_children * 100 / max_children )) &lt;br /&gt;
 &lt;br /&gt;
   log &amp;quot;PHP-FPM: ${current_children}/${max_children} children (${usage_pct}%)&amp;quot; &lt;br /&gt;
 &lt;br /&gt;
   # Get Cloudflare zone and current level&lt;br /&gt;
   local zone_id&lt;br /&gt;
   zone_id=$(get_zone_id)&lt;br /&gt;
   if [[ -z &amp;quot;${zone_id}&amp;quot; || &amp;quot;${zone_id}&amp;quot; == &amp;quot;null&amp;quot; ]]; then&lt;br /&gt;
     log &amp;quot;ERROR: Unable to determine Cloudflare zone ID for ${CF_DOMAIN}&amp;quot;&lt;br /&gt;
     exit 1&lt;br /&gt;
   fi&lt;br /&gt;
 &lt;br /&gt;
   local current_level&lt;br /&gt;
   current_level=$(get_cf_security_level &amp;quot;${zone_id}&amp;quot;)&lt;br /&gt;
   log &amp;quot;Cloudflare security level: ${current_level}&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
   local state&lt;br /&gt;
   state=$(get_state)&lt;br /&gt;
   log &amp;quot;Current state flag: ${state}&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
   # Logic:&lt;br /&gt;
   # - If usage &amp;gt;= HIGH_USAGE_PCT and not already under attack -&amp;gt; enable&lt;br /&gt;
   # - If usage &amp;lt;= LOW_USAGE_PCT and currently under attack      -&amp;gt; disable &lt;br /&gt;
 &lt;br /&gt;
   if (( usage_pct &amp;gt;= HIGH_USAGE_PCT )) &amp;amp;&amp;amp; [[ &amp;quot;${state}&amp;quot; != &amp;quot;attack&amp;quot; ]]; then&lt;br /&gt;
     log &amp;quot;High PHP-FPM usage (&amp;gt;= ${HIGH_USAGE_PCT}%). Enabling Under Attack mode...&amp;quot;&lt;br /&gt;
     if [[ &amp;quot;${current_level}&amp;quot; != &amp;quot;${CF_ATTACK_LEVEL}&amp;quot; ]]; then&lt;br /&gt;
       local ok&lt;br /&gt;
       ok=$(set_cf_security_level &amp;quot;${zone_id}&amp;quot; &amp;quot;${CF_ATTACK_LEVEL}&amp;quot;)&lt;br /&gt;
       if [[ &amp;quot;${ok}&amp;quot; == &amp;quot;true&amp;quot; ]]; then&lt;br /&gt;
         log &amp;quot;Cloudflare set to ${CF_ATTACK_LEVEL}&amp;quot;&lt;br /&gt;
         set_state &amp;quot;attack&amp;quot;&lt;br /&gt;
       else&lt;br /&gt;
         log &amp;quot;ERROR: Failed to enable Under Attack mode&amp;quot;&lt;br /&gt;
       fi&lt;br /&gt;
     else&lt;br /&gt;
       log &amp;quot;Cloudflare already in ${CF_ATTACK_LEVEL} level.&amp;quot;&lt;br /&gt;
       set_state &amp;quot;attack&amp;quot;&lt;br /&gt;
     fi&lt;br /&gt;
 &lt;br /&gt;
   elif (( usage_pct &amp;lt;= LOW_USAGE_PCT )) &amp;amp;&amp;amp; [[ &amp;quot;${state}&amp;quot; == &amp;quot;attack&amp;quot; ]]; then&lt;br /&gt;
     log &amp;quot;PHP-FPM usage low (&amp;lt;= ${LOW_USAGE_PCT}%). Disabling Under Attack mode...&amp;quot;&lt;br /&gt;
     if [[ &amp;quot;${current_level}&amp;quot; != &amp;quot;${CF_NORMAL_LEVEL}&amp;quot; ]]; then&lt;br /&gt;
       local ok&lt;br /&gt;
       ok=$(set_cf_security_level &amp;quot;${zone_id}&amp;quot; &amp;quot;${CF_NORMAL_LEVEL}&amp;quot;)&lt;br /&gt;
       if [[ &amp;quot;${ok}&amp;quot; == &amp;quot;true&amp;quot; ]]; then&lt;br /&gt;
         log &amp;quot;Cloudflare set to ${CF_NORMAL_LEVEL}&amp;quot;&lt;br /&gt;
         set_state &amp;quot;normal&amp;quot;&lt;br /&gt;
       else&lt;br /&gt;
         log &amp;quot;ERROR: Failed to disable Under Attack mode&amp;quot;&lt;br /&gt;
       fi&lt;br /&gt;
     else&lt;br /&gt;
       log &amp;quot;Cloudflare already at normal level (${CF_NORMAL_LEVEL}).&amp;quot;&lt;br /&gt;
       set_state &amp;quot;normal&amp;quot;&lt;br /&gt;
     fi &lt;br /&gt;
 &lt;br /&gt;
   else&lt;br /&gt;
     log &amp;quot;No change to Cloudflare mode (usage: ${usage_pct}%, state: ${state}).&amp;quot;&lt;br /&gt;
   fi&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 main &amp;quot;$@&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Setup Cron to Auto Enable/Disable Under-Attack Mode in Cloudflare===&lt;br /&gt;
&lt;br /&gt;
Now set it up to run every minute &lt;br /&gt;
&lt;br /&gt;
 * * * * * bash /path/to/script/cf-phpfpm-attack-toggle.sh &amp;gt;&amp;gt; /var/log/cf-under-attack.log&lt;br /&gt;
&lt;br /&gt;
Now when your site gets heavy traffic it will auto enable under-attack mode.&lt;br /&gt;
&lt;br /&gt;
===How to setup the API Key in Cloudflare===&lt;br /&gt;
&lt;br /&gt;
To generate the API key in cloudflare, you will need to go to&lt;br /&gt;
&lt;br /&gt;
'''Manage Account -&amp;gt; Account API Tokens -&amp;gt; Create Token&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
Make sure to select '''Zone -&amp;gt; Zone Settings both (Edit/Read)&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
Those are the only settings this API token needs&lt;/div&gt;</summary>
		<author><name>Brian</name></author>	</entry>

	</feed>