#!/bin/bash

# This script is used to combine and examine the outputs from the lastb command from all of the Linux servers located in
# South Mountain Community College's Cisco lab, It gets IP addresses from the output from the lastb command which may be in
# dotted decimal, dashed decimal or FQDN format. Once a suspect IP is found, a WHOIS is performed on the IP and the subnet to
# which the IP belongs is determined. Ultimately, it will generate a file - Subnets.list.temp - with the list of subnets (and
# sometimes, host addresses, if originating in the US or the subnet cannot be determined). The Subnets.list.temp file is used
# with the ExecuteUpdate.sh script (which is called by this script in non-test mode) to update the iptables on all of the
# lab's Linux VMs using crontab. See ExecuteUpdate.sh for notes as to its operation.
#
# Packages that need to be installed for this script to work are:
# Extra Packages for Enterprise Linux: epel-release.noarch
# Allow non-interactive SSH login from within a script: sshpass.x86_64
# Lookup IP addresses in WHOIS directories: whois.x86_64
# Geolocation databases (created by Maxmind): GeoIP.x86_64
#
# Also:
#       lastb needs to work, which may mean that /var/log/btmp needs to be created
#               Once created, it needs to be owned by root and be in the utmp group (chgrp utmp /var/log/btmp)
#               It also needs rw permission for root only (chmod 600 /var/log/btmp)
#
#       dig, to allow for the lookup of FQDNs
#
# GeoIP can be updated using the GeoIPupdate.sh script (which can be used in crontab), or with the following lines of script
#       cd /usr/share/GeoIP
#       wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
#       gunzip -f GeoIP.dat.gz
#
# Author : Tracy L Baker
# Contact: tracy.baker@southmountaincc.edu or tech@whatacharacter.net

# This function is used when a report comes back that only lists a network ID and broadcast ID and no CIDR
# When calling this functions, make certain to make the network address the first argument and the broadcast address the
# second -- there is no coding in place to see if these are reversed.  If they are, bad things will happen (tm).
function BuildSubnet ()
{
        # Check to make certain that $1 and $2 are NOT blank
        if [[ $1 == "" || $2 == "" ]]
        then
                clear; echo; echo "ERROR: Call to BuildSubnet() function has blank argument(s)!"
                echo "First argument  = "$1; echo "Second argument = "$2; echo; return 1
        fi

        # Define variables that will only be used within this function, hence "local"
        local Increment=0; local ClassfulCIDR=0; local NetBits=0
        local NetOct=(); local BCOct=()
        local Network=""; local BCast=""

        Network=$1; BCast=$2

        # To determine the network's increment (and therefore CIDR), we must first break apart the network and broadcast
        # addresses into their four octets. Since we're using an array, the elements in the array are 0 through 3 -- so octet
        # 1 is array element 0, octet 2 is array element 1, and so on.
        for (( i=0; i<4; i++))
        do
                BCOct[$i]=$(echo $BCast | cut -d. -f$((i+1))); NetOct[$i]=$(echo $Network | cut -d. -f$((i+1)))
        done

        # Start by looking at the fourth octet in the network address, if it is not zero, process it -- the CIDR will be /25
        # or greater and the network address will be a non-zero number in the fourth octet. Once that check is done, and was
        # false, look for an octet in the broadcast address that is not equal to 255, working backwards from the fourth --
        # once one is found process it. This will get CIDRs from /1 to /30 (this covers /25 and greater when the fourth
        # network octet is zero), Once an octet is identified, a formula is applied that gives the increment, it is:
        # Increment=((BroadcastOctet[x]+1)-NetworkOctet[x]). The classful CIDR is also tracked as we work through the octets.
        if [[ ${NetOct[3]} != 0 ]]
        then
                Increment=$((++BCOct[3] - NetOct[3])); ClassfulCIDR=24
        elif [[ ${BCOct[3]} != 255 ]]
        then
                Increment=$((++BCOct[3] - NetOct[3])); ClassfulCIDR=24
        elif [[ ${BCOct[2]} != 255 ]]
        then
                Increment=$((++BCOct[2] - NetOct[2])); ClassfulCIDR=16
        else
                Increment=$((++BCOct[1] - NetOct[1])); ClassfulCIDR=8
        fi

        # Once we have the increment, we know how many network bits there are in addition to the ones in $ClassfulCIDR. We
        # look that up using the case statements below. NOTE: there are some times, especially APNIC addresses, where the
        # increment is something that is other than possible (like 3). In this case, we add zero network bits to the last
        # $ClassfulCIDR value we have.
        case $Increment in
                128) NetBits=1 ;; 64) NetBits=2 ;; 32) NetBits=3 ;; 16) NetBits=4 ;;
                  8) NetBits=5 ;;  4) NetBits=6 ;;  2) NetBits=7 ;;  1) NetBits=8 ;;
                  *) NetBits=0 ;;
        esac

        # Build the $SubNet (to be blocked). As this is a global variable, it will be immediately available for use by the
        # main script.
        SubNet=$Network"/"$((ClassfulCIDR+NetBits))

        return 0
}

