From 61366e403921926efe1de1068976c85bddde3e87 Mon Sep 17 00:00:00 2001 From: Adam French Date: Mon, 9 Mar 2026 14:18:01 +0000 Subject: [PATCH] Add fail2ban to stop these malicious ips ;-; --- docker-compose.yml | 16 ++++++++++++++++ fail2ban/filter.d/nginx-4xx.conf | 6 ++++++ fail2ban/filter.d/nginx-login.conf | 5 +++++ fail2ban/jail.d/defaults.conf | 4 ++++ fail2ban/jail.d/nginx-4xx.conf | 7 +++++++ fail2ban/jail.d/nginx-login.conf | 7 +++++++ fail2ban/jail.d/sshd.conf | 7 +++++++ nginx/Dockerfile | 3 +++ nginx/entrypoint.sh | 4 ++++ 9 files changed, 59 insertions(+) create mode 100644 fail2ban/filter.d/nginx-4xx.conf create mode 100644 fail2ban/filter.d/nginx-login.conf create mode 100644 fail2ban/jail.d/defaults.conf create mode 100644 fail2ban/jail.d/nginx-4xx.conf create mode 100644 fail2ban/jail.d/nginx-login.conf create mode 100644 fail2ban/jail.d/sshd.conf diff --git a/docker-compose.yml b/docker-compose.yml index d6d63ec..bce6392 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,7 @@ networks: volumes: dbdata: uploads: + nginx-logs: services: nginx: @@ -27,6 +28,7 @@ services: - ./certbot/conf:/etc/letsencrypt - ./certbot/www:/var/www/certbot - uploads:/uploads + - nginx-logs:/var/log/nginx certbot: image: certbot/certbot @@ -123,3 +125,17 @@ services: - "2222:2222" depends_on: - db + + fail2ban: + image: crazymax/fail2ban:latest + container_name: fail2ban + network_mode: host + cap_add: + - NET_ADMIN + - NET_RAW + restart: always + volumes: + - ./fail2ban/jail.d:/data/jail.d + - ./fail2ban/filter.d:/data/filter.d + - nginx-logs:/var/log/nginx:ro + - /var/log/auth.log:/var/log/auth.log:ro diff --git a/fail2ban/filter.d/nginx-4xx.conf b/fail2ban/filter.d/nginx-4xx.conf new file mode 100644 index 0000000..8f271cd --- /dev/null +++ b/fail2ban/filter.d/nginx-4xx.conf @@ -0,0 +1,6 @@ +[Definition] +# Matches excessive 4xx responses (scanners probing for common paths) +# Log format: $remote_addr "$request" $status rt=$request_time +failregex = ^ ".*" 4\d\d rt= +ignoreregex = "GET /favicon\.ico HTTP + "GET /robots\.txt HTTP diff --git a/fail2ban/filter.d/nginx-login.conf b/fail2ban/filter.d/nginx-login.conf new file mode 100644 index 0000000..113be6b --- /dev/null +++ b/fail2ban/filter.d/nginx-login.conf @@ -0,0 +1,5 @@ +[Definition] +# Matches failed login attempts (401/403) on POST to /auth/login +# Log format: $remote_addr "$request" $status rt=$request_time +failregex = ^ "POST .*/auth/login HTTP/.*" (401|403) rt= +ignoreregex = diff --git a/fail2ban/jail.d/defaults.conf b/fail2ban/jail.d/defaults.conf new file mode 100644 index 0000000..7d46cb3 --- /dev/null +++ b/fail2ban/jail.d/defaults.conf @@ -0,0 +1,4 @@ +[DEFAULT] +# Ignore localhost; add your home IP after the comma +ignoreip = 127.0.0.1/8 ::1 +banaction = iptables-multiport diff --git a/fail2ban/jail.d/nginx-4xx.conf b/fail2ban/jail.d/nginx-4xx.conf new file mode 100644 index 0000000..72acc36 --- /dev/null +++ b/fail2ban/jail.d/nginx-4xx.conf @@ -0,0 +1,7 @@ +[nginx-4xx] +enabled = true +filter = nginx-4xx +logpath = /var/log/nginx/access.log +maxretry = 20 +findtime = 300 +bantime = 3600 diff --git a/fail2ban/jail.d/nginx-login.conf b/fail2ban/jail.d/nginx-login.conf new file mode 100644 index 0000000..4732323 --- /dev/null +++ b/fail2ban/jail.d/nginx-login.conf @@ -0,0 +1,7 @@ +[nginx-login] +enabled = true +filter = nginx-login +logpath = /var/log/nginx/access.log +maxretry = 5 +findtime = 600 +bantime = 3600 diff --git a/fail2ban/jail.d/sshd.conf b/fail2ban/jail.d/sshd.conf new file mode 100644 index 0000000..97c7943 --- /dev/null +++ b/fail2ban/jail.d/sshd.conf @@ -0,0 +1,7 @@ +[sshd] +enabled = true +filter = sshd +logpath = /var/log/auth.log +maxretry = 5 +findtime = 600 +bantime = 3600 diff --git a/nginx/Dockerfile b/nginx/Dockerfile index 45c71b0..fefd4f0 100644 --- a/nginx/Dockerfile +++ b/nginx/Dockerfile @@ -28,6 +28,9 @@ COPY nginx.conf.template /etc/nginx/nginx.conf.template COPY nginx_setup.conf.template /etc/nginx/nginx_setup.conf.template COPY nginx_dev.conf.template /etc/nginx/nginx_dev.conf.template COPY robots.txt /etc/nginx/html/robots.txt +# Remove default symlinks so logs write to real files on the shared volume +RUN unlink /var/log/nginx/access.log && unlink /var/log/nginx/error.log + COPY entrypoint.sh /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/nginx/entrypoint.sh b/nginx/entrypoint.sh index 872ed1c..806e4db 100755 --- a/nginx/entrypoint.sh +++ b/nginx/entrypoint.sh @@ -17,6 +17,10 @@ else envsubst '${DOMAIN}' < /etc/nginx/nginx_setup.conf.template > /etc/nginx/nginx.conf fi +# Ensure log directory and files exist on the shared volume +mkdir -p /var/log/nginx +touch /var/log/nginx/access.log /var/log/nginx/error.log + # Ensure uploads directory and files are readable by nginx worker processes chmod 755 /uploads 2>/dev/null || true chmod -R a+rX /uploads 2>/dev/null || true