Nginx

由於 404 請求,wordpress 上的 SQL CPU 非常高

  • June 29, 2017

我正在執行一個帶有 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。

https://getrepsheet.com/

它可以幫助判斷一個請求是否是你想要的,並以不同的方式處理它們。這些執行隨機 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,將它們列入白名單!)

引用自:https://serverfault.com/questions/849849