# 七虎 AI PaaS nginx site — enhanced with rate limiting + scanner defense # Owner: 七虎平台运维 (Senior Developer) # 维护: edit on host /app/backend/nginx/aiflow.conf, push to container /etc/nginx/conf.d/aiflow.conf # 重载: docker exec qihu-aiflow sh -c "nginx -t && nginx -s stop && nginx" # 三档速率限制 limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s; limit_req_zone $binary_remote_addr zone=admin_limit:10m rate=5r/s; limit_req_zone $binary_remote_addr zone=login_limit:1m rate=1r/s; # 动态黑名单(由 /app/backend/nginx/block_ip.py 写入) include /etc/nginx/blocked_ips.conf; server { listen 8080 default_server; server_name _; client_max_body_size 100m; client_body_timeout 30s; keepalive_timeout 75s; gzip off; # ===== 反扫描器: bad URI 直接 444 ===== if ($request_uri ~* "^/(wp-admin|wp-login|xmlrpc\.php|administrator/|sites/default|manager/html|server-status|server-info|elmah\.axd|web\.config|readme|license\.txt|install\.php|shell\.php)") { return 444; } if ($request_uri ~* "^/(phpmyadmin|\.env|\.git/|actuator|actuator/|\.well-known/security)") { return 444; } if ($http_user_agent ~* "(zgrab|nmap|masscan|nikto|sqlmap|acunetix|nessus|wpscan|dirbuster|gobuster|ffuf|hydra|metasploit|MJ12bot|AhrefsBot|SemrushBot|DotBot|PetalBot|Aspera|HTTrack|Scrapy|libwww|Havij|TSWeb)") { return 444; } if ($http_user_agent ~* "(^curl/|^wget/|^python-requests)") { return 444; } access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log warn; # 索引 HTML 不缓存 location = /index.html { add_header Cache-Control "no-cache"; try_files /index.html =404; } # 静态资源永久缓存 location ~* \.(svg|png|jpg|jpeg|gif|ico|webp|woff2?|ttf|eot|css|js|map)$ { root /app/frontend/dist; try_files $uri =404; access_log off; expires 30d; add_header Cache-Control "public, max-age=2592000"; } # SPA fallback location / { try_files $uri $uri/ /index.html; } # ===== 普通 API: 30r/s ===== location /app/ { limit_req zone=api_limit burst=60 nodelay; proxy_pass http://localhost:18080/app/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 600s; proxy_connect_timeout 10s; } # ===== ADMIN API: 5r/s 严格 ===== location ~ ^/app/api/(admin/|market/admin/|internal/) { limit_req zone=admin_limit burst=10 nodelay; proxy_pass http://localhost:18080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 600s; proxy_send_timeout 600s; } # ===== AUTH: 1r/s 防爆破 ===== location ~ ^/app/api/(auth/login|auth/register|casdoor/) { limit_req zone=login_limit burst=5 nodelay; proxy_pass http://localhost:18080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 60s; proxy_send_timeout 60s; } # ===== SSE STREAMING: 禁缓冲 长连接 ===== location ~ ^/app/(api/chat/events|api/pet/) { proxy_pass http://localhost:18080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Connection ""; proxy_buffering off; proxy_cache off; proxy_request_buffering off; proxy_http_version 1.1; proxy_read_timeout 86400s; proxy_send_timeout 86400s; chunked_transfer_encoding on; } # 健康检查 location = /health { access_log off; return 200 "ok\n"; add_header Content-Type text/plain; } # 405/413 nice error error_page 413 /custom_413; location = /custom_413 { internal; return 413 "Payload Too Large\n"; } }