Secure Linux Firewall with IPSet Blocklists, Linux IPSet Firewall Automation,Dynamic IP Blocking on Linux with IPSet,Harden your Linux server with IPSet blocklists,Blocking Malicious IPs with IPSet and FireHOL Lists,Linux Security Guide: Banlist via IPSet,firewall με blocklists μέσω ipset σε Debian/Ubuntu.

Το ipset σου επιτρέπει να φτιάξεις μια λίστα (set) από IPs και να εφαρμόσεις έναν κανόνα firewall πάνω σε αυτήν. Έτσι μπορείς εύκολα να φορτώσεις blocklists χιλιάδων IPs χωρίς να γεμίσεις το firewal (UFW) με κανόνες.

Βήματα

Εγκατέστησε το ipset:


sudo apt update 
sudo apt install ipset iptables curl

Δημιούργησε μια λίστα (π.χ. banlist):
sudo ipset create banlist hash:ip 

Πρόσθεσε IPs στη λίστα:

sudo ipset add banlist 1.2.3.4 
sudo ipset add banlist 5.6.7.8

Αν έχεις αρχείο με IPs:

while read ip; do sudo ipset add banlist $ip; done < banlist.txt 


Σύνδεσε τη λίστα με το UFW (στην πραγματικότητα μέσω iptables που χρησιμοποιεί το UFW):

sudo iptables -I INPUT -m set --match-set banlist src -j DROP 

(Αυτό θα ρίχνει όλα τα πακέτα από IPs που είναι στη λίστα).
Αν θες να το κάνεις μόνιμο στο boot:
Βάζεις τους κανόνες στο /etc/ufw/before.rules
Ή χρησιμοποιείς systemd unit/script που επαναφορτώνει τη λίστα και τον κανόνα στο startup.

Παρακάτω θα βρεις έτοιμη υλοποίηση για Debian/Ubuntu που:

  • Κατεβάζει μία ή περισσότερες blocklists,
  • Τις φορτώνει σε ipset (IPv4 & IPv6),
  • Εφαρμόζει κανόνα DROP μέσω iptables/ip6tables (παίζει κανονικά με UFW),
  • Τις ενημερώνει αυτόματα με systemd timer,
  • Επιβιώνει από reboot χωρίς να πειράξουμε αρχεία του UFW.


1)Εγκατάσταση πακέτων

sudo apt update
sudo apt install -y ipset iptables

2) Αρχείο πηγών (λίστες) – μπορείς να το προσαρμόσεις


sudo mkdir -p /etc/ipset
sudo tee /etc/ipset/banlist.sources >/dev/null <<'EOF'
# One URL per line. Lines starting with # are ignored.
# You can add or remove URLs as you like.
# Example sources (FireHOL level1 + blocklist.de all):
https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset
https://lists.blocklist.de/lists/all.txt
EOF

3) Script ενημέρωσης & φόρτωσης ipset Κανουμε edit το παρακάτω αρχείο


nano /usr/local/bin/update-banlists.sh
και προσθέτουμε τον κώδικα

#!/usr/bin/env bash
set -euo pipefail

# ==============================
# Config (paths)
# ==============================
SOURCES_FILE="/etc/ipset/banlist.sources"
STATE_DIR="/var/lib/ipset"
TMP_DIR="$(mktemp -d)"
IPV4_SET="banlist"
IPV6_SET="banlist6"
SAVE_FILE_V4="${STATE_DIR}/${IPV4_SET}.save"
SAVE_FILE_V6="${STATE_DIR}/${IPV6_SET}.save"

# ==============================
# Helpers
# ==============================
log() { echo "[update-banlists] $*"; }

ensure_prereqs() {
  command -v ipset >/dev/null || { echo "ipset not found"; exit 1; }
  mkdir -p "$STATE_DIR"
}

