返回

使用宝塔面板受到CC攻击后自动开启 Cloudflare 经典的 5 秒盾

项目地址:https://github.com/csh733/autouam_control

原理: 通过检测系统负载(cpu或load)自动开启 Cloudflare UAM 和 challenge(验证码)

宝塔面板计划任务

复制下面的脚本代码,使用前修改以下配置值,放在计划任务的 shell 脚本之中。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#!/bin/bash

# --------------------------使用前修改以下配置值--------------------------

mode="load"
# 两种模式可选,一:load (负载) 二:cpu。建议选 load

challenge="1"
# 是否同时开启验证码质询 设为1即开启。建议开启

keeptime="180"
# ≈开盾最小时间,如60 则开盾60秒内负载降低不会关,60秒后关。建议值 180

interval="1"
# 检测间隔时间,默认0.5秒。建议设为1

email="눈_눈"
# CloudFlare 账号邮箱

api_key="눈_눈"
# CloudFlare API KEY

zone_id="눈_눈"
# 区域ID 在域名的概述页面获取

default_security_level="high"
# 默认安全等级 关闭UAM时将会把安全等级调整为它

check="6"
#自定义开盾阈值(非必需)。load模式建议设为CPU核心数 + 2,如4核则设为6。
#load模式填负载值 如:8  cpu模式填百分数值 如:90

# --------------------------下方无需修改--------------------------

api_url="https://api.cloudflare.com/client/v4/zones/$zone_id/settings/security_level"
# API的地址

api_url1="https://api.cloudflare.com/client/v4/zones/$zone_id/firewall/rules"
# API的地址之二

api_url2="https://api.cloudflare.com/client/v4/zones/$zone_id/filters"
# API的地址之三

# 安装依赖
if ! which jq &> /dev/null; then
    echo "jq not found!"
    if [[ -f "/usr/bin/apt-get" ]]; then
        apt-get install -y jq
    elif [[ -f "/usr/bin/dnf" ]]; then
        dnf install -y epel-release
        dnf install -y jq
    elif [[ -f "/usr/bin/yum" ]]; then
        yum install -y epel-release
        yum install -y jq
    fi
fi

