diff --git a/ddos-mitigator.sh b/ddos-mitigator.sh index d3517f5..dcddaae 100755 --- a/ddos-mitigator.sh +++ b/ddos-mitigator.sh @@ -43,10 +43,14 @@ MY_PORT="443" # After this point, no editing is required. # These suffixes must be appended to the respective addresses and subnets. -ext8=".0.0.0/8" -ext16=".0.0/16" -ext24=".0/24" -ext32="/32" +suffix8="/8" +suffix16="/16" +suffix24="/24" +suffix32="/32" +ext8=".0.0.0" +ext16=".0.0" +ext24=".0" +ext32="" # Define some constants to format the output in a colorful way. red="$(printf '\033[38;2;255;0;43m')" @@ -119,13 +123,15 @@ function exec_as_root() { function filter() { # list of current connections file="$1" - # subnet extension, e.g. ".0.0/16" + # subnet extension, e.g. ".0.0" ext="$2" + # subnet suffix, e.g. "/16" + suffix="$3" rm -f "${filtered}" # Reject already banned addresses while read -r -u3 address ; do - if [[ "${banned}" != *"${address}${ext}"* ]] ; then + if [[ "${banned}" != *"${address}${ext}${suffix}"* ]] ; then echo "Considering ${address}." echo "${address}" >> "${filtered}" else @@ -283,41 +289,40 @@ function set_highlight_color() { ################################################################################ # Process the file denoted by $1. For each line in the file, the count and the -# address are displayed and a whois request is made. The user can then choose to -# ban or ignore the address. Addresses chosen to be banned are appended to the -# $banlist. +# address are displayed and a lookup for the IP addresses country is made in the +# GeoIP database. The user can then choose to ban or ignore the address. +# Addresses chosen to be banned are appended to the $banlist. ################################################################################ function process_file () { local file="${1}" local line='' local count=0 - local addr='' + local addronly='' + local addrwithsuffix='' local banaction='' local nline=1 - local country_cn=1 + local country= # Read the contents from filedescriptor 3 (important: Don's use the # standard filedescriptor because we need to handle user input from # within the loop). while IFS= read -r -u3 line ; do line="$(echo "${line}" | tr -s '[:blank:]')" count="$(echo "${line}" | cut -d' ' -f2)" - addr="$(echo "${line}" | cut -d' ' -f3-)${ext}" + addronly="$(echo "${line}" | cut -d' ' -f3-)${ext}" + addrwithsuffix="${addronly}${suffix}" set_highlight_color "${count}" + country="$(./geoip-lookup.py -f "${database}" "${addronly}")" if [[ autopilot -eq 0 ]] ; then - whois "${addr}" | tee "${whoisoutput}" - else - whois "${addr}" > "${whoisoutput}" + echo "Country: '${country}'" fi - grep -iq "^country: *${bancountry}$" "${whoisoutput}" - country_cn=$? echo -n "Address ${bold}$((nline++)) of ${nlines}${reset}: \ -Found '${blue}${addr}${reset}' ${hilite}${count}${reset} times." +Found '${blue}${addrwithsuffix}${reset}' ${hilite}${count}${reset} times." if [[ ${autopilot} -eq 0 ]] ; then echo -n "Ban [y/N/s=No, and skip remaining]? " read banaction else - if [[ ${country_cn} -eq 0 ]] ; then + if [[ "${country}" == "${bancountry}" ]] ; then if [[ $count -ge $autopilot ]] ; then echo -en "\n${red}Autopilot active. ${reset}" banaction=y @@ -338,17 +343,17 @@ Found '${blue}${addr}${reset}' ${hilite}${count}${reset} times." case "${banaction}" in "s" | "S" ) - echo "Not banning '${blue}${addr}${reset}', \ + echo "Not banning '${blue}${addrwithsuffix}${reset}', \ skipping remaining addresses." return ;; "y" | "Y" ) - echo "Adding '${blue}${addr}${reset}' to \ + echo "Adding '${blue}${addrwithsuffix}${reset}' to \ banlist." - echo "${addr}" >> "${banlist}" + echo "${addrwithsuffix}" >> "${banlist}" ;; "n" | "N" | * ) - echo "Not banning '${blue}${addr}${reset}'." + echo "Not banning '${blue}${addrwithsuffix}${reset}'." ;; esac # Here goes: Pipe the file contents via filedescriptor 3. @@ -414,10 +419,10 @@ cut -d. -f1-2 "${fileraw}" | sort > "${file16}" cut -d. -f1 "${fileraw}" | sort > "${file8}" # Filter already banned addresses -filter "${file32}" "${ext32}" -filter "${file24}" "${ext24}" -filter "${file16}" "${ext16}" -filter "${file8}" "${ext8}" +filter "${file32}" "${ext32}" "${suffix32}" +filter "${file24}" "${ext24}" "${suffix24}" +filter "${file16}" "${ext16}" "${suffix16}" +filter "${file8}" "${ext8}" "${suffix8}" # Determine the number of connections per address uniq -c "${file32}" | sort -rn | sponge "${file32}" @@ -472,6 +477,8 @@ TEMP="file${netmask}" file="${!TEMP}" TEMP="ext${netmask}" ext="${!TEMP}" +TEMP="suffix${netmask}" +suffix="${!TEMP}" TEMP="nlines${netmask}" nlines="${!TEMP}" unset TEMP @@ -490,9 +497,9 @@ sudo -k # Iterate over all addresses in $banlist and invoke fail2ban-client on each # one of them. -while read -r addr ; do - echo "Banning ${addr} ..." - exec_as_root fail2ban-client set "${jail}" banip "${addr}" +while read -r addrwithsuffix ; do + echo "Banning ${addrwithsuffix} ..." + exec_as_root fail2ban-client set "${jail}" banip "${addrwithsuffix}" done < "${banlist}" echo "${green}All done!${reset}"