| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- #!/usr/bin/env bash
- # Pull the IRDB blocklist and atomic-replace an ipset.
- #
- # Usage (cron-friendly):
- # IRDB_URL=http://localhost:8081 IRDB_TOKEN=irdb_con_... \
- # IPSET_NAME=irdb-blocked examples/consumers/iptables-restore.sh
- #
- # Prerequisites:
- # - the ipset is referenced by an iptables rule, e.g.
- # iptables -I INPUT -m set --match-set irdb-blocked src -j DROP
- # - ipset and iptables-restore are installed
- # - the consumer's policy returns IPv4 entries (or a mixed set;
- # this script filters per family)
- #
- # Atomic-replace pattern: build a swap set in memory, swap, destroy
- # old. Even an in-flight rule keeps working through the swap.
- set -euo pipefail
- : "${IRDB_URL:?must be set}"
- : "${IRDB_TOKEN:?must be set}"
- IPSET_NAME="${IPSET_NAME:-irdb-blocked}"
- TYPE="${IPSET_TYPE:-hash:net}"
- TIMEOUT="${IRDB_TIMEOUT:-30}"
- LIST=$(curl -fsS --max-time "$TIMEOUT" \
- -H "Authorization: Bearer $IRDB_TOKEN" \
- -H "Accept: text/plain" \
- "$IRDB_URL/api/v1/blocklist")
- # Split into v4 / v6 — this script handles v4 only by default. Drop
- # v6 entries if your ipset is `hash:net` family inet; mirror this
- # script for inet6 if you need both.
- SWAP="${IPSET_NAME}-swap"
- # Re-create the swap set; ignore "Set cannot be created: set with the
- # same name already exists" since we destroy unconditionally below.
- ipset create "$SWAP" "$TYPE" -exist
- ipset flush "$SWAP"
- while IFS= read -r line; do
- [ -z "$line" ] && continue
- case "$line" in
- *:*) continue ;; # skip v6
- *) ipset add "$SWAP" "$line" -exist ;;
- esac
- done <<<"$LIST"
- # Make the existing target set if absent so the swap target is valid.
- ipset create "$IPSET_NAME" "$TYPE" -exist
- ipset swap "$SWAP" "$IPSET_NAME"
- ipset destroy "$SWAP"
- COUNT=$(ipset list -t "$IPSET_NAME" | awk -F': ' '/^Number of entries:/ {print $2}')
- echo "irdb-blocklist updated: $COUNT entries in $IPSET_NAME"
|