@@ -111,9 +111,20 @@ if [[ -z "$1" || -z "$2" || -z "$3" || -z "$4" || -z "$5" ]]; then
111111 exit 1
112112fi
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
115121if [[ ! -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
117128fi
118129
119130# Check runtime dependencies
@@ -127,73 +138,69 @@ if ! command -v jq &>/dev/null; then
127138 exit 1
128139fi
129140
130- # Function to check if the IP is listed on AbuseIPDB
141+ # Check if the IP is listed on AbuseIPDB
131142check_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
197204report_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
231238fi
232239
233- # Report to AbuseIPDB
240+ # Report to AbuseIpdb
234241if [[ " ${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