#!/bin/bash
#Nifty: Easily block bad reputation ip addresses

curl -s https://nifty.sh/lib/universal/niftylib.sh > /tmp/lib.nifty.sh
. /tmp/lib.nifty.sh
rm -f /tmp/lib.nifty.sh

# Requirements
require_root
require_64bit
require_os centos7 centos8 alma8

if [ ! -f "/usr/bin/whiptail" ]; then
  yum install -y newt
fi

# Function to present choices to the user
function choices() {
  whiptail --title "Block abusive IP addresses" --ok-button "Block selected"  --checklist \
  "Choose which lists to block" 20 78 15 \
  "firehol_abusers_1d.netset" "Firehol Abusers 1D" OFF \
  "firehol_level2.netset" "Firehol Level 2" OFF \
  "tor_exits.ipset" "TOR Exit nodes" OFF \
  "socks_proxy_1d.ipset" "Open SOCKS proxies 1D" OFF \
  "stopforumspam_1d.ipset" "StopForumSpam.com 1D" OFF \
  "greensnow.ipset" "GreenSnow" OFF \
  3>&1 1>&2 2>&3
}

# Intro info
whiptail --title "team.blue Badguy Blocker" --msgbox "This script will block IP Addresses ipset and iptables. Be sure not to mess up existing rules." 8 78

# Additional info
whiptail --title "team.blue Badguy Blocker" --msgbox "WARNING! All existing block ranges created by this tool will be flushed. Select ALL countries you want to block including those that might already be blocked now." 8 78

# Check if ipset is installed
if [ ! -f "/usr/sbin/ipset" ]; then

  if (whiptail --title "ipset missing" --yesno "ipset is not installed. Do you want me to install it for you?" 8 78); then
    yum install ipset -y
  else
    echo "User selected No, exit status was $?."
    echo "ERROR: ipset must be present."
    exit 1
  fi

fi


# Get the list of blocks chosen
blocks=$(choices)


# Create a workdir and go to it
workdir=$(mktemp -d -t badblock-$(date +%Y-%m-%d-%H-%M-%S)-XXXXXXXXXX)
pushd $workdir > /dev/null 2>&1

# Get all current ipsets
IPSETS=$(ipset list |grep "Name" |cut -d" " -f2)

# Delete all iptables rules made by this script earlier
while [ true ]; do
  RULE=$(iptables -L -n --line-numbers | grep -P "^[0-9]+\s+DROP.*match-set tbabusers" |awk '{print $1}' |head -n1)

  if [ -z $RULE ]; then
    break
  else
    iptables -D INPUT $RULE
  fi
done


touch blockset
# Loop through selected blocks
for block in $blocks; do

  # $block contains quotes. Remove those
  clean=$(echo $block |sed -e 's/^"//g' -e 's/"$//g')

  # Set a variable with the file name from the download mirror
  FILE="${clean}"

  # Generate the link
  DL="https://mirror.dk.team.blue/firehol/$FILE"

  # Download the link. TODO: Better error handling
  curl -s $DL >> blockset

  # Decide the name of our ipset
  SETNAME="tbabusers"
done


cat blockset | sort -u > final
size=$(cat final |wc -l)

if [ `cat final | wc -l` -ge "65535" ]; then
	echo "SORRY! Set too large, cannot contain more than 65535 ip addresses"
	exit 1
fi

FILE="final"

  # Check that the ip file exists before trying to do anything with it
  if [ -f $FILE ]; then

    # Check if this set already exists
    ipset destroy $SETNAME

    # Create the set
    ipset -N $SETNAME hash:net

    # Get cidr list
    CIDR_LIST=$(cat $FILE |grep -v "#")
    CIDR_COUNT=$(cat $FILE |grep -v "#" |wc -l)

    # Populate the set with our ip ranges
    cnt=0
    {
      for cidr in $CIDR_LIST; do
        cnt=$((cnt+1))
        echo $(( 100*cnt/CIDR_COUNT ))
        ipset -A $SETNAME $cidr
      done
    } | whiptail --gauge "Blocking $size IP addresses/ranges $1 $2" 6 50 0

    # Our ipset is populated. Now tell iptables to block based on it
    iptables -A INPUT -m set --match-set $SETNAME src -j DROP

    echo "Blocked $CIDR_COUNT ranges!"

  else
    echo "FAIL: $FILE does not exist!"
    exit 1
  fi


popd > /dev/null 2>&1
rm -rf $workdir

