Created
July 15, 2025 08:49
-
-
Save filipgorczynski/19a3edf3ab77c6a99b457911f3214956 to your computer and use it in GitHub Desktop.
Unban IP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# unban-ip.sh ─ remove an IP address from Fail2Ban, ipset, and iptables | |
# Usage: sudo ./unban-ip.sh <IPv4_OR_IPv6> | |
set -euo pipefail | |
IP="${1:-}" | |
if [[ -z "$IP" ]]; then | |
echo "Usage: sudo $0 <IP>" | |
exit 1 | |
fi | |
echo "==> Unbanning $IP …" | |
######################################## | |
# 1. Fail2Ban | |
######################################## | |
if command -v fail2ban-client &>/dev/null; then | |
echo "→ Checking Fail2Ban..." | |
mapfile -t JAILS < <(fail2ban-client status 2>/dev/null | awk -F': ' '/Jail list/{gsub(/, */, "\n", $2); print $2}') | |
for jail in "${JAILS[@]}"; do | |
if fail2ban-client status "$jail" 2>/dev/null | grep -qw "$IP"; then | |
echo " • Unbanning from jail: $jail" | |
fail2ban-client set "$jail" unbanip "$IP" | |
fi | |
done | |
fi | |
######################################## | |
# 2. ipset | |
######################################## | |
if command -v ipset &>/dev/null; then | |
echo "→ Checking ipset sets..." | |
for set in $(ipset list -name); do | |
if ipset test "$set" "$IP" &>/dev/null; then | |
echo " • Removing from ipset: $set" | |
ipset del "$set" "$IP" | |
fi | |
done | |
fi | |
######################################## | |
# 3. iptables (legacy backend) | |
######################################## | |
echo "→ Checking iptables rules..." | |
TABLES=(filter nat mangle raw security) | |
for table in "${TABLES[@]}"; do | |
CHAINS=$(iptables -t "$table" -S | awk '/^-A/ {print $2}' | sort -u) | |
for chain in $CHAINS; do | |
# list line numbers backwards so deletion doesn’t re‑index earlier rules | |
mapfile -t LINES < <( | |
iptables -t "$table" -L "$chain" -n --line-numbers \ | |
| awk -v ip="$IP" '$0 ~ ip && ($4 == ip || $5 == ip) {print $1}' \ | |
| sort -rn | |
) | |
for line in "${LINES[@]}"; do | |
echo " • Deleting rule $table/$chain line $line" | |
iptables -t "$table" -D "$chain" "$line" | |
done | |
done | |
done | |
######################################## | |
# 4. Persist (optional but recommended) | |
######################################## | |
read -rp "Save new firewall state so it survives reboot? [y/N] " ANSWER | |
if [[ "$ANSWER" =~ ^[Yy]$ ]]; then | |
if command -v netfilter-persistent &>/dev/null; then | |
echo "→ Saving via netfilter‑persistent" | |
netfilter-persistent save | |
elif systemctl is-active --quiet iptables.service 2>/dev/null; then | |
echo "→ Saving via iptables service" | |
service iptables save | |
else | |
echo "→ No persistence helper found; rules will be gone after next reboot" | |
fi | |
else | |
echo "→ Skipped saving; change lasts until next reboot or firewall reload" | |
fi | |
echo "✅ Finished." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment