Привет, Discourse..
Несколько дней назад мой небольшой сервер подвергся DDoS-атаке.
Даже несмотря на то, что трафик можно пропускать через Cloudflare (CF), некоторые атаки всё же проникают на сервер. В результате нагрузка на процессор поднимается до 60–80%.
Это можно предотвратить, включив режим «Under Attack Mode».
Иногда я также отвлекаюсь, чтобы зайти в панель CF и вручную включить «Under Attack Mode».
После поиска в Google оказалось, что есть несколько статей, описывающих автоматическое включение режима «Under Attack Mode» на основе нагрузки на процессор.
#!/bin/bash
# Cloudflare Auto Under Attack Mode = CF Auto UAM
# версия 0.99beta
# Перечисления уровней безопасности
SL_OFF=0
SL_ESSENTIALLY_OFF=1
SL_LOW=2
SL_MEDIUM=3
SL_HIGH=4
SL_UNDER_ATTACK=5
# Строки уровней безопасности
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"
# Конфигурация
debug_mode=0 # 1 = true, 0 = false, добавляет больше логов и позволяет редактировать переменные для тестирования скрипта
install_parent_path="/home"
cf_email=""
cf_apikey=""
cf_zoneid=""
upper_cpu_limit=35 # 10 = 10% нагрузки, 20 = 20% нагрузки. Общая нагрузка с учётом количества ядер
lower_cpu_limit=5
regular_status=$SL_HIGH
regular_status_s=$SL_HIGH_S
time_limit_before_revert=$((60 * 5)) # по умолчанию 5 минут
# конец конфигурации
# Функции
install() {
mkdir $install_parent_path"/cfautouam" &>/dev/null
cat >$install_parent_path"/cfautouam/cfautouam.service" <<EOF
[Unit]
Description=Автоматизация режима Cloudflare Under Attack Mode
[Service]
ExecStart=$install_parent_path/cfautouam/cfautouam.sh
EOF
cat >$install_parent_path"/cfautouam/cfautouam.timer" <<EOF
[Unit]
Description=Автоматизация режима 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 - Установлено" >>$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 - Удалено" >>$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
# Запись времени
date +%s >$install_parent_path"/cfautouam/uamdisabledtime"
echo "$(date) - cfautouam - Нагрузка CPU: $curr_load - 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
# Запись времени
date +%s >$install_parent_path"/cfautouam/uamenabledtime"
echo "$(date) - cfautouam - Нагрузка CPU: $curr_load - 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 # ошибка
;;
esac
}
main() {
# Получение текущего уровня защиты и нагрузки
get_security_level
curr_security_level=$?
get_current_load
curr_load=$?
if [ $debug_mode == 1 ]; then
debug_mode=1 # случайная строка, необходимая для скрытия глупой ошибки shellcheck
# редактируйте переменные здесь для отладки скрипта
#curr_load=5
#time_limit_before_revert=15
fi
# Если UAM был недавно включён
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 [[ $timediff -lt $time_limit_before_revert ]]; then
if [ $debug_mode == 1 ]; then
echo "$(date) - cfautouam - Нагрузка CPU: $curr_load - лимит времени не истёк независимо от нагрузки CPU - ничего не делаем" >>$install_parent_path"/cfautouam/cfautouam.log"
fi
exit
fi
# Если лимит времени истёк и нагрузка CPU нормализовалась, отключаем UAM
if [[ $timediff -gt $time_limit_before_revert && $curr_load -lt $lower_cpu_limit ]]; then
if [ $debug_mode == 1 ]; then
echo "$(date) - cfautouam - Нагрузка CPU: $curr_load - лимит времени истёк - нагрузка CPU ниже порога" >>$install_parent_path"/cfautouam/cfautouam.log"
fi
disable_uam
exit
fi
# Если лимит времени истёк, но нагрузка CPU не нормализовалась, ждём
if [[ $timediff -gt $time_limit_before_revert && $curr_load -gt $lower_cpu_limit ]]; then
if [ $debug_mode == 1 ]; then
echo "$(date) - cfautouam - Нагрузка CPU: $curr_load - лимит времени истёк, но нагрузка CPU выше порога, ждём окончания лимита" >>$install_parent_path"/cfautouam/cfautouam.log"
fi
fi
exit
fi
# Если UAM не включён, продолжаем
# Включение и отключение UAM на основе нагрузки
# Если нагрузка выше предела
if [[ $curr_load -gt $upper_cpu_limit && $curr_security_level == "$regular_status" ]]; then
enable_uam
# Иначе, если нагрузка ниже предела
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: $curr_load - изменений не требуется" >>$install_parent_path"/cfautouam/cfautouam.log"
fi
fi
}
# Конец функций
# Main -> аргументы командной строки
if [ "$1" = '-install' ]; then
install
echo "$(date) - cfautouam - Установлено" >>$install_parent_path"/cfautouam/cfautouam.log"
exit
elif [ "$1" = '-uninstall' ]; then
uninstall
echo "$(date) - cfautouam - Удалено" >>$install_parent_path"/cfautouam/cfautouam.log"
exit
elif [ "$1" = '-enable_uam' ]; then
echo "$(date) - cfautouam - UAM включён вручную" >>$install_parent_path"/cfautouam/cfautouam.log"
enable_uam
exit
elif [ "$1" = '-disable_uam' ]; then
echo "$(date) - cfautouam - UAM отключён вручную" >>$install_parent_path"/cfautouam/cfautouam.log"
disable_uam
exit
elif [ -z "$1" ]; then
main
exit
else
echo "cfautouam - Неверный аргумент"
exit
fi
Я попробовал следовать инструкции, но это не сработало… Есть ли другой способ?