Website/IPtables Blacklist/ipset_blocklist.sh
2024-11-14 16:49:03 -06:00

333 lines
11 KiB
Bash

#!/bin/bash
# Where we keep all the blacklists.
iproute=$(ip route get 8.8.8.8 | awk -- '{print $5}')
BL_DIR="/var/lib/ipset"
if [ ! -d $BL_DIR ]; then
mkdir -p $BL_DIR
else
echo "Unable to create $BL_DIR"
fi
if [ ! "$(command -v ipset)" ]; then
dnf install ipset
else
echo 'Unable find or install ipset'
fi
# Some hosting services such as RamNode will ban you for using > 90% of the cpu!!!
# So we recommend installing cpulimit and limiting to 20% of cpu usage when
# calling this script.
#
## cpulimit -z -l 20 /usr/local/bin/blacklists.sh
# cpulimit dosn't like scripts writing to stdout/stderr so them redirect to
# an output file.
#
exec >$BL_DIR/blocklists.out 2>&1
SCRIPT_NAME=$0
HOST_NAME=$(uname -n)
# default syslog messages priority and tag.
LOG_PRI="local0.notice"
LOG_TAG="[$SCRIPT_NAME]"
# Set to empty string if you don't want error emails. Otherwise, set to an admin email.
MAIL_ADMIN="root"
# Logging is enabled for the following ports this is so we can do later audit checks
# in case we are droping legitimate traffic.
TCP_PORTS="53,80,443"
UDP_PORTS="53"
# If PSAD is installed then block Danger Level = $DL and above attackers
# each time the blacklists are reloaded.
DL=3
# Retrieve new blacklists only when they are older then BL_AGE
BL_AGE="23 hours ago"
#---------------------------------------------------------------------------
# logmessage <msg_text>
logmessage() {
{
MSG="$1"
logger -s -p $LOG_PRI -t "$LOG_TAG" "$MSG"
}
}
# <ips> goodinbadnets
# - returns whitelist <ips> that that are in blacklists.
goodinbadnets() {
{
myips=""
for good in $(ipset list good_ips | grep -E "^[1-9]");
do
myip=$(ipset test bad_nets_n "$good" 2>&1 | grep "is in" | awk '{print $1}')
if [ -n "$myip" ]; then
myips="$myips $myip"
fi
done
echo "$myips"
}
}
# blacklistit <ip/cdr> <listname>
# - blacklists the given <ip/cdr> to bad_nets_n or gad_ips_n
# - also checks if the <ip/cdr> blacklists one of your whitelisted ips, and
# if so it will remove it from the blacklist and warn you.
blacklistit() {
{
IP=$1
LISTNAME=$2
if echo "$IP" | grep -E -q "\/[0-9]+"; then
ipset add bad_nets_n "$IP" -exist
badip=$(goodinbadnets)
if [ -n "$badip" ]; then
error_msg="ERROR Your whitelist IP $badip has been blacklisted in $LISTNAME"
logmessage "$error_msg"
ERROR_MSGS="$ERROR_MSGS\n$error_msg"
ipset del bad_nets_n "$IP"
fi
else
if ipset test good_ips "$IP" 2>/dev/null; then
error_msg="ERROR Your whitelist IP $IP has been blacklisted in $LISTNAME"
logmessage "$error_msg"
ERROR_MSGS="$ERROR_MSGS\n$error_msg"
else
ipset add bad_ips_n "$IP" -exist
fi
fi
}
}
# loadblacklist <name> <url>
# - loads standard form blacklist from <url> website, labels cache files with <name>
loadblacklist() {
{
BL_NAME=$1
BL_URL=$2
BL_FILE="$BL_DIR/$BL_NAME.txt"
if [ ! -f "$BL_FILE" ] || [ "$(date +%s -r "$BL_FILE")" -lt "$(date +%s --date="$BL_AGE")" ]; then
echo "-- getting fresh $BL_NAME from $BL_URL"
wget -q -t 2 --output-document="$BL_FILE" "$BL_URL"
fi
if [ -f "$BL_FILE" ]; then
echo "-- loading $BL_NAME from $BL_FILE"
# strip comments - mac address and ipv6 not supported yet so strip :
awk '{print $1}' "$BL_FILE" | cut -d\; -f1 | cut -d\, -f1 | grep -Ev "^#|^ *$|:" | sed -e "s/[^0-9\.\/]//g" | grep -E "^[0-9]" >"${BL_FILE}".filtered
echo "-- loading $BL_NAME - $(wc -l "${BL_FILE}".filtered) entries"
filter=$(cat "${BL_FILE}".filtered)
for ip in $filter;
do
blacklistit "$ip" "$BL_NAME"
done
fi
}
}
#---------------------------------------------------------------------------
# MAIN
#---------------------------------------------------------------------------
# concatenated list of all error message
ERROR_MSGS=""
if ! which ipset >/dev/null 2>&1; then
echo "ERROR: You must install 'ipset'"
exit 1
fi
logmessage "mylinux.work blocklist script started"
# Create temporary swap ipsets
ipset create bad_ips_n hash:ip hashsize 4096 maxelem 262144 2>/dev/null
ipset flush bad_ips_n
ipset create bad_nets_n hash:net hashsize 4096 maxelem 262144 2>/dev/null
ipset flush bad_nets_n
#
# Setup the active ipsets if they don't yet exist.
# Load them from last save sets to speed up load times in cases of reboot
# and ensure protection faster.
#
if ! ipset list bad_ips >/dev/null 2>&1; then
echo "-- creating bad_ips ipset as does not exist."
ipset create bad_ips hash:ip hashsize 4096 maxelem 262144
if [ -f "$BL_DIR/bad_ips.sav" ]; then
echo "-- importing from save file $BL_DIR/bad_ips.sav"
grep -v "create" $BL_DIR/bad_ips.sav | ipset restore
fi
fi
if ! ipset list bad_nets >/dev/null 2>&1; then
echo "-- creating bad_nets ipset as does not exist."
ipset create bad_nets hash:net hashsize 4096 maxelem 262144
if [ -f "$BL_DIR/bad_nets.sav" ]; then
echo "-- importing from save file $BL_DIR/bad_nets.sav"
grep -v "create" $BL_DIR/bad_nets.sav | ipset restore
fi
fi
#
# Setup our firewall ip chains
#
if ! iptables -L ftmon-blacklists -n >/dev/null 2>&1; then
echo "-- creating iptables rules for first time"
iptables -N ftmon-blacklists
iptables -I INPUT \
-m set --match-set bad_ips src -j ftmon-blacklists
# insert the smaller set first.
iptables -I INPUT \
-m set --match-set bad_nets src -j ftmon-blacklists
# keep a record of our business traffic ports.
# so we can check if we blocked legitimate traffic if need be.
# DNS and http/https are most typical legit ports
iptables -A blocklists -i "$iproute" -p tcp -m multiport --dports $TCP_PORTS -m limit --limit 5/min -j LOG --log-prefix "[BL DROP] "
iptables -A blocklists -i "$iproute" -p udp -m multiport --dport $UDP_PORTS -m limit --limit 5/min -j LOG --log-prefix "[BL DROP] "
iptables -A blocklists -i "$iproute" -m state --state NEW -p tcp -m multiport --dports $TCP_PORTS -j REJECT
iptables -A blocklists -i "$iproute" -m state --state NEW -p udp -m multiport --dports $UDP_PORTS -j REJECT
iptables -A blocklists -i "$iproute" -m state --state NEW -j DROP
fi
# List of ips to whitelist
if ! ipset list good_ips >/dev/null 2>&1; then
ipset create good_ips hash:ip
fi
# load fresh white list each time as the list should be small.
ipset flush good_ips
# load your good ip's
WL_CUSTOM="$BL_DIR/whitelist.txt"
count=0
count1=$(grep -Ev "^#|^ *$" $WL_CUSTOM | sed -e "s/#.*$//" -e "s/[^.0-9\/]//g")
if [ -f "$WL_CUSTOM" ]; then
for ip in $count1; do
ipset add good_ips "$ip" -exist
count=$((count + 1))
done
fi
echo "-- loaded $count entries from $WL_CUSTOM"
# load your personal custom blacklists.
BL_CUSTOM="$BL_DIR/blacklist.txt"
count=0
count2=$(grep -Ev "^#|^ *$" $BL_CUSTOM | sed -e "s/#.*$//" -e "s/[^.0-9\/]//g")
if [ -f "$BL_CUSTOM" ]; then
for ip in $count2; do
blacklistit "$ip" "$BLACKLIST"
count=$((count + 1))
done
fi
echo "-- loaded $(ipset list bad_ips_n | grep -Ec "^[1-9]") entries from blacklist "
echo "-- loaded $count entries from $BL_CUSTOM"
# If PSAD is installed then use some of it's good detection work
# to stop attackers.
count=0
count3=$(awk '{print $2, $1}' /var/log/psad/top_attackers | grep "^[$DL-]" | awk '{print $2}')
if [ -f "/var/log/psad/top_attackers" ]; then
for ip in $count3; do
blacklistit "$ip" "$BLACKLIST"
count=$((count + 1))
done
fi
echo "-- loaded $count entries from /var/log/psad/top_attackers "
#
# Load Standard format blacklists
# Some of them are over zealous, you may want to comment out.
#
# loadblacklist "bl-autoshun-inet" "http://www.autoshun.org/files/shunlist.csv"
loadblacklist "bl-bdsatib-inet" "https://www.binarydefense.com/banlist.txt"
loadblacklist "bl-bfblocker-inet" "http://danger.rulez.sk/projects/bruteforceblocker/blist.php"
loadblacklist "bl-cinsarmy-inet" "http://cinsscore.com/list/ci-badguys.txt"
loadblacklist "bl-drop-inet" "https://www.spamhaus.org/drop/drop.txt"
# loadblacklist "bl-dropv6-inet6" "https://www.spamhaus.org/drop/dropv6.txt"
# loadblacklist "bl-dshield-inet" "https://iplists.firehol.org/files/dshield.netset"
# loadblacklist "bl-dshield-top10-inet" "http://feeds.dshield.org/top10-2.txt"
# loadblacklist "bl-edrop-inet" "https://www.spamhaus.org/drop/edrop.txt"
# loadblacklist "bl-f2ball-inet" "http://lists.blocklist.de/lists/all.txt"
loadblacklist "bl-firehol-inet" "https://iplists.firehol.org/files/firehol_level1.netset"
# loadblacklist "bl-greensnow-inet" "https://blocklist.greensnow.co/greensnow.txt"
# loadblacklist "bl-infiltrated-inet" "http://www.infiltrated.net/blacklisted"
# loadblacklist "bl-ipsec-inet" "http://doc.emergingthreats.net/pub/Main/RussianBusinessNetwork/RussianBusinessNetworkIPs.txt"
loadblacklist "bl-ipsum-inet" "https://raw.githubusercontent.com/stamparm/ipsum/master/levels/2.txt"
# loadblacklist "bl-maxmind-inet" "https://www.maxmind.com/en/anonymous_proxies"
# loadblacklist "bl-openbl-inet" "http://www.openbl.org/lists/base.txt"
# loadblacklist "bl-torexitnodes-inet" "https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1"
# loadblacklist "bl-shlasso-inet" "http://www.spamhaus.org/drop/drop.lasso"
#
# bot nets
#
# https://palevotracker.abuse.ch/blocklists.php
# loadblacklist "bl-palevo-inet" "https://palevotracker.abuse.ch/blocklists.php?download=ipblocklist"
# https://spyeyetracker.abuse.ch/blocklist.php
# loadblacklist "bl-spyeye-inet" "https://spyeyetracker.abuse.ch/blocklist.php?download=ipblocklist"
# https://zeustracker.abuse.ch/blocklist.php
# loadblacklist "bl-zeus-inet" "https://zeustracker.abuse.ch/blocklist.php?download=badips"
#
# special cases, custom formats blacklists
#
# Obtain List of badguys from dshield.org
# https://isc.sans.edu/feeds_doc.html
BL_NAME="bl-dshield-top10-inet"
BL_URL="http://feeds.dshield.org/top10-2.txt"
BL_FILE="$BL_DIR/$BL_NAME.txt"
if [ ! -f "$BL_FILE" ] || [ "$(date +%s -r "$BL_FILE")" -lt "$(date +%s --date="$BL_AGE")" ]; then
echo "-- getting fresh $BL_NAME from $BL_URL"
wget -q -t 2 --output-document=$BL_FILE $BL_URL
fi
if [ -f "$BL_FILE" ]; then
echo "-- loading $BL_NAME from $BL_FILE"
load=$(grep -E "^[1-9]" $BL_FILE | cut -f1)
for ip in $load; do
blacklistit "$ip" $BL_NAME
done
fi
# swap in the new sets.
ipset swap bad_ips_n bad_ips
ipset swap bad_nets_n bad_nets
# show before and after counts.
complete_msg="bad_ips: current=$(ipset --list bad_ips_n | grep -Ec '^[1-9]') \
previous=$(ipset --list bad_ips | grep -Ec '^[1-9]') \
bad_nets: previous=$(ipset --list bad_nets | grep -Ec '^[1-9]') \
current=$(ipset --list bad_nets_n | grep -Ec '^[1-9]')"
logmessage "$complete_msg"
# only send email if problems.
if [ -n "$MAIL_ADMIN" ] && [ -n "$ERROR_MSGS" ]; then
echo -e "${complete_msg}\n${ERROR_MSGS}" | mail -s "$LOG_TAG $HOST_NAME" $MAIL_ADMIN
fi
# save memory space by destroying the temporary swap ipset
ipset destroy bad_ips_n
ipset destroy bad_nets_n
# save our ipsets for quick import on reboot.
ipset save bad_ips >$BL_DIR/bad_ips.sav
ipset save bad_nets >$BL_DIR/bad_nets.sav
logmessage "mylinux.work blocklist script completed"