# Определяем переменную для блокировки map $remote_addr $blocked_ip { default 0; include /etc/nginx/blocked_ips.map; } # Определяем типы запросов map $request_uri $request_type { default "general"; # API endpoints ~*^/api/ "api"; # Auth endpoints ~*^/(login|register|password-reset|auth|forgot-password|verify-email) "auth"; # Admin endpoints ~*^/(admin|dashboard|cp|control-panel|manager) "admin"; # Static files by extension ~*\.(jpg|jpeg|png|gif|ico|css|js|woff2?|ttf|eot|svg|pdf|zip|mp4|webm)$ "static"; # Static files by directory ~*^/(storage|uploads|media|images|css|js|fonts)/ "static"; } server { listen 80; server_name _; root /var/www/public; index index.php index.html; # ========== ОСНОВНЫЕ НАСТРОЙКИ БЕЗОПАСНОСТИ ========== # Защитные заголовки add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # ========== ПРЕДВАРИТЕЛЬНЫЕ ПРОВЕРКИ ========== # Если IP в черном списке if ($blocked_ip) { return 444; } # Блокировка пустых User-Agent if ($http_user_agent = "") { return 444; } # Блокировка нестандартных методов if ($request_method !~ ^(GET|HEAD|POST|OPTIONS)$) { return 444; } # ========== ГЛОБАЛЬНЫЕ ОГРАНИЧЕНИЯ ========== limit_conn conn_limit_per_ip 25; limit_req zone=req_limit_per_ip burst=30 delay=15; # ========== СТАТИЧЕСКИЕ ФАЙЛЫ ========== location ~* \.(jpg|jpeg|png|gif|ico|webp|avif)$ { limit_req zone=static_limit burst=100 nodelay; limit_conn conn_limit_per_ip 100; expires 1y; add_header Cache-Control "public, immutable"; add_header Pragma "public"; try_files $uri =404; access_log off; log_not_found off; } location ~* \.(css|js)$ { limit_req zone=static_limit burst=80 nodelay; limit_conn conn_limit_per_ip 80; expires 1y; add_header Cache-Control "public, immutable"; add_header X-Content-Type-Options "nosniff"; try_files $uri =404; access_log off; } location ~* \.(woff2?|ttf|eot|svg)$ { limit_req zone=static_limit burst=60 nodelay; limit_conn conn_limit_per_ip 60; expires 1y; add_header Cache-Control "public, immutable"; add_header Access-Control-Allow-Origin "*"; try_files $uri =404; access_log off; } # ========== API ENDPOINTS ========== location ~* ^/api/ { limit_req zone=api_limit burst=30 delay=15; limit_conn conn_limit_per_ip 30; access_log /var/log/nginx/api_access.log main; try_files $uri $uri/ /index.php?$query_string; } # ========== АУТЕНТИФИКАЦИЯ ========== location ~* ^/(login|register|password-reset|auth|forgot-password|verify-email) { limit_req zone=auth_limit burst=5 delay=3; limit_conn conn_limit_per_ip 5; access_log /var/log/nginx/auth_access.log main; try_files $uri $uri/ /index.php?$query_string; } # ========== ОБРАБОТКА PHP ========== location ~ \.php$ { # Дефолтные лимиты для всех PHP запросов limit_req zone=req_limit_per_ip burst=30 delay=15; limit_conn conn_limit_per_ip 30; try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; # Оптимизация из основного конфига fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; fastcgi_busy_buffers_size 240k; fastcgi_temp_file_write_size 256k; # Таймауты fastcgi_connect_timeout 60s; fastcgi_send_timeout 600s; fastcgi_read_timeout 600s; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } # ========== ОСНОВНОЙ LOCATION ========== location / { if ($query_string ~* "(?:^|[^a-z])(?:union|select|insert|update|delete|drop|create|alter|exec)(?:[^a-z]|$)") { return 444; } if ($request_uri ~ "//") { return 444; } try_files $uri $uri/ /index.php?$query_string; gzip_static on; gzip_vary on; } # ========== HEALTH CHECK ========== location = /health { access_log off; # Прямой прокси в Laravel try_files $uri /index.php?$query_string; add_header Cache-Control "no-store, no-cache, must-revalidate"; } # ========== ЗАЩИТА ФАЙЛОВОЙ СИСТЕМЫ ========== location ~ /\. { deny all; access_log off; log_not_found off; return 404; } location ~* (\.env|\.git|\.svn|\.htaccess|composer\.json|composer\.lock) { deny all; return 404; } location ~* (eval|base64_encode|system\(|shell_exec|passthru|exec|phpinfo) { deny all; return 444; } }