```docker-compose.yml version: '3.8' services: nginx: image: owasp/modsecurity:nginx container_name: secure_nginx ports: - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/html:/usr/share/nginx/html:ro - ./nginx/modsecurity/modsecurity.conf:/etc/modsecurity/modsecurity.conf:ro - ./nginx/log:/var/log/nginx restart: always fail2ban: image: crazymax/fail2ban:latest container_name: fail2ban volumes: - ./fail2ban/jail.local:/data/jail.local:ro - ./fail2ban/filter.d:/data/filter.d:ro - ./nginx/log:/var/log/nginx:ro - fail2ban-data:/data restart: always cap_add: - NET_ADMIN - NET_RAW volumes: fail2ban-data: ``` ```conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; modsecurity on; modsecurity_rules_file /etc/modsecurity/modsecurity.conf; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; limit_req_zone $binary_remote_addr zone=limit1:10m rate=5r/s; server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; location / { limit_req zone=limit1 burst=10 nodelay; try_files $uri $uri/ =404; } } } ``` nginx/html/index.html ``` ModSecurity + Fail2Ban

Güvenlik Duvarı Aktif!

``` nginx/modsecurity/modsecurity.conf ``` SecRuleEngine On SecRequestBodyAccess On SecResponseBodyAccess Off SecRule REQUEST_HEADERS:User-Agent "curl" "id:10001,phase:1,deny,status:403,msg:'Curl client blocked'" # Basit rate limit sayacı SecAction "id:10010,phase:1,initcol:ip=%{REMOTE_ADDR},pass,nolog" SecRule IP:REQCOUNT "@gt 20" "id:10011,phase:2,deny,status:429,msg:'Too many requests'" SecAction "id:10012,phase:2,pass,nolog,setvar:ip.reqcount=+1" ``` fail2ban/jail.local ``` [nginx-req-limit] enabled = true filter = nginx-req-limit action = iptables[name=HTTP, port=http, protocol=tcp] logpath = /var/log/nginx/access.log maxretry = 5 findtime = 60 bantime = 3600 ``` fail2ban/filter.d/nginx-req-limit.conf ``` [Definition] failregex = -.* "(GET|POST).*HTTP.*" 429 ignoreregex = ``` mkdir -p nginx/html nginx/modsecurity fail2ban/filter.d docker-compose up -d