Dynamic blacklist blocking using EdgeRouter
Subscribing to public blacklists and then blocking those connections using an ipset directly on the EdgeRouter for added network security.
Here's the full script:
#!/bin/sh
set -eu
WORKDIR="/config/blacklist"
FINAL_SET="BLACKLIST"
TMP_SET="BLACKLIST_TMP"
ABUSEIPDB_URL="https://raw.githubusercontent.com/borestad/blocklist-abuseipdb/refs/heads/main/abuseipdb-s100-7d.ipv4"
STOPFORUMSPAM_URL="https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/stopforumspam_7d.ipset"
SPAMHAUS_URL="https://www.spamhaus.org/drop/drop.lasso"
RAW_ABUSEIPDB="$WORKDIR/abuseipdb-s100-7d.ipv4"
RAW_STOPFORUMSPAM="$WORKDIR/stopforumspam_7d.ipset"
RAW_SPAMHAUS="$WORKDIR/drop.lasso"
COMBINED="$WORKDIR/combined.txt"
SORTED="$WORKDIR/combined.sorted.txt"
FINAL_LIST="$WORKDIR/final.txt"
RESTORE_FILE="$WORKDIR/ipset.restore"
WHITELIST="$WORKDIR/LocalWhitelist.txt"
WHITELIST_SORTED="$WORKDIR/whitelist.sorted.txt"
LOGFILE="$WORKDIR/update-blacklist.log"
mkdir -p "$WORKDIR"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOGFILE"
}
backup_file() {
FILE="$1"
if [ -f "$FILE" ]; then
mv "$FILE" "$FILE.bak"
fi
}
is_valid_ipv4_or_cidr() {
echo "$1" | awk -F'[./]' '
NF==4 || NF==5 {
for (i=1; i<=4; i++) {
if ($i == "" || $i < 0 || $i > 255) exit 1
}
if (NF==5 && ($5 == "" || $5 < 0 || $5 > 32)) exit 1
exit 0
}
{ exit 1 }'
}
is_reserved() {
case "$1" in
0.*|10.*|127.*|169.254.*|172.1[6-9].*|172.2[0-9].*|172.3[0-1].*|192.168.*|224.*|240.*)
return 0
;;
*)
return 1
;;
esac
}
filter_safe() {
while IFS= read -r ip; do
is_valid_ipv4_or_cidr "$ip" || continue
base_ip=$(echo "$ip" | cut -d/ -f1)
is_reserved "$base_ip" && continue
echo "$ip"
done
}
log "Starting blacklist update"
log "Backing up previous generated files"
backup_file "$COMBINED"
backup_file "$SORTED"
backup_file "$FINAL_LIST"
backup_file "$RESTORE_FILE"
backup_file "$WHITELIST_SORTED"
log "Downloading feeds"
curl -fsSL "$ABUSEIPDB_URL" -o "$RAW_ABUSEIPDB"
curl -fsSL "$STOPFORUMSPAM_URL" -o "$RAW_STOPFORUMSPAM"
curl -fsSL "$SPAMHAUS_URL" -o "$RAW_SPAMHAUS"
: > "$COMBINED"
log "Parsing AbuseIPDB feed"
if [ -s "$RAW_ABUSEIPDB" ]; then
grep -E '^[0-9./]+$' "$RAW_ABUSEIPDB" | filter_safe >> "$COMBINED" || [ $? -eq 1 ]
fi
log "Parsing stopforumspam ipset feed"
if [ -s "$RAW_STOPFORUMSPAM" ]; then
awk '/^add[[:space:]]+/ {print $3}' "$RAW_STOPFORUMSPAM" \
| grep -E '^[0-9./]+$' \
| filter_safe >> "$COMBINED" || [ $? -eq 1 ]
fi
log "Parsing Spamhaus DROP feed"
if [ -s "$RAW_SPAMHAUS" ]; then
awk -F';' '{print $1}' "$RAW_SPAMHAUS" \
| sed 's/^[[:space:]]*//;s/[[:space:]]*$//' \
| grep -E '^[0-9./]+$' \
| filter_safe >> "$COMBINED" || [ $? -eq 1 ]
fi
log "Deduplicating entries"
LC_ALL=C sort -u "$COMBINED" > "$SORTED"
if [ -f "$WHITELIST" ]; then
log "Applying whitelist from $WHITELIST"
: > "$WHITELIST_SORTED"
if [ -s "$WHITELIST" ]; then
grep -E '^[0-9./]+$' "$WHITELIST" \
| filter_safe \
| LC_ALL=C sort -u > "$WHITELIST_SORTED" || [ $? -eq 1 ]
fi
LC_ALL=C comm -23 "$SORTED" "$WHITELIST_SORTED" > "$FINAL_LIST"
else
cp "$SORTED" "$FINAL_LIST"
fi
COUNT=$(wc -l < "$FINAL_LIST" | tr -d ' ')
log "Final blacklist count: $COUNT"
if [ "$COUNT" -eq 0 ]; then
log "ERROR: Final blacklist is empty, aborting"
exit 1
fi
log "Ensuring final ipset exists"
ipset list "$FINAL_SET" >/dev/null 2>&1 || \
ipset create "$FINAL_SET" hash:net family inet hashsize 4096 maxelem 262144
log "Cleaning up stale temp set if present"
ipset destroy "$TMP_SET" >/dev/null 2>&1 || true
log "Building restore file"
{
echo "create $TMP_SET hash:net family inet hashsize 4096 maxelem 262144"
while IFS= read -r entry; do
[ -n "$entry" ] && echo "add $TMP_SET $entry"
done < "$FINAL_LIST"
} > "$RESTORE_FILE"
log "Loading temp set via ipset restore"
ipset restore -f "$RESTORE_FILE"
log "Swapping temp set into place"
ipset swap "$TMP_SET" "$FINAL_SET"
log "Destroying old temp set"
ipset destroy "$TMP_SET"
log "Blacklist update complete"Assuming you've got the default WAN_IN and WAN_LOCAL firewall rules setup on your Edgerouter, you can run the following commands to deploy the ipset. Once it's setup on iptables then you're good to go. You may need to re-run these on reboot or using a cronjob or boot script.
iptables -C WAN_IN -m set --match-set BLACKLIST src -j DROP 2>/dev/null || \
iptables -I WAN_IN 1 -m set --match-set BLACKLIST src -j DROP
iptables -C WAN_LOCAL -m set --match-set BLACKLIST src -j DROP 2>/dev/null || \
iptables -I WAN_LOCAL 1 -m set --match-set BLACKLIST src -j DROPThe above script could be modified to subscribe to more lists, but I'm just using the three lists that work for me. I attempted to also sanitize the incoming IP data from the list, once it was working I added it to a shell script and installed this into the cronjob. Depending on which EdgeRouter you have, you'll need to consider how often to run this so you don't wear out your local storage.
Obviously the better solution would be to have a dedicated firewall, but I wanted to see if this was even possible and turns out, it is.