Automação do Modo de Ataque da CloudFlare

Olá discourse..

Há alguns dias meu pequeno servidor sofreu um ataque DDoS.
Mesmo que possa ser proxy pelo CF, alguns ataques ainda conseguem penetrar no servidor. até que o servidor atinja leituras de CPU de 60% a 80%..
e isso pode ser evitado ativando o “Modo Sob Ataque”
às vezes também me distraio para entrar no CF, que é apenas para ativar manualmente o “Modo Sob Ataque”

depois de pesquisar no Google, descobri que existem vários artigos que dizem que o Modo Sob Ataque automático é baseado na leitura da CPU.

CF AUTO

#!/bin/bash
# Cloudflare Auto Under Attack Mode = CF Auto UAM
# version 0.99beta

# Security Level Enums
SL_OFF=0
SL_ESSENTIALLY_OFF=1
SL_LOW=2
SL_MEDIUM=3
SL_HIGH=4
SL_UNDER_ATTACK=5

# Security Level Strings
SL_OFF_S="off"
SL_ESSENTIALLY_OFF_S="essentially_off"
SL_LOW_S="low"
SL_MEDIUM_S="medium"
SL_HIGH_S="high"
SL_UNDER_ATTACK_S="under_attack"

#config
debug_mode=0 # 1 = true, 0 = false, adiciona mais logs e permite editar variáveis para testar o script
install_parent_path="/home"
cf_email=""
cf_apikey=""
cf_zoneid=""
upper_cpu_limit=35 # 10 = 10% de carga, 20 = 20% de carga. Carga total, levando em conta o número de núcleos
lower_cpu_limit=5
regular_status=$SL_HIGH
regular_status_s=$SL_HIGH_S
time_limit_before_revert=$((60 * 5)) # 5 minutos por padrão
#end config

# Functions

install() {
  mkdir $install_parent_path"/cfautouam" >/dev/null

  cat >$install_parent_path"/cfautouam/cfautouam.service" <<EOF
[Unit]
Description=Automate Cloudflare Under Attack Mode
[Service]
ExecStart=$install_parent_path/cfautouam/cfautouam.sh
EOF

  cat >$install_parent_path"/cfautouam/cfautouam.timer" <<EOF
[Unit]
Description=Automate Cloudflare Under Attack Mode
[Timer]
OnBootSec=60
OnUnitActiveSec=5
AccuracySec=1
[Install]
WantedBy=timers.target
EOF

  chmod +x $install_parent_path"/cfautouam/cfautouam.service"
  systemctl enable $install_parent_path"/cfautouam/cfautouam.timer"
  systemctl enable $install_parent_path"/cfautouam/cfautouam.service"
  systemctl start cfautouam.timer
  echo "$(date) - cfautouam - Installed" >>$install_parent_path"/cfautouam/cfautouam.log"
  exit
}

uninstall() {
  systemctl stop cfautouam.timer
  systemctl stop cfautouam.service
  systemctl disable cfautouam.timer
  systemctl disable cfautouam.service
  rm $install_parent_path"/cfautouam/cfstatus" >/dev/null
  rm $install_parent_path"/cfautouam/uamdisabledtime" >/dev/null
  rm $install_parent_path"/cfautouam/uamenabledtime" >/dev/null
  rm $install_parent_path"/cfautouam/cfautouam.timer"
  rm $install_parent_path"/cfautouam/cfautouam.service"
  echo "$(date) - cfautouam - Uninstalled" >>$install_parent_path"/cfautouam/cfautouam.log"
  exit
}

disable_uam() {
  curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$cf_zoneid/settings/security_level" \
    -H "X-Auth-Email: $cf_email" \
    -H "X-Auth-Key: $cf_apikey" \
    -H "Content-Type: application/json" \
    --data "{\"value\":\"$regular_status_s\"}" >/dev/null

  # log time
  date +%s >$install_parent_path"/cfautouam/uamdisabledtime"

  echo "$(date) - cfautouam - CPU Load: $curr_load - Disabled UAM" >>$install_parent_path"/cfautouam/cfautouam.log"
}

enable_uam() {
  curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$cf_zoneid/settings/security_level" \
    -H "X-Auth-Email: $cf_email" \
    -H "X-Auth-Key: $cf_apikey" \
    -H "Content-Type: application/json" \
    --data '{"value":"under_attack"}' >/dev/null

  # log time
  date +%s >$install_parent_path"/cfautouam/uamenabledtime"

  echo "$(date) - cfautouam - CPU Load: $curr_load - Enabled UAM" >>$install_parent_path"/cfautouam/cfautouam.log"
}

get_current_load() {
  currload=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\\([0-9.]*\\)%* id.*/\\1/" | awk '{print 100 - $1}')
  currload=$(echo "$currload/1" | bc)
  return $currload
}

get_security_level() {
  curl -X GET "https://api.cloudflare.com/client/v4/zones/$cf_zoneid/settings/security_level" \
    -H "X-Auth-Email: $cf_email" \
    -H "X-Auth-Key: $cf_apikey" \
    -H "Content-Type: application/json" 2>/dev/null |
    awk -F":" '{ print $4 }' | awk -F"," '{ print $1 }' | tr -d '"' >$install_parent_path"/cfautouam/cfstatus"

  security_level=$(cat $install_parent_path"/cfautouam/cfstatus")

  case $security_level in
  "off")
    return $SL_OFF
    ;;
  "essentially_off")
    return $SL_ESSENTIALLY_OFF
    ;;
  "low")
    return $SL_LOW
    ;;
  "medium")
    return $SL_MEDIUM
    ;;
  "high")
    return $SL_HIGH
    ;;
  "under_attack")
    return $SL_UNDER_ATTACK
    ;;
  *)
    return 100 # error
    ;;
  esac
}

