diff --git a/unban-ip-from-redis-cache.sh b/unban-ip-from-redis-cache.sh new file mode 100755 index 0000000..e136131 --- /dev/null +++ b/unban-ip-from-redis-cache.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash +# nextcloud-unban.sh +# Interaktives Skript zum gezielten Entfernen von Nextcloud-Login-/Ratelimit-Keys aus Redis +# Speichert KEINE Zugangsdaten; verwendet redis-cli (muss im PATH liegen). + +set -euo pipefail +IFS=$'\n\t' + +# Farben +NC="\033[0m" +BOLD="\033[1m" +GREEN="\033[32m" +YELLOW="\033[33m" +RED="\033[31m" +CYAN="\033[36m" + +function header() { + echo -e "${BOLD}${CYAN}================ Nextcloud Redis Unban Helper ================${NC}\n" +} + +function footer() { + echo -e "\n${BOLD}${CYAN}=============================================================${NC}\n" +} + +function check_redis() { + if ! command -v redis-cli >/dev/null 2>&1; then + echo -e "${RED}redis-cli ist nicht installiert oder nicht im PATH. Bitte installiere redis-tools oder füge redis-cli hinzu.${NC}" >&2 + exit 2 + fi + # quick ping + if ! redis-cli PING >/dev/null 2>&1; then + echo -e "${RED}Konnte Redis nicht erreichen. Stelle sicher, dass redis läuft und redis-cli Standardverbindung funktioniert.${NC}" >&2 + exit 3 + fi +} + +function read_ip() { + local prompt="$1" + local ip + while true; do + read -rp "$prompt" ip + ip="${ip// /}" + if [[ -z "$ip" ]]; then + echo -e "${YELLOW}Keine Eingabe erkannt — bitte eine IPv4- oder IPv6-Adresse eingeben.${NC}" + continue + fi + # basic validation: at least contains digits and ':' (for IPv6) or '.' (for IPv4) + if [[ "$ip" =~ [0-9] ]] && ( [[ "$ip" == *":"* ]] || [[ "$ip" == *"."* ]] ); then + echo "$ip" + return 0 + else + echo -e "${YELLOW}Ungültiges Format. Bitte IPv4 (z.B. 1.2.3.4) oder IPv6 (z.B. 2003:ab:...) eingeben.${NC}" + fi + done +} + +function list_keys_for_ip() { + local ip="$1" + # pattern: any key that contains the IP + redis-cli --scan --pattern "*${ip}*" | sed '/^$/d' +} + +function confirm() { + local prompt="$1" + local yn + while true; do + read -rp "$prompt [j/N]: " yn + case "$yn" in + [JjYy]*) return 0 ;; + [Nn]* | "" ) return 1 ;; + *) echo "Bitte mit j/ja oder n/nein antworten." ;; + esac + done +} + +# --- main --- +header +check_redis + +echo -e "Dieses Skript sucht Redis-Keys, die deine angegebene IP enthalten (z.B. Ratelimit-Keys von Nextcloud)\n" + +IP=$(read_ip "Gib die IP-Adresse ein, die du freigeben möchtest: ") + +echo -e "\n${BOLD}Suche nach passenden Redis-Keys für:${NC} ${GREEN}${IP}${NC}\n" + +mapfile -t KEYS < <(list_keys_for_ip "$IP") || true + +if [ ${#KEYS[@]} -eq 0 ]; then + echo -e "${YELLOW}Keine Keys gefunden, die '${IP}' enthalten.${NC}\n" + if confirm "Möchtest du stattdessen alle Keys anzeigen, die das Wort 'login' enthalten?"; then + redis-cli --scan --pattern "*login*" | sed '/^$/d' || true + fi + footer + exit 0 +fi + +# schöne Ausgabe +echo -e "${BOLD}Gefundene Keys:${NC} (${#KEYS[@]})\n" +for k in "${KEYS[@]}"; do + echo -e " - ${CYAN}${k}${NC}" +done + +# bestimme Länge für Box +echo +if confirm "Diese ${#KEYS[@]} Keys wirklich löschen?"; then + # Löschen + deleted=0 + failed=0 + for k in "${KEYS[@]}"; do + if redis-cli DEL "$k" >/dev/null 2>&1; then + ((deleted++)) + echo -e "${GREEN}Gelöscht:${NC} $k" + else + ((failed++)) + echo -e "${RED}Fehler beim Löschen:${NC} $k" + fi + done + + echo -e "\n${BOLD}Ergebnis:${NC} ${GREEN}$deleted gelöschte Keys${NC}, ${RED}$failed fehlgeschlagen${NC}." +else + echo -e "${YELLOW}Abgebrochen — keine Keys wurden gelöscht.${NC}" +fi + +footer + +exit 0 +