由於 404 請求,wordpress 上的 SQL CPU 非常高
我正在執行一個帶有 Nginx、MariaDB、PHP-FPM 的 Wordpress 站點,並且受到來自大量 IP 的大量不同 404 請求的轟炸(每小時約 10.000 個不同的 IP 請求隨機 URL,這會導致非常高的 SQL 負載和隨機停機時間)。
我試圖將主伺服器放在不同的 Nginx 伺服器後面,該伺服器將對站點進行反向代理記憶體以減少負載,但由於 404 請求通過 Nginx 代理記憶體伺服器,主伺服器仍然會獲得非常高的負載。
伺服器現在出現 5XX 錯誤,因為 MYSQLD 佔用了所有 CPU 來處理它的東西,因此我認為 PHP-FPM 餓死並且對 Nginx 的請求沒有響應?
我在錯誤日誌中得到了很多:
2017/05/13 03:48:40 [error] 24894#24894: *2936187 upstream timed out (110: Connection timed out) while connecting to upstream
我的伺服器有 16 核、64GB RAM 和 200GB SSD 磁碟,執行 Ubuntu 17.04 和 MYSQLD 總是盡可能多地佔用所有 CPU。
我的主伺服器 Nginx 配置:
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 2048; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; client_max_body_size 32M; disable_symlinks off; include /etc/nginx/mime.types; default_type application/octet-stream; gzip off; ### START SERVER CONFIG server { listen 80 default_server; root /var/www/html; index index.php index.html index.htm; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; server_name _; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass 127.0.0.1:9000; } location ~ /\.ht { deny all; } } ### END OF SERVER CONFIG }
PHP-FPM 配置:
[www] user = www-data group = www-data listen = 127.0.0.1:9000 listen.owner = www-data listen.group = www-data listen.allowed_clients = 127.0.0.1 process.priority = -10 pm = dynamic pm.max_children = 64 pm.start_servers = 32 pm.min_spare_servers = 2 pm.max_spare_servers = 32
有什麼辦法可以改善這種情況嗎?正如我所說,所有請求都來自許多不同的 IP,它們請求不同的 URL,請求看起來非常合法(標題看起來完全像瀏覽器),所以我無法制定任何防火牆規則來阻止它,但我知道他們重新自動請求,因為有一些使用者代理告訴它來自 IA64 架構,我的任何訪問者都沒有它。
不,由於某種原因,我不能使用 Cloudflare 或類似服務來阻止自動請求……那麼是否有任何 Nginx 外掛通過測試 javascript 或類似方法來檢測它是真正的瀏覽器負載還是機器人,然後才允許它進入地點?
起初我會研究傳入的請求。它們是真的攻擊還是您的應用程序有很多斷開的連結?如果你能解決這個原因,它總是更好。
Fail2Ban 也是我推薦的東西,但如果每個 IP 只執行一個請求,它不會做太多事情。
無論如何,您都希望避免 404 到達 Wordpress/PHP/MySQL。如果您可以匹配請求中的任何模式,則網路伺服器可以處理它。如果沒有明確的模式,那就更棘手了,但仍然可以完成。
MySQL 的這些指令可以適用於 Nginx:
https://www.pipeten.info/2015/10/better-handling-wordpress-404-errors/
但更好的是 Repsheet。
它可以幫助判斷一個請求是否是你想要的,並以不同的方式處理它們。這些執行隨機 404 的 IP 顯然不能模仿正常的使用者行為。經過一些學習後,Repsheet 將能夠分辨出來,然後您可以在它到達完整的 Web 堆棧之前發出 404 或 403。
Repsheet 有一個 Nginx 模組:https ://github.com/repsheet/repsheet-nginx
反過來,它會知道你的真實(重複)使用者是好演員,你可以設置規則來優先考慮他們。
最後,因為大多數 HTTP 機器人都非常愚蠢,您可以使用 Nginx 的測試 Cookie 模組來測試這是否是真正的使用者代理:
https://github.com/kyprizel/testcookie-nginx-module
(但要小心阻止像Google這樣的好機器人,不要扼殺你的 SEO,將它們列入白名單!)