diff --git a/ddos-mitigator.sh b/ddos-mitigator.sh index 63eb120..327c776 100755 --- a/ddos-mitigator.sh +++ b/ddos-mitigator.sh @@ -24,6 +24,7 @@ MY_PORT="443" # After this point, no editing is required. # Define the files that will contain the addresses an subnets. fileraw="raw-http.txt" +filtered="filtered-http.txt" file8="sorted-http-8.txt" file16="sorted-http-16.txt" file24="sorted-http-24.txt" @@ -88,6 +89,14 @@ inquired interactively. ENDOFHELP } +function execAsRoot() { + if [[ $(id -un) == "root" ]] ; then + "$@" + else + sudo "$@" + fi +} + function parseCommandline() { TEMP=$(getopt -o 'a::,j:,n:,h' -l 'auto::,jail:,netmask:,help' -- "$@") @@ -165,6 +174,9 @@ jail="apache-auth" parseCommandline "$@" +# List already banned addresses in the chosen jail +banned="$(execAsRoot fail2ban-client get "${jail}" banip)" + # Determine the current connections to the desired port; store the raw data in # $fileraw. netstat -nt | grep "${MY_IP}:${MY_PORT}" | tr -s '[:blank:]' | cut -d' ' -f5 \ @@ -176,6 +188,29 @@ cut -d. -f1-3 "${fileraw}" | sort | uniq -c | sort -rn > "${file24}" cut -d. -f1-2 "${fileraw}" | sort | uniq -c | sort -rn > "${file16}" cut -d. -f1 "${fileraw}" | sort | uniq -c | sort -rn > "${file8}" +function filter() { + # list of current connections + file="$1" + # subnet extension, e.g. ".0.0/16" + ext="$2" + rm -f "${filtered}" + + # Reject already banned addresses + while read -r -u3 address ; do + if [[ "${banned}" != *"${address}${ext}"* ]] ; then + echo "${address}" >> "${filtered}" + fi + done 3< "${file}" + + mv "${filtered}" "${file}" +} + +# Filter already banned addresses +filter "${file32}" "${ext32}" +filter "${file24}" "${ext24}" +filter "${file16}" "${ext16}" +filter "${file8}" "${ext8}" + # Determine the number of entries per file. nlines32=$(cat "${file32}" | wc -l) nlines24=$(cat "${file24}" | wc -l) @@ -378,12 +413,7 @@ sudo -k # one of them. while read -r addr ; do echo "Banning ${addr} ..." - if [[ $(id -un) == "root" ]] ; then - # Don't use sudo when we're running as root. - fail2ban-client set "${jail}" banip "${addr}" - else - sudo fail2ban-client set "${jail}" banip "${addr}" - fi + execAsRoot fail2ban-client set "${jail}" banip "${addr}" done < "${banlist}" echo -e "${green}All done!${reset}"