# Start a timer so we can keep track of how long the processing takes
StartTime=$(date +%s)

### NOTE: As of 4/21/2015 there was a extreme rise in hacking attempts from US addresses, As a result, US subnets are now
### being blocked by default. Setting USHostAddresses to 1 will allow the inclusion of host IPs as opposed to subnet IPs for
### attacks originating from US networks.
USHostAddresses="0"

# Define the lab's servers. the RemoteServer() array holds a list of all the IPs (fourth octet) to access. RemotePassword
# holds the root password for the servers. LocalServer is the machine that this script is running on.
RemoteServer=(40 41 42 43 44 45 46 47 48 49 50 51 7); BaseIP="111.111.111."; RemotePassword="(PUTPASSWORDHERE)"; LocalServer=3

# Initialize variables
StartLog=1; updated=0; B="--BAD--> "; AF=", appending address ("; AB=") to Subnets.list.temp."; i=0
Divider="------------------------------------------------------------------------------"; AddressWhitelist=()

# Make certain there aren't any old report files from the servers.
rm -f ToBeBlocked.lastb*; rm -f Subnet.country.list

clear

# If the script was executed as 'source getSubnets.sh test', run in test mode. Otherwise, dispay a message and wait 30
# seconds to allow the script to be aborted, if desired.
TEST=$1
if [[ $TEST != "test" ]]
then
        echo; echo "If you intended to run this script in test mode, press CTRL-C in the next 30 seconds and use the"
        echo "syntax: source getSubnets.sh test"
        echo; echo "Otherwise, wait, and the script will run as intended (in crontab, most likely)."; sleep 30; TEST=""
fi

# Read in the list of whitelisted hosts and/or subnets from Subnets.address.whitelist and place the values into the
# AddressWhitelist array for later processing. In the Subnets.address.whitelist file, lines with # are ignored.
i=0
while read line
do
        if [[ $line != *"#"* ]]
        then
                AddressWhitelist[$i]=$line
                echo "Adding to list of whitelisted subnets/hosts: "${AddressWhitelist[i]}
                ((i++))
        fi
done < Subnets.address.whitelist

