2.9 KiB
2.9 KiB
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:
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
<!DOCTYPE html>
<html>
<head>
<title>ModSecurity + Fail2Ban</title>
</head>
<body>
<h1>Güvenlik Duvarı Aktif!</h1>
</body>
</html>
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 = <HOST> -.* "(GET|POST).*HTTP.*" 429
ignoreregex =
mkdir -p nginx/html nginx/modsecurity fail2ban/filter.d docker-compose up -d