Secure firewall setup

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"
4 Likes