-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_banned_host
executable file
·270 lines (222 loc) · 9.8 KB
/
check_banned_host
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#!/bin/bash
#By Josef Meile <jmeile@hotmail.com> @ June, 2019
#Checks if a host is present in the blacklist host text file.
#Usage:
# 1) ./check_banned_host -> Here you can interactivelly write the ips you want
# to check, then the script will echo an answer
# 2) ./check_banned_host < blacklisted_hosts.txt --> Here the file
# blacklisted_hosts.txt will be scanned and an answer will be printed
# 3) ./check_banned_host rotate --> the file blacklisted_hosts.txt and
# blacklisted_hosts_full.txt will be rotated. The first file will kept only
# comments, whitelists, and currently banned ips; expired bans will be
# dropped. The second file will be truncated. Copies of both files previous
# to the script execution will be saved on the logs folder.
# 4) ./check_banned_host debug --> It will only print the current whitelists,
# bans, and expirations, but it won't remove expired bans. It is only a way
# of showing current banned ips.
# 5) it will be called from Apache. Here Apache will handle the request
# according to the answer code
#If the script is called without arguments, then it will return the following:
#* If the host is suffixed by: deny, then it will get the banned time. If it
# doesn't have expired yet, then it will return 0 (host is still banned);
# otherwise, it will return 1 (host isn't banned anymore so, checks will be
# done again to make sure that it isn't trying to access forbidden links).
#* If the host is suffixed by allow, then it will return 2 (host was
# whitelisted). On this case, the host will bypass all checks.
#If the host isn't found in the blacklist host file, then 1 will be returned
#and the checks will be done.
#If called with rotate, then the blacklisted_hosts.txt file will be scanned and
#the expired bans will be deleted
#Before using it, you have to setup the excecutable permissions for this file,
#ie: chmod +x check_banned_host
#Path were the apache host scripts are located
APACHE_HOST_TRAP_PATH=/usr/local/ApacheHostTrap
#This is the path where the file blacklisted_hosts.txt is stored
BANNED_HOSTS_BASE_PATH=$APACHE_HOST_TRAP_PATH
#This is the base name of the blacklisted hosts file. Usually you don't need
#to change this
BANNED_HOSTS_BASE_NAME=blacklisted_hosts
#Full path of the blacklisted hosts files. Do not change it
BANNED_HOSTS_PATH=$BANNED_HOSTS_BASE_PATH/$BANNED_HOSTS_BASE_NAME.txt
BANNED_HOSTS_FULL_PATH=$BANNED_HOSTS_BASE_PATH/"$BANNED_HOSTS_BASE_NAME"_full.txt
#Here the backup of the banned host files will be kept
BANNED_HOSTS_BACKUP_BASE_PATH=$APACHE_HOST_TRAP_PATH/logs/banned
#Name of the current banned hosts backup files, do not change them
BANNED_HOSTS_CURRENT_BACKUP=$BANNED_HOSTS_BACKUP_BASE_PATH/"$BANNED_HOSTS_BASE_NAME"_short-$(date +'%Y-%m-%d_%H.%M.%S').bak
BANNED_HOSTS_FULL_CURRENT_BACKUP=$BANNED_HOSTS_BACKUP_BASE_PATH/"$BANNED_HOSTS_BASE_NAME"_full-$(date +'%Y-%m-%d_%H.%M.%S').bak
#Base path for the unbanned log files
BASE_LOG_FILE_PATH=$BANNED_HOSTS_BASE_PATH/logs/unbanned
#Base file name of rotation logs
BASE_LOG_FILE_NAME=rotate
TMP_PATH="/tmp"
#Current log file for this execution
CURRENT_LOG_FILE="$TMP_PATH/$BASE_LOG_FILE_NAME-$(date +'%Y-%m-%d_%H.%M.%S').log"
#Number of logs to keep
LOGS_TO_KEEP=30
#This temporal file will be used while expiring the bans
TMP_FILE=$TMP_PATH/$BANNED_HOSTS_BASE_NAME.txt
#Time in seconds to ban the ip, ie: 86400 will ban the host for one day:
#24 (hours in a day) * 60 (minutes in an hour) * 60 (seconds in a minute)=86400
UNBAN_TIME=86400
#This command must be ran after processing the log files; otherwise, no new
#host will be registered
APACHE_RELOAD_CMD="/usr/sbin/service apache2 reload"
#Command for compressing old logs
ZIP_COMMAND="bzip2 --best"
function log_message(){
#Description: logs the entered message to CURRENT_LOG_FILE
#Parameters:
# $1: message to log
echo "$1" >> $CURRENT_LOG_FILE
}
function check_banned_host(){
#Description: Checks if an ip is present in the blacklisted host text file
#Parameters:
# $1: ip to check
#Returns:
# 0 if the ip is still banned
# 1 if the ip ban time expired or it wasn't present on the text file
# 2 if the ip was whitelisted
#If the Ip is present in the text file, then gets what is suffixing it, which
#can be 'allow' or 'deny ban_time'
local ip_entry=`grep "$1" $BANNED_HOSTS_PATH | cut -f2- -d' '`
local ip_values
validation_passed=1
if [ "$ip_entry" ]; then
#If the ip was found, then it will put the strings suffixing it into an
#array
read -ra ip_values <<< "$ip_entry"
if [ "${ip_values[0]}" == "deny" ] ; then
#If the first value in the array is 'deny', then calculates the banning
#time
local block_expiration=$(( ${ip_values[1]} + $UNBAN_TIME ))
#Gets the current seconds since the epoch
local current_seconds=`date +%s`
#If the banning time doesn't have passed yet, then it keeps it banned
if (( block_expiration > current_seconds )); then
validation_passed=0
fi
else
#It is 'allow', so it means that it is whitelisted
validation_passed=2
fi
fi
}
function expire_banned_host(){
#Description: Expire banned hosts as soon as the UNBAN_TIME has passed
#Parameters:
# $1: entry to check
#Returns:
# If the host is still banned, it is a white list or a comment, then it will
# be echoed to a temporary file
local file_entry_par=$1
local entry_values
echo_line=0
if [[ $file_entry_par =~ ^#.* ]] ; then
#It is a comment
echo_line=1
else
read -ra entry_values <<< "$file_entry_par"
if [[ "${entry_values[1]}" == "allow" ]] ; then
#It is a whitelisted host
echo_line=1
KEPT_IPS=$((KEPT_IPS+1))
elif [[ "${entry_values[1]}" == "deny" ]] ; then
#This host was banned, now checking if banned time has passed
log_message "Host ban was found"
banning_time=${entry_values[2]}
#Gets the banning time and adds the expiration time
local block_expiration=$(( $banning_time + $UNBAN_TIME ))
#Gets the current seconds since the epoch
local current_seconds=`date +%s`
log_message "Host banned at: `date -d @$banning_time`"
log_message "Host ban expiration: `date -d @$block_expiration`"
#If the banning time doesn't have passed yet, then it will be echoed
if (( block_expiration > current_seconds )); then
echo_line=1
KEPT_IPS=$((KEPT_IPS+1))
fi
else
#Other things will be always echoed
echo_line=1
fi
fi
if [[ $echo_line == "1" ]] ; then
#Saves this entry to the temporal file
log_message "Line: $LINE_NO was kept:"
echo "$file_entry_par" >> $TMP_FILE
KEPT_LINES=$((KEPT_LINES+1))
else
#Prints some debug info
log_message "Host in line: $LINE_NO was unbanned:"
DROPPED_IPS=$((DROPPED_IPS+1))
fi
log_message $file_entry_par
}
SCRIPT_ACTION=
if [[ $# == "1" ]] ; then
SCRIPT_ACTION=$1
fi
if [[ $SCRIPT_ACTION == "rotate" || $SCRIPT_ACTION == "debug" ]] ; then
log_message "*******************************************************************************"
log_message "Current date: `date`"
#Human representation of the UNBAN_TIME
UNBAN_TIME_HUMAN=`eval "echo $(date -ud "@$UNBAN_TIME" +'$((%s/3600/24)) days %H hours %M minutes %S seconds')"`
log_message "Unban time: $UNBAN_TIME_HUMAN"
log_message "*******************************************************************************"
> $TMP_FILE
LINE_NO=0
DROPPED_IPS="0"
KEPT_IPS="0"
KEPT_LINES="0"
while read file_entry; do
LINE_NO=$((LINE_NO+1))
expire_banned_host "$file_entry"
done < $BANNED_HOSTS_PATH
log_message "*******************************************************************************"
log_message "Processed: $LINE_NO lines"
log_message "Kept $KEPT_LINES lines, from which $KEPT_IPS were whitelists or banned ips"
log_message "Dropped: $DROPPED_IPS expired bans"
log_message "Finished at: `date`"
log_message "*******************************************************************************"
if [[ $SCRIPT_ACTION == "rotate" ]] ; then
#Zips the bakup file before moving the current backup
$ZIP_COMMAND $BANNED_HOSTS_BACKUP_BASE_PATH/"$BANNED_HOSTS_BASE_NAME"*.bak
#If there are more than LOGS_TO_KEEP short logs, then remove the rest
log_rotate_cmd="ls -1tr $BANNED_HOSTS_BACKUP_BASE_PATH/\"$BANNED_HOSTS_BASE_NAME\"_short*.bak.* | head -n -$LOGS_TO_KEEP | xargs -d '\n' rm -f --"
eval $log_rotate_cmd
#If there are more than LOGS_TO_KEEP full logs, then remove the rest
log_rotate_cmd="ls -1tr $BANNED_HOSTS_BACKUP_BASE_PATH/\"$BANNED_HOSTS_BASE_NAME\"_full*.bak.* | head -n -$LOGS_TO_KEEP | xargs -d '\n' rm -f --"
eval $log_rotate_cmd
#Copies the current backup files
mv $BANNED_HOSTS_PATH $BANNED_HOSTS_CURRENT_BACKUP
mv $BANNED_HOSTS_FULL_PATH $BANNED_HOSTS_FULL_CURRENT_BACKUP
#Copies the new banned host file without the unbanned hosts
mv $TMP_FILE $BANNED_HOSTS_PATH
#Recreates the full log file
touch $BANNED_HOSTS_FULL_PATH
#Reloads apache configuration
$APACHE_RELOAD_CMD
#Zips the log files
$ZIP_COMMAND $BASE_LOG_FILE_PATH/*.log
#If there are more than LOGS_TO_KEEP logs, then remove the rest
log_rotate_cmd="ls -1tr $BASE_LOG_FILE_PATH/*.log.* | head -n -$LOGS_TO_KEEP | xargs -d '\n' rm -f --"
eval $log_rotate_cmd
#Moves the current log
mv $CURRENT_LOG_FILE $BASE_LOG_FILE_PATH
else
echo "Finished debugging"
echo "Please check the following files to see the results:"
echo "* $CURRENT_LOG_FILE"
echo "* $TMP_FILE"
echo "You can delete them afterwards by running:"
echo "rm $CURRENT_LOG_FILE $TMP_FILE"
fi
else
#This will keep the function reading ips until the apache server gets stopped or restarted
#or if ran interactively, then until the user press CTRL+C
while read host_ip; do
check_banned_host $host_ip
echo $validation_passed
done
fi