Skip to content

Commit 0ea833f

Browse files
authored
Update abuseipdb_fail2ban_actionban.sh
1 parent 549f2d1 commit 0ea833f

File tree

1 file changed

+54
-52
lines changed

1 file changed

+54
-52
lines changed

abuseipdb_fail2ban_actionban.sh

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,20 @@ if [[ -z "$1" || -z "$2" || -z "$3" || -z "$4" || -z "$5" ]]; then
111111
exit 1
112112
fi
113113

114-
# Ensure the reported IP list file exists
114+
# Ensure the directory for the reported IP list exists
115+
REPORTED_IP_DIR=$(dirname "${REPORTED_IP_LIST_FILE}")
116+
if [[ ! -d "${REPORTED_IP_DIR}" ]]; then
117+
mkdir -p "${REPORTED_IP_DIR}" || { log_message "FATAL: Could not create directory ${REPORTED_IP_DIR}"; exit 1; }
118+
fi
119+
120+
# Ensure the reported IP list file exists and is writable
115121
if [[ ! -f "${REPORTED_IP_LIST_FILE}" ]]; then
116-
touch "${REPORTED_IP_LIST_FILE}"
122+
touch "${REPORTED_IP_LIST_FILE}" || { log_message "FATAL: Could not create file ${REPORTED_IP_LIST_FILE}"; exit 1; }
123+
fi
124+
125+
if [[ ! -w "${REPORTED_IP_LIST_FILE}" ]]; then
126+
log_message "FATAL: File ${REPORTED_IP_LIST_FILE} is not writable."
127+
exit 1
117128
fi
118129

119130
# Check runtime dependencies
@@ -127,73 +138,69 @@ if ! command -v jq &>/dev/null; then
127138
exit 1
128139
fi
129140

