# Do not put '#!/bin/bash' here or else the script does not know if it is running under bash or sh logFile="/var/log/secure"; #logFile="/home/macs/Desktop/test.txt"; # Check if the script is NOT running under bash (sed find and replace replaces the first match) if ! [ `ps ch -o %c $$` == 'bash' ] ; then # Not running in bash. Probably launched by crontab user_specified_threshold=3 # This one user_specified_minute=*/2 # This one user_specified_hour=* # This one else # Is running in bash. Ask user to specify parameters. Entered values will replace "This one" values above. while true do echo -n "Specify blocking threshold " read threshold # Check if the specified value is a number if ! [[ "$threshold" =~ ^[0-9]+$ ]] ; then exec >&2; echo "Blocking threshold needs to be a whole number" else # If the specified value is a number, break out of the loop break fi done while true do echo -n "Specify time interval (minutes) " read minute # Check if the specified value is a number if ! [[ "$minute" =~ ^[0-9]+$ ]] ; then exec >&2; echo "Minute needs to be a whole number" else # If the specified value is a number, break out of the loop break fi done # Divide the minute by 60 to see how many hours there are hour=$(expr $minute / 60) # Multiply the number of hours by 60 and have the number of minutes subtract the number of hours to see how many remaining minutes there are minute=$(expr $minute - $(expr $hour \* 60)) if [ "$hour" != "0" ]; then hour='*/'$hour else hour='*' fi if [ "$minute" != "0" ]; then minute='*/'$minute else minute='*' fi # Replace the "This one" values with the values gotten from the user. (write user specified parameter values to file) /bin/sed -i 0,/'.*user_specified_threshold.* # This one'/s@@'user_specified_threshold='"$threshold"' # This one'@ '/home/macs/Desktop/block-ip5.sh' /bin/sed -i 0,/'.*user_specified_minute.* # This one'/s@@'user_specified_minute='"$minute"' # This one'@ '/home/macs/Desktop/block-ip5.sh' /bin/sed -i 0,/'.*user_specified_hour.* # This one'/s@@'user_specified_hour='"$hour"' # This one'@ '/home/macs/Desktop/block-ip5.sh' echo "Script will start running in the next minute" # Add crontab entry to run the script and then remove it right after. This script runs in an infinite loop and we do not want multiple instances of this same script running at the same time. # /var/spool/cron/root crontab -l | { cat; echo "*/1 * * * * /home/macs/Desktop/block-ip5.sh"; } | crontab - crontab -l | { cat; echo "*/1 * * * * /bin/sed -i '/.*block-ip5.sh.*/ d' '/var/spool/cron/root'"; } | crontab - exit fi # Infinite loop to check if there are any IP addresses to block every five seconds while [ 1 -eq 1 ]; do # Below is the the ip blocking algorithm, which requires piping the output five times # 1) Use grep to search the log file for ": Failed password for", "Banned IP address", and "Accepted password for" # 2) if awk finds "Failed" in field 6, get the computer's IP address in field 11 and append it to str with a space between each IP address # if awk finds "Banned" in field 7, the past "Failed" entries for that IP are invalid so find that IP address in str and remove it # if awk finds "Accepted" in field 6, the user has successfully logged in so the past "Failed" entries for that IP are invalid so find that IP address in str and remove it # 3) Split str by the space and print each IP address as a separate variable (required in order to count up the occurances of the same IP address in the next step) # 4) Use awk to count up the occurances of the same IP address and have a for loop go through and print the IP addresses that are above the blocking threshold # 5) Split the string by the space and loop through the IP addresses # Append a "Banned IP address" string to the log file for each IP address # Create a drop rule for the IP address in iptables # Create a crontab event to remove the drop rule from iptables and delete the crontab rule itself after the user specified time interval has passed ipArr=`grep ': Failed password for\|Banned IP address\|Accepted password for' ${logFile} | awk '{ if ($6=="Failed") { str=(str $11 " ") } else if ($7=="Banned") { gsub($10,"",str); } else if ($6=="Accepted") { gsub($11,"",str); } } END { print str }' | awk '{ split($0, a, " "); for(i in a) { print a[i] } }' | awk '{a[$1]++}'"END{for(i in a) { if(a[i] > $user_specified_threshold) { print i } } }" | awk '{ split($0, a, " "); for(i in a) { system(" echo \`date +\"%b %d %H:%M:%S\"\` $(hostname | cut -d. -f1) \`ps ch -o %c $$ \` [$$]: \"Banned IP address "'a[i]'" for "'$user_specified_threshold+1'" consecutive failed password attempts\" >> \"'${logFile}'\" ") system("/sbin/iptables -A INPUT -s "'a[i]'" -j DROP") system("crontab -l | { cat; echo \"\"'${user_specified_minute}'\" \"'${user_specified_hour}'\" * * * /sbin/iptables -D INPUT -s "'a[i]'" -j DROP && /bin/sed -i \"\"\x27\"/.*"'a[i]'".*/ d\"\x27\"\" \"\"\x27\"/var/spool/cron/root\"\x27\"\"\"; } | crontab -") } }'` sleep 5 done