main() {
  # Get current protection level & load
  get_security_level
  curr_security_level=$?
  get_current_load
  curr_load=$?

  if [ $debug_mode == 1 ]; then
    debug_mode=1 # random inconsequential line needed to hide a dumb shellcheck error
	#edit vars here to debug the script
    #curr_load=5
    #time_limit_before_revert=15
  fi

  # If UAM was recently enabled

  if [[ $curr_security_level == "$SL_UNDER_ATTACK" ]]; then
    uam_enabled_time=$(<"$install_parent_path/cfautouam/uamenabledtime")
    currenttime=$(date +%s)
    timediff=$((currenttime - uam_enabled_time))

    # If time limit has not passed do nothing
    if [[ $timediff -lt $time_limit_before_revert ]]; then
        if [ $debug_mode == 1 ]; then
          echo "$(date) - cfautouam - CPU Load: $curr_load - time limit has not passed regardless of CPU - do nothing" >>$install_parent_path"/cfautouam/cfautouam.log"
        fi
        exit
    fi

    # If time limit has passed & cpu load has normalized, then disable UAM
    if [[ $timediff -gt $time_limit_before_revert && $curr_load -lt $lower_cpu_limit ]]; then
        if [ $debug_mode == 1 ]; then
          echo "$(date) - cfautouam - CPU Load: $curr_load - time limit has passed - CPU Below threshhold" >>$install_parent_path"/cfautouam/cfautouam.log"
        fi
        disable_uam
        exit
    fi

    # If time limit has passed & cpu load has not normalized, wait
    if [[ $timediff -gt $time_limit_before_revert && $curr_load -gt $lower_cpu_limit ]]; then
      if [ $debug_mode == 1 ]; then
        echo "$(date) - cfautouam - CPU Load: $curr_load - time limit has passed but CPU above threshhold, waiting out time limit" >>$install_parent_path"/cfautouam/cfautouam.log"
      fi
    fi
    exit
  fi

  # If UAM is not enabled, continue

  # Enable and Disable UAM based on load

  #if load is higher than limit
  if [[ $curr_load -gt $upper_cpu_limit && $curr_security_level == "$regular_status" ]]; then
    enable_uam
  #else if load is lower than limit
  elif [[ $curr_load -lt $lower_cpu_limit && $curr_security_level == "$SL_UNDER_ATTACK" ]]; then
    disable_uam
  else
    if [ $debug_mode == 1 ]; then
      echo "$(date) - cfautouam - CPU Load: $curr_load - no change necessary" >>$install_parent_path"/cfautouam/cfautouam.log"
    fi
  fi
}

# End Functions

# Main -> command line arguments

if [ "$1" = '-install' ]; then
  install
  echo "$(date) - cfautouam - Installed" >>$install_parent_path"/cfautouam/cfautouam.log"
  exit
elif [ "$1" = '-uninstall' ]; then
  uninstall
  echo "$(date) - cfautouam - Uninstalled" >>$install_parent_path"/cfautouam/cfautouam.log"
  exit
elif [ "$1" = '-enable_uam' ]; then
  echo "$(date) - cfautouam - UAM Manually Enabled" >>$install_parent_path"/cfautouam/cfautouam.log"
  enable_uam
  exit
elif [ "$1" = '-disable_uam' ]; then
  echo "$(date) - cfautouam - UAM Manually Disabled" >>$install_parent_path"/cfautouam/cfautouam.log"
  disable_uam
  exit
elif [ -z "$1" ]; then
  main
  exit
else
  echo "cfautouam - Invalid argument"
  exit
fi

Tentei seguir o que foi explicado, mas não funcionou. Existe outra maneira?

Ter algo que vincule a utilização da CPU à possibilidade de um host estar sendo atacado pode funcionar com sites PHP, mas lembre-se que reconstruções e atualizações consomem muita CPU e provavelmente também acionariam isso…

1 curtida

Sim, isso é muito verdade. Em relação à CPU, sempre que você atualiza e aprimora qualquer coisa sobre o Discourse, sempre obtém uma leitura de CPU muito alta. Não é por isso que é possível atualizar todas as vezes. Talvez você possa parar este script e, após a atualização, executá-lo novamente.

Para o primeiro ataque DDoS, preciso que este script esteja em execução no meu servidor para lidar com o segundo ataque e talvez eu tenha bloqueado imediatamente todos os ASN e seus IPs BOT. Os atacantes de DDoS atualizarão seus ASN e IP, portanto, tenho que encontrar uma maneira de bloquear o ataque surpresa.

Tem certeza de que eles não estão apenas contornando o Cloudflare por meio de um endereço IP vazado?

1 curtida

há alguns amigos do Discourse sugerindo que o servidor só aceita IP em vez de apenas Cloudflare e também há algumas regras no WAF. e eu não acho que serei capaz de fazer login no servidor ou fazer ddos pela segunda vez