130-
# Function to check if the IP is listed on AbuseIPDB
141+
# Check if the IP is listed on AbuseIPDB
131142
check_ip_in_abuseipdb() {
132-
local response
133-
local http_status
134-
local body
135-
local exit_code
136-
local total_reports
137-
local error_detail
143+
local response http_status body exit_code total_reports error_detail
144+
local delimiter="HTTP_STATUS:"
138145

139146
# Perform the API call and capture both response and HTTP status
140-
response=$(curl -s -w "HTTPSTATUS:%{http_code}" -G "https://api.abuseipdb.com/api/v2/check" \
147+
response=$(curl -s -w "${delimiter}%{http_code}" -G "https://api.abuseipdb.com/api/v2/check" \
141148
--data-urlencode "ipAddress=${IP}" \
142149
-H "Key: ${APIKEY}" \
143150
-H "Accept: application/json" 2>&1)
144151

145-
exit_code=$?
146-
147-
# Extract the HTTP status code
148-
http_status=$(echo "${response}" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
149-
150-
# Extract the body
151-
body=$(echo "${response}" | sed -e 's/HTTPSTATUS\:.*//g')
152-
153-
# Check if curl encountered a network or other fatal error
154-
if [[ $exit_code -ne 0 ]]; then
155-
log_message "Aborting due to curl failure when checking IP. Exit code: ${exit_code}, Response: ${response}"
152+
if [[ $? -ne 0 ]]; then
153+
log_message "ERROR CHECK: API failure. Response: ${response}"
156154
exit 1
157155
fi
158156

157+
# Separate the HTTP status code from the response body
158+
http_status=$(echo "${response}" | tr -d '\n' | sed -e "s/.*${delimiter}//")
159+
body=$(echo "${response}" | sed -e "s/${delimiter}[0-9]*//")
160+
159161
# Check if the response body is empty
160162
if [[ -z "${body}" ]]; then
161-
log_message "API response was empty when checking IP."
163+
log_message "ERROR CHECK: API response empty."
162164
exit 1
163165
fi
164166

165-
# Validate the JSON response
167+
# Validate that the response is valid JSON
166168
if ! echo "${body}" | jq . >/dev/null 2>&1; then
167-
log_message "API response was malformed when checking IP. Response: ${body}"
169+
log_message "ERROR CHECK: API response malformed. Response: ${body}"
168170
exit 1
169171
fi
170172

171173
# Handle different HTTP status codes
172-
if [[ "${http_status}" -ge 200 && "${http_status}" -lt 300 ]]; then
173-
# Successful HTTP response; now check for API-level errors
174-
if echo "${body}" | jq -e '.errors' >/dev/null 2>&1; then
175-
error_detail=$(echo "${body}" | jq -r '.errors[].detail')
176-
log_message "API returned errors when checking IP. Detail: ${error_detail}"
174+
if [[ "${http_status}" =~ ^[0-9]+$ ]]; then
175+
if [[ "${http_status}" -ge 200 && "${http_status}" -lt 300 ]]; then
176+
# Successful HTTP response; check for API-level errors
177+
if echo "${body}" | jq -e '.errors | length > 0' >/dev/null 2>&1; then
178+
error_detail=$(echo "${body}" | jq -r '.errors[].detail')
179+
log_message "ERROR CHECK: API returned errors. Detail: ${error_detail}"
180+
exit 1
181+
fi
182+
else
183+
# Non-successful HTTP status
184+
log_message "ERROR CHECK: API returned ${http_status}. Response: ${body}"
177185
exit 1
178186
fi
179187
else
180-
# Non-successful HTTP status codes
181-
log_message "API returned HTTP status ${http_status} when checking IP. Response: ${body}"
188+
log_message "ERROR CHECK: HTTP status '${http_status}' is not numeric."
182189
exit 1
183190
fi
184191

185192
# Extract totalReports
186193
total_reports=$(echo "${body}" | jq '.data.totalReports')
187194

188-
# Check the IP listed on AbuseIPDB
195+
# Finally, check the IP listed on AbuseIPDB
189196
if [[ "${total_reports}" -gt 0 ]]; then
190197
return 0 # IP is reported
191198
else
192199
return 1 # IP is not reported
193200
fi
194201
}
195202

196-
# Function to report an IP to AbuseIPDB
203+
# Report to AbuseIpDB
197204
report_ip_to_abuseipdb() {
198205
local response
199206
response=$(curl --fail -s 'https://api.abuseipdb.com/api/v2/report' \
@@ -205,23 +212,23 @@ report_ip_to_abuseipdb() {
205212

206213
# API call fail
207214
if [[ $? -ne 0 ]]; then
208-
log_message "Aborting due to API failure when reporting IP. Response: ${response}"
215+
log_message "ERROR REPORT: API failure. Response: ${response}"
209216
exit 1
210217
else
211-
log_message "Reported IP ${IP} to AbuseIPDB. Local list updated."
218+
log_message "SUCCESS REPORT: Reported IP ${IP} to AbuseIPDB. Local list updated."
212219
fi
213220
}
214221

215-
# Should Ban IP
216-
if grep -q -E "^IP=${IP} L=[0-9\-]+" "${REPORTED_IP_LIST_FILE}"; then
217-
# IP is already reported, check if it's still listed on AbuseIPDB
222+
# Check if IP is already reported and still listed on AbuseIPDB
223+
if grep -q -E "^IP=${IP}[[:space:]]+L=[0-9\-]+" "${REPORTED_IP_LIST_FILE}"; then
224+
# IP found locally, check if it's still listed on AbuseIPDB
218225
if check_ip_in_abuseipdb; then
219226
# IP is still listed on AbuseIPDB, no need to report again
220-
log_message "IP ${IP} has already been reported and remains on AbuseIPDB. No duplicate report made."
227+
log_message "INFO: IP ${IP} has already been reported and remains on AbuseIPDB. No duplicate report made."
221228
shouldBanIP=0
222229
else
223-
# IP is already reported before but not listed on AbuseIPDB, report it again
224-
log_message "IP ${IP} has already been reported but is no longer listed on AbuseIPDB. Reporting it again."
230+
# IP is reported before but not listed on AbuseIPDB, report it again
231+
log_message "INFO: IP ${IP} has already been reported but is no longer listed on AbuseIPDB. Reporting it again."
225232
shouldBanIP=1
226233
is_found_local=1
227234
fi
@@ -230,20 +237,15 @@ else
230237
shouldBanIP=1
231238
fi
232239

233-
# Report to AbuseIPDB
240+
# Report to AbuseIpdb
234241
if [[ "${shouldBanIP}" -eq 1 ]]; then
235242
# Add the new ban entry to local list kindly
236243
if [[ "${is_found_local}" -eq 0 ]]; then
237-
# Open with read/write access
238-
exec 200<> "${REPORTED_IP_LIST_FILE}"
239-
# Lock
240-
flock -x 200
241-
# Write
242-
echo "IP=${IP} L=${BANTIME}" >> "${REPORTED_IP_LIST_FILE}"
243-
# Release the lock (Maybe redundant)
244-
flock -u 200
245-
# Close the file descriptor
246-
exec 200>&-
244+
exec 200<> "${REPORTED_IP_LIST_FILE}" # Open with read/write access
245+
flock -x 200 # Lock
246+
echo "IP=${IP} L=${BANTIME}" >> "${REPORTED_IP_LIST_FILE}" # Write
247+
flock -u 200 # Release the lock
248+
exec 200>&- # Close the file descriptor
247249
fi
248250

249251
# Report IP

0 commit comments

Comments
 (0)