Hi,
Yes, I use Firehol and other block lists:
"https://www.projecthoneypot.org/list_of_ips.php?t=d&rss=1"
"https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1"
"https://danger.rulez.sk/projects/bruteforceblocker/blist.php"
"https://www.spamhaus.org/drop/drop_v4.json"
"https://cinsscore.com/list/ci-badguys.txt"
"https://lists.blocklist.de/lists/all.txt"
"https://blocklist.greensnow.co/greensnow.txt"
"https://iplists.firehol.org/files/firehol_level1.netset"
"https://iplists.firehol.org/files/stopforumspam_7d.ipset"
"https://raw.githubusercontent.com/borestad/blocklist-abuseipdb/main/abuseipdb-s100-14d.ipv4"
"https://raw.githubusercontent.com/stamparm/ipsum/master/levels/1.txt"
I made this script to download all the IPs from the sources, remove duplicated IPs and create 3 levels (level 3 if IPs appear in 3 or more sources, level 2 if IPs appear in 2 sources and level 1 if …)
#!/bin/bash
set -uo pipefail
# Configuration
IPSET_NAME="${1:-sahsanu}"
DEST_DIR="/usr/local/hestia/data/firewall/ipset"
# Create directories if they don't exist
mkdir -p "$DEST_DIR"
# Logging function (only if interactive)
log() {
if [ -t 1 ]; then
echo "$@"
fi
}
BLOCKLISTS=(
"https://www.projecthoneypot.org/list_of_ips.php?t=d&rss=1"
"https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1"
"https://danger.rulez.sk/projects/bruteforceblocker/blist.php"
"https://www.spamhaus.org/drop/drop_v4.json"
"https://cinsscore.com/list/ci-badguys.txt"
"https://lists.blocklist.de/lists/all.txt"
"https://blocklist.greensnow.co/greensnow.txt"
"https://iplists.firehol.org/files/firehol_level1.netset"
"https://iplists.firehol.org/files/stopforumspam_7d.ipset"
"https://raw.githubusercontent.com/borestad/blocklist-abuseipdb/main/abuseipdb-s100-14d.ipv4"
"https://raw.githubusercontent.com/stamparm/ipsum/master/levels/1.txt"
)
IP_BLOCKLIST_TMP=$(mktemp)
trap 'rm -f "$IP_BLOCKLIST_TMP"' EXIT
TOTAL=${#BLOCKLISTS[@]}
CURRENT=0
log "Downloading blocklists..."
for i in "${BLOCKLISTS[@]}"; do
CURRENT=$((CURRENT + 1))
# Extract a readable name from URL
if grep -q githubusercontent <<<"$i"; then
SOURCE_NAME=$(awk -F '/' '{print $5}' <<<"$i")
elif grep -q firehol <<<"$i"; then
SOURCE_NAME="Firehol: $(awk -F '/' '{print $5}' <<<"$i")"
else
SOURCE_NAME=$(sed -E 's|https?://([^/]+).*|\1|' <<<"$i")
fi
#log "[$CURRENT/$TOTAL] Fetching $SOURCE_NAME..."
IP_TMP=$(mktemp)
HTTP_RC=$(curl -L --connect-timeout 10 --max-time 10 -o "$IP_TMP" -s -w "%{http_code}" "$i")
#if [[ $HTTP_RC == "200" || $HTTP_RC == "302" || $HTTP_RC == "000" ]]; then
if [[ $HTTP_RC == "200" ]]; then
IP_COUNT=$(grep -Po '(?:\d{1,3}\.){3}\d{1,3}(?:/\d{1,2})?' "$IP_TMP" | wc -l)
log "[$(printf '%02d' $CURRENT)/$TOTAL] Downloaded $IP_COUNT IPs from $SOURCE_NAME"
grep -Po '(?:\d{1,3}\.){3}\d{1,3}(?:/\d{1,2})?' "$IP_TMP" |
sed -r 's/^0*([0-9]+)\.0*([0-9]+)\.0*([0-9]+)\.0*([0-9]+)(.*)$/\1.\2.\3.\4\5/' >>"$IP_BLOCKLIST_TMP"
elif [[ $HTTP_RC == "503" ]]; then
echo >&2 "[$(printf '%02d' $CURRENT)/$TOTAL] **Unavailable** (503): $SOURCE_NAME"
else
echo >&2 "[$(printf '%02d' $CURRENT)/$TOTAL] **Error** downloading IP list:HTTP $HTTP_RC for $SOURCE_NAME"
fi
rm -f "$IP_TMP"
done
# Create temporary files
IP_COUNT=$(mktemp)
IP_LV1=$(mktemp)
IP_LV2=$(mktemp)
IP_LV3=$(mktemp)
trap 'rm -f "$IP_COUNT" "$IP_LV1" "$IP_LV2" "$IP_LV3"' EXIT
IPSET_LV1="${IPSET_NAME}-LV1.v4.iplist"
IPSET_LV2="${IPSET_NAME}-LV2.v4.iplist"
IPSET_LV3="${IPSET_NAME}-LV3.v4.iplist"
# Filter private IPs, multicast and single-digit subnets (/0-/9)
# This prevents excessively broad ranges that could block half the internet
log "Processing and filtering IPs..."
sed -r -e '/^(0\.0\.0\.0|10\.|127\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[0-1]\.|192\.168\.|22[4-9]\.|23[0-9]\.)/ d' \
-e '/\/[0-9]$/ d' "$IP_BLOCKLIST_TMP" |
sort -V | uniq -c >"$IP_COUNT"
# Classify by appearance level
awk '$1 >= 3' "$IP_COUNT" | awk '{print $2}' >"$IP_LV3"
awk '$1 == 2' "$IP_COUNT" | awk '{print $2}' >"$IP_LV2"
awk '$1 == 1' "$IP_COUNT" | awk '{print $2}' >"$IP_LV1"
# Count IPs by level (only show in interactive mode)
if [ -t 1 ]; then
LV3_COUNT=$(wc -l <"$IP_LV3")
LV2_COUNT=$(wc -l <"$IP_LV2")
LV1_COUNT=$(wc -l <"$IP_LV1")
echo "Processed IPs:"
{
echo "Level 3 (≥3 occurrences): $LV3_COUNT"
echo "Level 2 (2 occurrences): $LV2_COUNT"
echo "Level 1 (1 occurrence): $LV1_COUNT"
} | column -t -s ':' -R 2 | sed 's/^/ /'
fi
# Move to Hestia directory
mv "$IP_LV3" "$DEST_DIR/$IPSET_LV3" && log "Created LV3 list: $DEST_DIR/$IPSET_LV3"
mv "$IP_LV2" "$DEST_DIR/$IPSET_LV2" && log "Created LV2 list: $DEST_DIR/$IPSET_LV2"
mv "$IP_LV1" "$DEST_DIR/$IPSET_LV1" && log "Created LV1 list: $DEST_DIR/$IPSET_LV1"
log "Blocklists updated successfully"