for ((;;)); do
    if [[ "$mode" == "cpu" ]]; then
        check=${check:-90}
        #系统空闲时间
        TIME_INTERVAL=5
        time=$(date "+%Y-%m-%d %H:%M:%S")
        LAST_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
        LAST_SYS_IDLE=$(echo $LAST_CPU_INFO | awk '{print $4}')
        LAST_TOTAL_CPU_T=$(echo $LAST_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')
        sleep ${TIME_INTERVAL}
        NEXT_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
        NEXT_SYS_IDLE=$(echo $NEXT_CPU_INFO | awk '{print $4}')
        NEXT_TOTAL_CPU_T=$(echo $NEXT_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')

        #系统空闲时间
        SYSTEM_IDLE=$(echo ${NEXT_SYS_IDLE} ${LAST_SYS_IDLE} | awk '{print $1-$2}')
        #CPU总时间
        TOTAL_TIME=$(echo ${NEXT_TOTAL_CPU_T} ${LAST_TOTAL_CPU_T} | awk '{print $1-$2}')
        load=$(echo ${SYSTEM_IDLE} ${TOTAL_TIME} | awk '{printf "%.2f", 100-$1/$2*100}')
    else
        load=$(cat /proc/loadavg | colrm 5)
        check=${check:-$(cat /proc/cpuinfo | grep "processor" | wc -l)}
    fi

    if [[ ! -f "status.txt" ]]; then
        echo "" > status.txt
    else
        status=$(cat status.txt)
    fi

    if [[ -f "ruleid.txt" ]]; then
        ruleid=$(cat ruleid.txt)
    fi

    if [[ -f "filterid.txt" ]]; then
        filterid=$(cat filterid.txt)
    fi

    now=$(date +%s)
    time=$(date +%s -r status.txt)

    echo "当前$mode负载:$load"
    if [[ $status -eq 1 ]]; then
        echo "UAM ON!"
        if [[ "$challenge" -eq 1 ]]; then
            echo "Challenge ON!"
        fi
    else
        echo "UAM OFF!"
        if [[ "$challenge" -eq 1 ]]; then
            echo "Challenge OFF!"
        fi
    fi

    newtime=$(expr $now - $time)
    closetime=$(expr $keeptime - $newtime)

    if [[ $(awk 'BEGIN {print ('$load'<'$check') ? 1:0}') -eq 1 ]] && [[ $status -eq 1 ]] && [[ $newtime -gt $keeptime ]]; then
        echo -e "\n$mode负载低于$check,当前已开盾超过规定时间$newtime秒,尝试调整至默认安全等级($default_security_level)"
        # Disable Under Attack Mode
        result=$(curl -X PATCH "$api_url" \
            -H "X-Auth-Email: $email" \
            -H "X-Auth-Key: $api_key" \
            -H "Content-Type: application/json" \
            --data "{
                \"value\": \"$default_security_level\"
            }" --silent \
        | jq -r '.success')
        if [[ "$result" = "true" ]]; then
            echo 0 > status.txt
            echo -e "\n成功"
        fi
        if [[ "$challenge" -eq 1 ]]; then
            result=$(curl -X DELETE "$api_url1/$ruleid" \
                -H "X-Auth-Email: $email" \
                -H "X-Auth-Key: $api_key" \
                -H "Content-Type: application/json" \
                --silent)
            result1=$(curl -X DELETE "$api_url2/$filterid" \
                -H "X-Auth-Email: $email" \
                -H "X-Auth-Key: $api_key" \
                -H "Content-Type: application/json" \
                --silent)
            if echo $result | jq -e '.success' && echo $result1 | jq -e '.success'; then
                echo -e "\n验证码关闭成功"
            fi
        fi
    elif [[ $(awk 'BEGIN {print ('$load'<'$check') ? 1:0}') -eq 1 ]]; then
        echo -e "\n$mode负载低于$check,不做任何改变,状态持续了$newtime秒"
        if [[ $status -eq 1 ]]; then
            echo -e "将于$closetime秒后调整安全等级至$default_security_level"
        fi
    elif [[ $(awk 'BEGIN {print ('$load'>'$check') ? 1:0}') -eq 1 ]] && [[ $status -eq 1 ]] && [[ $newtime -gt $keeptime ]]; then
        echo -e "\n$mode负载高于$check,当前已开启UAM超过$keeptime秒,UAM无效"
    elif [[ $(awk 'BEGIN {print ('$load'>'$check') ? 1:0}') -eq 1 ]] && [[ $status -eq 1 ]]; then
        echo -e "\n$mode负载高于$check,当前已开启($newtime秒),请再观察"
    elif [[ $(awk 'BEGIN {print ('$load'>'$check') ? 1:0}') -eq 1 ]]; then
        echo -e "\n$mode负载高于$check,开启UAM"
        # Enable Under Attack Mode
        result=$(curl -X PATCH "$api_url" \
            -H "X-Auth-Email: $email" \
            -H "X-Auth-Key: $api_key" \
            -H "Content-Type: application/json" \
                --data "{
                    \"value\": \"under_attack\"
                }" --silent \
        | jq -r '.success')
        if [[ "$result" = "true" ]]; then
            echo 1 > status.txt
            echo -e "\n成功"
        fi
        if [[ "$challenge" -eq 1 ]]; then
            while :; do
                result=$(curl -X POST "$api_url2" \
                    -H "X-Auth-Email: $email" \
                    -H "X-Auth-Key: $api_key" \
                    -H "Content-Type: application/json" \
                    --data '[{
                        "expression": "(not cf.client.bot)"
                    }]' --silent)
                if echo $result | jq -e '.success'; then
                    filterid=$(echo $result | jq -r '.result[].id')
                else
                    filterid=$(echo $result | jq -r '.errors[].meta.id')
                    for i in $filterid; do
                        result1=$(curl -X DELETE "$api_url2/$i" \
                            -H "X-Auth-Email: $email" \
                            -H "X-Auth-Key: $api_key" \
                            -H "Content-Type: application/json" --silent)
                    done
                    if echo $result1 | jq -e '.success'; then
                        echo "\n冲突的filter删除成功"
                    fi
                fi
                echo $result | jq -e '.success' && break
            done
            result=$(curl -X POST "$api_url1" \
                -H "X-Auth-Email: $email" \
                -H "X-Auth-Key: $api_key" \
                -H "Content-Type: application/json" \
                --data "[{
                    \"action\": \"challenge\",
                    \"filter\": {
                        \"id\": \"$filterid\",
                        \"expression\": \"(not cf.client.bot)\"
                    }
                }]" --silent)
            if echo $result | jq -e '.success'; then
                ruleid=$(echo $result | jq -r '.result[].id')
                echo "$filterid" > filterid.txt
                echo "$ruleid" > ruleid.txt
                echo -e "验证码开启成功,规则id:$ruleid"
            fi
        fi
    else
        echo 0 > status.txt
    fi
    sleep $interval
    clear
done
Licensed under CC BY-NC-SA 4.0
最后更新于 Jul 09, 2023 19:21 UTC
使用 Hugo 构建
主题 StackJimmy 设计