# For the local machine, get all logins -- root and all other accounts. This server is the "honeypot" and there aren't
# any student accounts to worry about. Using the lastb command with the -aw arguments (a = display hostname in last column,
# w = display full domain names).
echo; echo "Getting IPs from "$BaseIP$LocalServer"..."; lastb -aw > Dot$LocalServer.lastb
i=0
while read line
do
        # Make sure these are blank at the start of things to ensure proper processing
        IPaddress=""; OFormat=""

        # As long as $line isn't a blank line, process the information. This is a line of text read from the Dot{x}.lastb
        # file (where {x} is the local server as defined in the $LocalServer variable {see above}).
        if [[ $line != "" ]]
        then
                # Most IPs are dotted decimal (xxx.xxx.xxx.xxx), so look for those first
                IPaddress=$(echo $line | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')

                # If the dotted decimal doesn't exist, look for dashed (xxx-xxx-xxx-xxx). If they exist, pull those out and
                # convert to dotted decimal
                if [[ $IPaddress == "" ]]
                then
                        OFormat=$(echo $line | grep -Eo '[0-9]{1,3}\-[0-9]{1,3}\-[0-9]{1,3}\-[0-9]{1,3}')
                        if [[ $OFormat != "" ]]
                        then
                                IPaddress=${OFormat//-/.}
                        fi
                fi

                # If $IPAddress is still empty, maybe its is because there is a FQDN instead of an IP address, so let's
                # process that -- as long as the line has a ")" in it...  Also, use "dig +short" to pull the IP address
                # that matches the FQDN given. Sometimes, there is more than one IP listed for an FQDN. In this case,
                # just pull the first one.
                if [[ $IPaddress == "" && $line == *")"* ]]
                then
                        IPaddress=$(dig +short $(echo $line | cut -d')' -f2) | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
                        if [[ $(echo $IPaddress | grep -o "\." | wc -l) != "3" ]]
                        then
                                IPaddress=$(echo $IPaddress | cut -d' ' -f1)
                        fi
                fi

                # If $IPaddress is not empty and "root-servers.net" is not in the string (indicating a bad FQDN lookup), add
                # to the list
                if [[ $IPaddress != "" && $IPaddress != *"root-servers.net"* ]]
                then
                        echo "Found (#"$((++i))"): "$IPaddress; echo $IPaddress >> ToBeBlocked.lastb$LocalServer
                fi
        fi
done < Dot$LocalServer.lastb

# Remove Dot{x}.lastb files (where {x} is the value of the fourth octet of a server) as clean up
rm -f Dot$LocalServer.lastb

# Cycle through all the lab's servers, and look for bad logins against predefined accounts (which are defined in
# LastBRemote.sh), to prevent getting bad student logins. This is done by executing a small script (LastBRemote.sh) on each
# machine to generate lists on each machine, then copy those lists back to the server from which this script was run.
for (( address=0; address<${#RemoteServer[@]}; address++ ))
do
        echo; echo ">>>>>>>>>> Executing LastBRemote.sh on "$BaseIP${RemoteServer[address]}" <<<<<<<<<<"
        sshpass -p $RemotePassword ssh root@$BaseIP${RemoteServer[address]} 'bash -s' < LastBRemote.sh
        echo "<<<<<<<<<< Copying result file back to "$BaseIP$LocalServer" >>>>>>>>>>"
        sshpass -p $RemotePassword scp root@$BaseIP${RemoteServer[address]}:/root/ToBeBlocked.lastb /root/ToBeBlocked.lastb${RemoteServer[address]}
done

# Combine all the lists received from the servers, sort and pick out unique host IPs
cat ToBeBlocked.lastb* | sort -n | uniq > ToBeBlocked.list

# This loop reads through ToBeBlocked.list getting the subnets that will be blocked if the subnet in question isn't
# (1) whitelisted or (2) USHostAddresses is set to 0
echo; echo "Performing lookups for these IPs:"; echo; cat ToBeBlocked.list; echo
while read suspectIP
do
        # Initialize reusable variables to prevent errant values from showing up
        SubNet=""; LookUp=""; CIDR=""; OrigString=""; Authority=""; CountryCode=""; FullCountryName=""; Owner=""
        NOct=(); MultiSubnet=(); TempOct=0; OK=0

        # Perform a single lookup at the start of this loop and place results in WHOISlookup.report, which is used to
        # search on (A much better, and faster, solution that looking up the information via whois multiple times.)
        # The sleep timer is here because the script can go too fast. Some authorities will not return any values if
        # queried too often.
        echo; echo "Sleeping for 15 seconds..."; sleep 15
        whois $suspectIP > WHOISlookup.report
        Lookup=$(cat WHOISlookup.report)

        # Get country code for ARIN, RIPE, AfriNIC, and APNIC addresses and the country name (using its IP) from geoiplookup
        CountryCode=$(cat WHOISlookup.report | tr -d " " | grep '[Cc]ountry:' | cut -d: -f2)
        FullCountryName=$(geoiplookup $suspectIP | cut -d, -f2)

        ##### The next few blocks retrieve or calculate the network addresses and CIDRs that are used to iptables. #####

        # This is for "NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK" -- or, in other words, IANA managed addresses
        # This section needs to appear BEFORE the major RIR sections as all RIR names appear in the report.
        if [[ $Lookup == *"NCC-MANAGED-ADDRESS-BLOCK"* ]]
        then
                OrigString=$(cat WHOISlookup.report | grep 'route:')
                CountryCode=$(cat WHOISlookup.report | grep [Cc]ountry | cut -d' ' -f9-)
                Authority=$(cat WHOISlookup.report | grep [Oo]rganisation | cut -d' ' -f4-)
                SubNet=$(echo $OrigString | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}')
        fi

        # This is for JPNIC (Japan) addresses
        # This section needs to appear BEFORE processing for any other IPs addresses as some JPNIC addresses MAY return
        # nothing that can be used, but still have all the RIR names in the report in the section referring to all RIRs.
        # It will also handle JPNIC addresses that do not have information that can be processed.
        if [[ $SubNet == "" && $Lookup == *"JPNIC"* ]]
        then
                echo; echo "Checking JPNIC..."

                # If [Allocation] exists in the report, pull the subnet from there, this should happen first as the subnet
                # in [Allocation] is generally larger than the [Network Number] section
                OrigString=""
                if [[ $Lookup == *"[Allocation]"* ]]
                then
                        echo; echo "Pulling subnet from JPNIC [Allocation] section..."
                        OrigString=$(cat WHOISlookup.report | grep "\[Allocation\]")

                        # Some [Allocation] sections have a network/broadcast pair. If it does, pull the pair out and send
                        # to the BuildSubnet() function for processing.
                        if [[ $(echo $OrigString | grep -o "\." | wc -l) == "6" ]]
                        then
                                echo; echo "Processing [Allocation] section with network/broadcast pair (no CIDR)."
                                BuildSubnet $(echo $OrigString | cut -d' ' -f2 | cut -d- -f1) $(echo $OrigString | cut -d' ' -f2 | cut -d- -f2)

                        # If the [Allocation] section has a network/CIDR, simply pull that out and use it.
                        else
                                echo; echo "Processing [Allocation] section with CIDR."
                                SubNet=$(echo $OrigString | tr -d " " | cut -d']' -f2)
                        fi

                # If [Network Number] exists in the report, pull the subnet from there.
                elif [[ $Lookup == *"[Network Number]"* ]]
                then
                        echo; echo "Pulling subnet from JPNIC [Network Number] section..."
                        OrigString=$(cat WHOISlookup.report | grep "\[Network Number\]")
                        SubNet=$(echo $OrigString | tr -d " " | cut -d']' -f2)
                fi

                # If $OrigString is still blank (because it didn't find anything to process from the above two sections,
                # change the last octet to 0 and append a /24
                if [[ $OrigString == "" ]]
                then
                        echo "No subnet found, changing last octet to 0 and appending /24..."
                        for (( i=0; i<3; i++))
                        do
                                NOct[$i]=$(echo $suspectIP | cut -d. -f$(($i+1)))
                        done
                        SubNet=${NOct[0]}"."${NOct[1]}"."${NOct[2]}".0/24"
                        OrigString="None for this JPNIC address."
                fi

                # Set the authority name and country "name" (I've seen plenty of Hong Kong addresses use the Japanese IPs)
                Authority="JPNIC (APNIC)"
                CountryCode="(JP) Japanese Registry"
        fi

        # This is for some KORNET/KRNIC (Korea) addresses
        # This section needs to appear BEFRE processing for APNIC addresses as "APNIC" appears in the report
        if [[ ( $SubNet = "" ) && ( $Lookup == *"KORNET"* || $Lookup == *"KRNIC"* ) ]]
        then
                echo; echo "Checking KORNET / KRNIC..."
                OrigString=$(cat WHOISlookup.report | grep 'IPv4 Address')
                SubNet=$(echo $OrigString | cut -d' ' -f4)$(echo $OrigString | cut -d' ' -f7 | cut -c2-4)

                # Set the authority name and country "name"
                Authority="KORNET (APNIC)"
                if [[ $Lookup == *"KRNIC"* ]]
                then
                        Authority="KRNIC (APNIC)"
                fi
                CountryCode="(KR) Korean Registry"
        fi

        # Network/CIDR frm ARIN (North America) or RIPE (Europe) addresses
        if [[ ( $SubNet == "" ) && ( $Lookup == *"ARIN"* || $Lookup == *"RIPE"* ) ]]
        then
                echo; echo "Checking ARIN / RIPE..."
                if [[ $Lookup == *"ARIN"* ]]
                then
                        Authority="ARIN"; Search="CIDR"
                else
                        Authority="RIPE"; Search="route:"
                fi
                OrigString=$(cat WHOISlookup.report | grep $Search)

                # Sometimes there are multple network/CIDR records, just get the first one. If there is more than one they
                # are stored within the MultiSubnet array -- for future use.
                SubNet=$(echo $OrigString | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}')
                if [[ $SubNet != "" ]]
                then
                        for (( i=0; i<$(echo $SubNet | grep -o '/' | wc -l); i++))
                        do
                                MultiSubnet[$i]=$(echo $SubNet | cut -d' ' -f$((i+1)))
                        done
                        SubNet=${MultiSubnet[0]}
                else
                        # Some RIPE addresses return network and broadcast addresses and no CIDR, send to the BuildSubnet()
                        # function to generate get network/CIDR
                        OrigString=$(cat WHOISlookup.report | grep inetnum:)
                        if [[ $OrigString != "" ]]
                        then
                                BuildSubnet $(echo $OrigString | cut -d' ' -f2) $(echo $OrigString | cut -d' ' -f4)
                        fi
                fi
        fi

        # We must calculate the network/CIDR for APNIC (Asia/Pacfic) and AfriNIC (Africa) addresses. The BuildSubnet()
        # function does just that.
        if [[ ( $SubNet == "" ) && ( $Lookup == *"APNIC"* || $Lookup == *"AFRINIC"* ) ]]
        then
                echo; echo "Checking APNIC / AfriNIC..."
                OrigString=$(cat WHOISlookup.report | grep inetnum:)

                # Send network and broadcast addresses to BuildSubnet function to build network/CIDR
                BuildSubnet $(echo $OrigString | cut -d' ' -f2) $(echo $OrigString | cut -d' ' -f4)

                # Set the Authority
                Authority="AfriNIC"
                if [[ $Lookup == *"APNIC"* ]]
                then
                        Authority="APNIC"
                fi
        fi

        # We must build the Network/CIDR from LACNIC (South America) or Nic.br (Brazil) addresses, as they're usually
        # presented in an abbreviated format: Ex. 221.98/14
        if [[ ( $SubNet == "" ) && ( $Lookup == *"lacnic"* || $Lookup == *"Nic.br"*  ) ]]
        then
                echo; echo "Checking LACNIC / Nic.br..."
                # Get the country code, then get the partial Network address and CIDR
                OrigString=$(cat WHOISlookup.report | grep inetnum:)
                PartialNet=$(echo $OrigString | cut -d' ' -f2 | cut -d'/' -f1)
                CIDR=$(echo $OrigString | cut -d' ' -f2 | cut -d'/' -f2)

                # Cycle through the partial network address looking for octets that have no value - replace those with 0s
                for (( i=0; i<4; i++))
                do
                        TempOct=$(echo $PartialNet | cut -d. -f$(($i+1)))

                        if [[ $TempOct == "" ]]
                        then
                                NOct[$i]=0
                        else
                                NOct[$i]=$TempOct
                        fi
                done

                # Glue all back together and set the Authority
                SubNet=${NOct[0]}"."${NOct[1]}"."${NOct[2]}"."${NOct[3]}"/"$CIDR
                Authority="LACNIC"
                if [[ $(cat WHOISlookup.report) == *"Nic.br"* ]]
                then
                        Authority="Nic.br (LACNIC)"
                fi
        fi

        # Get the IPs owner's name or business, if possible
        if [[ $Lookup == *"OrgName:"* ]]
        then
                Owner=$(whois $suspectIP | grep OrgName: | cut -d' ' -f9-)
        elif [[ $Lookup == *"Organization Name"* && $Owner == "" ]]
        then
                Owner=$(whois $suspectIP | grep 'Organization Name' | cut -d' ' -f5-)
        elif [[ $Lookup == *"owner:"* && $Owner == "" ]]
        then
                Owner=$(whois $suspectIP | grep owner: | cut -d' ' -f2-)
        elif [[ $Lookup == *"role:"* && $Owner == "" ]]
        then
                Owner=$(whois $suspectIP | grep role: | cut -d' ' -f2-)
        fi

        echo
        echo "IP that was processed       = "$suspectIP
        echo "Network presentation        = "$OrigString
        echo "Address under consideration = "$SubNet
        if [[ $Owner ]]
        then
                echo "'Owner' of this IP          = "$Owner
        fi
        echo "Country code                = "$CountryCode
        echo "Subnet authority            = "$Authority

        # If we STILL don't know the subnet, we want to know that -- and block the host
        if [[ $SubNet == "" ]]
        then
                SubNet=$suspectIP; Authority="NONE - EXAMINE THIS IP ADDRESS!!"; CountryCode="Unknown"
        fi

        # Compare $SubNet and $suspectIP against the AddressWhitelist array to see if either is a whitelisted address
        for (( i=0; i<((${#AddressWhitelist[@]}+1)); i++ ))
        do
                if [[ $SubNet == ${AddressWhitelist[$i]} || $suspectIP == ${AddressWhitelist[$i]} ]]
                then
                        echo "--GOOD--> Found whitelisted address ("$suspectIP"), skipping..."; OK=1; break
                fi
        done

        if [[ $OK == 0 ]]
        then
                # If the $SubNet variable remains greater then 18 characters long after previous processing, add the specific
                # host address to list of addresses to be blocked. NOTE: This section may be depricated -- but is left in
                # just in case something funky slips through (which happens now and again -- its a good catch all)
                if [[ ${#SubNet} > 18 ]]
                then
                        echo $B"Longer than 18 characters ("$SubNet")"$AF$suspectIP$AB" (country code="$CountryCode")"
                        SubNet=$suspectIP

                # If the host address is in the US, add the specific host address to the list of addresses to be blocked,
                # if USHostAddresses is set to 1 (this is done near the top of this script).
                elif [[ $CountryCode == *"US"* && $USHostAddresses == "1"  ]]
                then
                        echo $B"US address"$AF$suspectIP$AB
                        SubNet=$suspectIP

                # If the address is NOT from the US *and* the $SubNet variable remains empty from previous processing, add
                # the specific host address to list of addresses to be blocked. NOTE: This section may be depricated -- but
                # it is left in just in case something funky slips through.
                elif [[ $SubNet == "" ]]
                then
                        echo $B"Non-US address (country code="$CountryCode") with no CIDR or route: entry"$AF$suspectIP$AB
                        SubNet=$suspectIP

                # If the address is NOT from the US and the $SubNet variable has been filled, add the subnet to which
                # specific host resides to the list of addresses to be blocked
                elif [[ $CountryCode != *"US"* ]]
                then
                        echo $B"Non-US address ("$CountryCode")"$AF$SubNet$AB
                fi

                # Write $SubNet to Subnets.list.temp if $Subnet is not blank AND $OK is 0 (if $OK is 1, then it is a
                # whitelisted address), which will be used by updateIPtablesALLPCs.sh to build a master list of subnets
                # (Subnets.list) that will be added to iptables on all servers.
                if [[ $SubNet != "" ]]
                then
                        updated=1
                        echo; echo "Adding "$SubNet" to Subnets.list.temp"
                        echo $SubNet >> Subnets.list.temp
                fi
        fi

        # Write to log file /var/log/getIP.log
        if [[ $StartLog == 1 ]]
        then
                echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"  >> /var/log/getSubnets.log
                echo ">>>>>>>>>>> STARTING LOG FOR "$(date)" <<<<<<<<<<<"  >> /var/log/getSubnets.log
                echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"  >> /var/log/getSubnets.log
        fi
        StartLog=0
        echo $Divider >> /var/log/getSubnets.log
        echo "Suspect IP address           : "$suspectIP >> /var/log/getSubnets.log
        echo "Original subnet information  : "$OrigString >> /var/log/getSubnets.log
        echo "Address that was blocked     : "$SubNet >> /var/log/getSubnets.log
        if [[ $OK == 1 ]]
        then
                echo ">>>>>>>> WHITELISTED <<<<<<<<" >> /var/log/getSubnets.log
        fi
        if [[ $Owner ]]
        then
                echo "'Owner' of this IP           : "$Owner >> /var/log/getSubnets.log
        fi
        echo "Authority for this IP        : "$Authority >> /var/log/getSubnets.log
        echo "Country code for IP address  : "$CountryCode >> /var/log/getSubnets.log
        echo "Country name (geoiplookup)   :"$FullCountryName >> /var/log/getSubnets.log
        echo $FullCountryName >> Subnet.country.list
done < ToBeBlocked.list

# Sort list and collect only unique addresses
cat Subnets.list.temp | sort -rn | uniq > Subnets.list.temp.sort
cat Subnets.list.temp.sort > Subnets.list.temp

# E-Mail administrator is any subnets were found
if [[ $updated == 1 ]]
then
        echo; echo "Sending Subnets.list.temp to administrator..."
        mail -s "ADDED: BLOCKED NETWORKS LOG" tracy.baker@southmountaincc.edu < /root/Subnets.list.temp
        echo; echo "Displaying Subnets.list.temp"; echo; cat Subnets.list.temp
else
        echo; echo "There were no updates at this time..."
fi

# Write some statistics out to the log file after everything is said and done.
Existing=$(cat Subnets.list | wc -l); New=$(cat Subnets.list.temp | wc -l)
echo $Divider >> /var/log/getSubnets.log; echo $Divider >> /var/log/getSubnets.log
echo "Existing IPs being blocked   :" $Existing >> /var/log/getSubnets.log
echo "New IPs found                :" $New >> /var/log/getSubnets.log
echo "Total IPs being blocked      :" $((Existing+New)) >> /var/log/getSubnets.log
echo $Divider >> /var/log/getSubnets.log; echo $Divider >> /var/log/getSubnets.log
echo "Originating countries        :" >> /var/log/getSubnets.log
cat Subnet.country.list | sort | uniq >> /var/log/getSubnets.log;  rm -f Subnet.country.list
echo $Divider >> /var/log/getSubnets.log
echo "Total execution time = "$(($(date +%s) - $StartTime))" seconds."  >> /var/log/getSubnets.log
echo $Divider >> /var/log/getSubnets.log; echo $Divider >> /var/log/getSubnets.log

# NOTE: test is passed to the script at the command prompt (source getSubnets.sh test)
if [[ $TEST != "test" ]]
then
        ### This is the NON test section ###

        # Clean up some files.
        rm -f Subnets.list.t; rm -f Subnets.list.temp.sort; rm -f WHOISlookup.report
        rm -f ToBeBlocked.list; rm -f ToBeBlocked.list.temp; rm -f ToBeBlocked.lastb*
        echo; echo "This script is NOT in test mode..."

        # Append Subnets.list.temp to Subnets.list
        cat Subnets.list.temp >> Subnets.list

        # Go through Subnets.list and remove any blank lines that may have crept in then do a reverse sort and keep only
        # unique addresses (remove duplicates). Clean up files afterwards.
        while read line
        do
        if [[ $line != "" ]]
        then
                echo $line >> Subnets.list.clean
        fi
        done < Subnets.list
        rm -f Subnets.list; cat Subnets.list.clean | sort -nr | uniq > Subnets.list; rm -f Subnets.list.clean

        # Copy Subnets.list to the labs' servers, the execute then ExecuteUpdate.sh (updating iptables and resetting
        # /var/log/btmp) script
        for (( address=0; address<${#RemoteServer[@]}; address++ ))
        do
                echo; echo ">>>>>>>>>> Copying Subnets.list to: "$BaseIP${RemoteServer[address]}" <<<<<<<<<<"
                sshpass -p $RemotePassword scp /root/Subnets.list root@$BaseIP${RemoteServer[address]}:/root
                echo; echo ">>>>>>>>>> Executing ExecuteUpdate.sh on "$BaseIP${RemoteServer[address]}" <<<<<<<<<<"
                sshpass -p $RemotePassword ssh root@$BaseIP${RemoteServer[address]} 'bash -s' < ExecuteUpdate.sh
        done

        # Update iptables and reset /var/log/btmp on local machine
        source ExecuteUpdate.sh
        cat /dev/null > /var/log/btmp; echo "" > /var/log/secure
        rm -f Subnets.list.temp
else
        ### This IS the test section ###
        echo; echo "This script IS in test mode..."

        # Flush iptables on local machine, add IPs from Subnets.list.temp and keep count of the number added
        echo; echo "Adding to "$BaseIP$LocalServer"'s iptables."
        iptables -F
        Counter=1
        while read SN
        do
                echo "Adding subnet number "$((Counter++))" - "$SN
                iptables -I INPUT -s $SN -j DROP
        done < Subnets.list.temp

        # Save iptables and restart iptables service, then display just the INPUT chain
        service iptables save
        systemctl restart iptables
        echo; echo "Displaying "$BaseIP$LocalServer"'s iptables, INPUT chain only"; echo
        iptables -L INPUT
        echo; echo "/var/log/btmp was NOT reset on any machines."
fi

# Zero out the password variable so they don't stay in memory
RemotePassword=""

echo; echo "Done."; echo