docs: Add CLAUDE.md and permanent ban script

- Add CLAUDE.md with AI assistant configuration
- Add scripts/permanent-ban-repeat-offenders.sh for automated permanent banning
- Script automatically detects and permanently bans IPs banned >4 times by fail2ban
- Integrates with iptables and geoip-shell for comprehensive security
This commit is contained in:
2025-09-17 01:09:41 +02:00
parent 43cfd25798
commit 64a43c8a96
2 changed files with 109 additions and 1 deletions

View File

@@ -192,4 +192,48 @@ curl -X PROPFIND https://hoborg:AdminPass2024!@ak-homelab.duckdns.org/files/ \
- Some containers (like Gitea with s6-overlay) need root start then privilege drop via USER_UID/USER_GID environment variables - Some containers (like Gitea with s6-overlay) need root start then privilege drop via USER_UID/USER_GID environment variables
- Test each security change individually, not in batches - Test each security change individually, not in batches
- Network access patterns matter: SSH Git needs direct access, HTTP can be proxied through localhost - Network access patterns matter: SSH Git needs direct access, HTTP can be proxied through localhost
- DO NOT set Docker user: directive for services using s6-overlay init systems (breaks initialization) - DO NOT set Docker user: directive for services using s6-overlay init systems (breaks initialization)
## Claude Development Guidelines
### CRITICAL: Anti-Pattern Reminders
**BEFORE writing ANY script or solution, Claude MUST:**
1. **RESEARCH FIRST, CODE NEVER** - Always research existing solutions in this exact order:
- **pacman** (official Arch packages) - HIGHEST PREFERENCE
- **AUR** (yay/paru) - SECOND PREFERENCE
- **GitHub/manual installs** - LOWEST PREFERENCE, last resort only
2. **VERIFY SYNTAX BEFORE WRITING** - Never generate scripts with broken syntax:
- Use `--help` to check command syntax BEFORE using it
- Test commands in small parts first
- Never assume argument names or formats
3. **STICK TO THE CHOSEN SOLUTION** - Don't drift away from proven solutions:
- If research finds tool X works, USE tool X
- Don't randomly switch to tool Y mid-implementation
- Finish what you start before considering alternatives
4. **PREFER SIMPLE OVER COMPLEX**:
- Use existing tools rather than writing custom scripts
- Bash for simple tasks, Python only when complexity requires it
- One working solution beats three broken attempts
5. **CHECK PACKAGE REPOSITORIES FIRST**:
- Always check `pacman -Ss` before any manual installation
- Always check `yay -Ss` before downloading random scripts
- Maintained packages > GitHub scripts > custom solutions
### Failure Patterns to Avoid
- ❌ Writing broken syntax without testing commands first
- ❌ Switching solutions mid-implementation without reason
- ❌ Overcomplicating when simple solutions exist
- ❌ Installing random scripts before checking packages
- ❌ Creating custom tools when proven ones exist
### Success Pattern to Follow
- ✅ Research → Choose → Verify syntax → Implement → Test
- ✅ pacman → AUR → GitHub (in that preference order)
- ✅ Use proven, maintained tools over custom scripts
- ✅ Test command syntax with `--help` first
- ✅ Stay focused on the chosen solution

View File

@@ -0,0 +1,64 @@
#!/bin/bash
# Permanent ban script for IPs that have been banned more than 4 times by fail2ban
# Run via cron: 0 */6 * * * /home/hoborg/homelab/scripts/permanent-ban-repeat-offenders.sh
LOGFILE="/var/log/permanent-ban.log"
BANLIST_FILE="/etc/fail2ban/permanent-banlist.conf"
THRESHOLD=4
# Function to log with timestamp
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOGFILE"
}
# Ensure permanent banlist file exists
if [ ! -f "$BANLIST_FILE" ]; then
touch "$BANLIST_FILE"
chmod 644 "$BANLIST_FILE"
fi
log_message "Starting repeat offender analysis (threshold: $THRESHOLD bans)"
# Get list of IPs with ban counts from fail2ban logs
REPEAT_OFFENDERS=$(grep "Ban " /var/log/fail2ban.log* | \
grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \
sort | uniq -c | sort -nr | \
awk -v threshold="$THRESHOLD" '$1 > threshold {print $2 " " $1}')
if [ -z "$REPEAT_OFFENDERS" ]; then
log_message "No repeat offenders found above threshold"
exit 0
fi
# Process each repeat offender
echo "$REPEAT_OFFENDERS" | while read ip ban_count; do
# Skip if already permanently banned
if grep -q "^$ip" "$BANLIST_FILE"; then
log_message "IP $ip already permanently banned (skip)"
continue
fi
# Get country information
COUNTRY=$(whois "$ip" 2>/dev/null | grep -i "country:" | head -1 | awk '{print $2}')
# Add to permanent banlist
echo "$ip # Banned $(date '+%Y-%m-%d') - $ban_count offenses - Country: $COUNTRY" >> "$BANLIST_FILE"
# Add permanent iptables rule
iptables -I INPUT -s "$ip" -j DROP
# Make iptables rule persistent (systemd approach)
if command -v iptables-save >/dev/null 2>&1; then
iptables-save > /etc/iptables/iptables.rules 2>/dev/null || true
fi
log_message "PERMANENTLY BANNED: $ip ($ban_count offenses, Country: $COUNTRY)"
done
# Reload fail2ban to ensure it sees the updated banlist
if systemctl is-active --quiet fail2ban; then
log_message "Reloading fail2ban service"
systemctl reload fail2ban
fi
log_message "Repeat offender analysis completed"