ensure_sets_exist() {
  # Create sets if missing (idempotent)
  if ! ipset list -n | grep -qx "$IPV4_SET"; then
    ipset create "$IPV4_SET" hash:ip family inet timeout 0
  fi
  if ! ipset list -n | grep -qx "$IPV6_SET"; then
    ipset create "$IPV6_SET" hash:ip family inet6 timeout 0
  fi
}

download_sources() {
  local line url out="${TMP_DIR}/combined.txt"
  : > "$out"
  while IFS= read -r line; do
    url="$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
    [[ -z "$url" ]] && continue
    [[ "$url" =~ ^# ]] && continue
    log "Downloading $url"
    if curl -fsSL "$url" | sed 's/\r$//' >> "$out"; then
      :
    else
      log "WARN: failed to fetch $url"
    fi
  done < "$SOURCES_FILE"

  # Keep only lines that look like IP (v4 or v6) or CIDR
  # Many lists already are just IP/CIDR per line.
  grep -E -i '^[0-9a-f:.]+(/[0-9]+)?$' "$out" | sed 's/ //g' | sort -u > "${TMP_DIR}/ips.txt"
}

flush_and_reload_sets() {
  # We'll rebuild using temporary sets to avoid race conditions
  local TMP_V4="${IPV4_SET}_new"
  local TMP_V6="${IPV6_SET}_new"

  # Create temp sets
  ipset create "$TMP_V4" hash:ip family inet  || true
  ipset create "$TMP_V6" hash:ip family inet6 || true

  # Populate temp sets
  while IFS= read -r ip; do
    [[ -z "$ip" ]] && continue
    if [[ "$ip" == *:* ]]; then
      # Likely IPv6
      ipset add "$TMP_V6" "$ip" 2>/dev/null || true
    else
      # Likely IPv4
      ipset add "$TMP_V4" "$ip" 2>/dev/null || true
    fi
  done < "${TMP_DIR}/ips.txt"

  # Swap
  ipset swap "$TMP_V4" "$IPV4_SET"
  ipset swap "$TMP_V6" "$IPV6_SET"

  # Destroy temp sets
  ipset destroy "$TMP_V4" || true
  ipset destroy "$TMP_V6" || true

  # Save to disk
  ipset save "$IPV4_SET" > "$SAVE_FILE_V4"
  ipset save "$IPV6_SET" > "$SAVE_FILE_V6"
}

apply_firewall_rules() {
  # Ensure iptables rules exist (idempotent)
  if ! iptables -C INPUT -m set --match-set "$IPV4_SET" src -j DROP 2>/dev/null; then
    iptables -I INPUT -m set --match-set "$IPV4_SET" src -j DROP
  fi
  if command -v ip6tables >/dev/null; then
    if ! ip6tables -C INPUT -m set --match-set "$IPV6_SET" src -j DROP 2>/dev/null; then
      ip6tables -I INPUT -m set --match-set "$IPV6_SET" src -j DROP
    fi
  fi
}

restore_from_disk_if_empty() {
  # If sets are empty and we have a saved copy, restore
  if [ "$(ipset list "$IPV4_SET" | awk '/Number of entries:/ {print $4}')" = "0" ] 2>/dev/null && [ -s "$SAVE_FILE_V4" ]; then
    ipset restore < "$SAVE_FILE_V4" || true
  fi
  if [ "$(ipset list "$IPV6_SET" | awk '/Number of entries:/ {print $4}')" = "0" ] 2>/dev/null && [ -s "$SAVE_FILE_V6" ]; then
    ipset restore < "$SAVE_FILE_V6" || true
  fi
}

main() {
  ensure_prereqs
  ensure_sets_exist
  # Make sure firewall rules exist before/after update
  apply_firewall_rules
  restore_from_disk_if_empty

  download_sources
  flush_and_reload_sets
  apply_firewall_rules

  log "Done. Entries:"
  ipset list "$IPV4_SET" | awk '/Number of entries:/ {print "IPv4:", $4}'
  ipset list "$IPV6_SET" | awk '/Number of entries:/ {print "IPv6:", $4}'
}

trap 'rm -rf "$TMP_DIR"' EXIT
main

Κάνουμε εκτελέσιμο το update-banlists.sh

sudo chmod +x /usr/local/bin/update-banlists.sh
sudo mkdir -p /var/lib/ipset
και δημιουργουμε έναν φάκελο οπου θα μπουν τα 2 αρχεία banlist.save & banlist6.save που εμπεριέχουν τις banαρισμένες IP

sudo mkdir -p /var/lib/ipset

4) Υπηρεσία εκκίνησης (εφαρμογή κανόνων στο boot) Φτιαχνουμε το αρχείο ipset-banlist.service


sudo nano /etc/systemd/system/ipset-banlist.service
και βάζουμε τα παρακάτω.

[Unit]
Description=Create/restore ipset ban lists and enforce firewall rules
After=network-online.target ufw.service
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/update-banlists.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Κάνουμε το αρχείο να τρέχει ipset-banlist.service σαν υπηρεσία

sudo systemctl daemon-reload
sudo systemctl enable --now ipset-banlist.service

5) Προγραμματισμένη αυτόματη ενημέρωση (ημερησίως)

