Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions fail2ban/filter.d/nginx-4xx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Fail2Ban filter for Nginx 4xx responses
# ============================================================================
# Matches 401 Unauthorized, 403 Forbidden, 404 Not Found responses
# These indicate failed auth attempts, blocked access, or probing
#
# Protects all services behind nginx reverse proxy:
# - Immich (DOMAIN1)
# - Paperless (DOMAIN2)
# - FreshRSS (DOMAIN3)
# - Home Assistant (DOMAIN4)
# ============================================================================

[Definition]

# Match 401/403/404 responses
# Log format: IP - - [timestamp] "METHOD /path HTTP/version" STATUS size "referer" "user-agent"
failregex = ^<HOST> -.* - \[[^\]]*\] "(?:GET|POST|HEAD|PUT|DELETE) \S* HTTP\/1\.[01]" (401|403|404) \d+ ".*" ".*"$

# Ignore legitimate 404s (favicons, robots.txt, etc.)
ignoreregex = ^<HOST> .* "(GET|HEAD) /(favicon\.ico|robots\.txt|apple-touch-icon|site\.webmanifest) HTTP
16 changes: 0 additions & 16 deletions fail2ban/filter.d/nginx-auth-failed.conf

This file was deleted.

14 changes: 0 additions & 14 deletions fail2ban/filter.d/nginx-forbidden-scan.conf

This file was deleted.

3 changes: 0 additions & 3 deletions fail2ban/filter.d/nginx-immich-proxy.conf

This file was deleted.

20 changes: 20 additions & 0 deletions fail2ban/filter.d/nginx-malicious-uri.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Fail2Ban filter for malicious URI patterns
# ============================================================================
# Matches requests for common attack vectors regardless of HTTP status code
# Attackers probing for vulnerabilities often get 200/301 on some paths
#
# Catches:
# - WordPress attacks (wp-admin, wp-login, xmlrpc.php)
# - Database admin tools (phpmyadmin, mysql, adminer)
# - Config file exposure (.env, .git, config, backup)
# - Shell/backdoor attempts (shell, setup, install)
# ============================================================================

[Definition]

# Match malicious URIs regardless of status code
# These paths should never be accessed on a legitimate homelab
failregex = ^<HOST> -.*"(?:GET|POST|HEAD) /[^"]*(?:phpmyadmin|phpadmin|pma|admin|mysql|database|\.env|wp-login|wp-admin|shell|config|backup|setup|install|xmlrpc\.php|\.git).*".*$

# No ignore patterns - all matches are suspicious
ignoreregex =
14 changes: 0 additions & 14 deletions fail2ban/filter.d/nginx-rate-limit-abuse.conf

This file was deleted.

49 changes: 0 additions & 49 deletions fail2ban/jail.d/freshrss.local

This file was deleted.

39 changes: 6 additions & 33 deletions fail2ban/jail.d/homeassistant.local
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# ============================================================================
# Fail2Ban Jail for Home Assistant (DOMAIN4)
# Fail2Ban Jail for Home Assistant Authentication
# ============================================================================
# Protects Home Assistant home automation hub from:
# - Brute-force login attempts (monitored via HA's internal log)
# - Rate limiting abuse (503 responses via nginx)
# - Path scanning/reconnaissance (403/404 on suspicious paths via nginx)
# Home Assistant returns HTTP 200 even for failed logins, so we cannot use
# nginx access logs. Instead, we monitor HA's internal log file.
#
# NOTE: Home Assistant returns HTTP 200 even for failed logins, so we monitor
# HA's own log file for authentication failures instead of nginx access logs.
# Note: Rate limiting and scan protection are handled by nginx-4xx and
# nginx-malicious-uri jails (via nginx access.log)
# ============================================================================

[homeassistant-auth]
Expand All @@ -20,34 +18,9 @@ logpath = /home/stefan/docker/homeassistant/homeassistant/config/home-assistant.
filter = homeassistant-auth
# Ban duration: 1 hour
bantime = 3600
# Max failed attempts before ban (set lower than HA's internal limit of 5)
# This ensures fail2ban blocks at firewall BEFORE HA's app-level ban kicks in
# Max failed attempts before ban (lower than HA's internal limit of 5)
maxretry = 3
# Time window for counting failures (10 minutes)
findtime = 600
# Target DOCKER-USER chain (blocks traffic before Docker routing)
chain = DOCKER-USER

[homeassistant-rate-limit]
enabled = true
ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
logpath = /home/stefan/docker/proxy/nginx/logs/access.log
filter = nginx-rate-limit-abuse
# Ban for 30 minutes
bantime = 1800
# Moderate threshold (HA dashboards can generate many requests)
maxretry = 30
findtime = 300
chain = DOCKER-USER

[homeassistant-scan]
enabled = true
ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
logpath = /home/stefan/docker/proxy/nginx/logs/access.log
filter = nginx-forbidden-scan
# Ban for 24 hours (reconnaissance is serious)
bantime = 86400
# Low threshold - scanners probe many paths
maxretry = 10
findtime = 600
chain = DOCKER-USER
49 changes: 0 additions & 49 deletions fail2ban/jail.d/immich.local

This file was deleted.

40 changes: 40 additions & 0 deletions fail2ban/jail.d/nginx.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ============================================================================
# Fail2Ban Jails for Nginx Reverse Proxy
# ============================================================================
# Protects ALL services behind nginx (Immich, Paperless, FreshRSS, Home Assistant)
# Uses shared nginx access.log - one ban blocks attacker from all services
# ============================================================================

[nginx-4xx]
enabled = true
# Ignore private networks
ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
# Nginx access log (shared by all services)
logpath = /home/stefan/docker/proxy/nginx/logs/access.log
# Filter for 401/403/404 responses
filter = nginx-4xx
# Ban duration: 24 hours
bantime = 24h
# Max failed attempts before ban
maxretry = 3
# Time window for counting failures (10 minutes)
findtime = 600
# Target DOCKER-USER chain (blocks traffic before Docker routing)
chain = DOCKER-USER

[nginx-malicious-uri]
enabled = true
# Ignore private networks
ignoreip = 127.0.0.1/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
# Nginx access log (shared by all services)
logpath = /home/stefan/docker/proxy/nginx/logs/access.log
# Filter for malicious URI patterns (wp-admin, .env, phpmyadmin, etc.)
filter = nginx-malicious-uri
# Ban duration: 24 hours
bantime = 24h
# Max attempts before ban (low threshold - these are clearly malicious)
maxretry = 3
# Time window for counting attempts (10 minutes)
findtime = 600
# Target DOCKER-USER chain (blocks traffic before Docker routing)
chain = DOCKER-USER
49 changes: 0 additions & 49 deletions fail2ban/jail.d/paperless.local

This file was deleted.