Πάμε στο/etc/systemd/system/ipset-banlist-update.service

nano /etc/systemd/system/ipset-banlist-update.service
και επικόλληση το παρακάτω

[Unit]
Description=Update ipset ban lists from remote sources

[Service]
Type=oneshot
ExecStart=/usr/local/bin/update-banlists.sh
Και ορίζουμε και τον χρονοδιακόπτη

nano /etc/systemd/system/ipset-banlist-update.timer
και επικόλληση το παρακάτω

[Unit]
Description=Run ipset ban lists update daily

[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=600

[Install]
WantedBy=timers.target
6) Έλεγχος λειτουργίας
Τρέξε χειροκίνητα μία ενημέρωση:

sudo /usr/local/bin/update-banlists.sh
Δες πόσες εγγραφές φορτώθηκαν:

sudo ipset list banlist  | awk '/Number of entries:/ {print}'
sudo ipset list banlist6 | awk '/Number of entries:/ {print}'
Επιβεβαίωσε ότι οι κανόνες υπάρχουν:

sudo iptables -S | grep match-set || true
sudo ip6tables -S | grep match-set || true
Έλεγχος των timers:

systemctl list-timers | grep ipset-banlist-update || true

Σημειώσεις / Καλές Πρακτικές 

UFW συμβατότητα: Δεν τροποποιούμε τα αρχεία του UFW. Οι κανόνες iptables/ip6tables εφαρμόζονται ξεχωριστά και ισχύουν σε κάθε boot από το ipset-banlist.service. Αν κάνεις ufw reload, το service ή το timer ξανατρέχουν και τους ξανασφαλίζουν.
 
Πηγές: Μπορείς να προσθέσεις/αφαιρέσεις URLs στο /etc/ipset/banlist.sources. Το script διαβάζει κάθε γραμμή και προσθέτει IPs/CIDRs.
 
IPv6: Καλύπτεται με ξεχωριστό set (banlist6) και κανόνα ip6tables.
Απαλοιφή: Αν χρειαστεί κάποια IP να επιτραπεί, μπορείς να την αφαιρέσεις από το set:

sudo ipset del banlist 203.0.113.10
* Παρατήρηση: Θα ξαναμπεί στην επόμενη ενημέρωση αν υπάρχει στη λίστα


Tags: Secure Linux Firewall with IPSet Blocklists, Linux IPSet Firewall Automation,Dynamic IP Blocking on Linux with IPSet,Harden your Linux server with IPSet blocklists,Blocking Malicious IPs with IPSet and FireHOL Lists,Linux Security Guide: Banlist via IPSet,firewall με blocklists μέσω ipset σε Debian/Ubuntu.