由于 404 请求,WordPress 上的 SQL CPU 非常高

由于 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,这些 IP 请求不同的 URL,并且请求看起来非常合法(标头看起来与浏览器完全一样),因此我无法制定任何防火墙规则来阻止它,但我知道它们是自动请求,因为有些用户代理告诉它来自 IA64 架构,而我的任何访问者都不会拥有它。

不,由于某种原因,我无法使用 Cloudflare 或类似服务来阻止自动请求...那么,是否有任何 Nginx 插件可以通过测试 javascript 或类似方法来检测它是真正的浏览器加载还是机器人,然后才允许它进入网站?

答案1

首先,我会研究传入的请求。它们真的是攻击吗,还是您的应用程序有很多断开的链接?如果您能修复原因,那总是更好的。

Fail2Ban 也是我推荐的,但是如果每个 IP 只发出一个请求,它就起不了多大作用。

无论如何,您都希望避免出现 404 错误,以便访问 Wordpress/PHP/MySQL。如果请求中存在任何可以匹配的模式,则 Web 服务器可以处理它。如果没有明确的模式,则更棘手,但仍然可以做到。

这些针对 MySQL 的说明可以适用于 Nginx:

https://www.pipeten.info/2015/10/better-handling-wordpress-404-errors/

但可能更好的是 Repsheet。

https://getrepsheet.com/

它可以帮助判断请求是否是您想要的,并对其进行不同的处理。这些 IP 随机出现 404 错误显然不是在模仿正常的用户行为。Repsheet 经过一些学习后就能判断出来,然后您可以在请求到达整个 Web 堆栈之前发出 404 或 403 错误。

Repsheet 有一个适用于 Nginx 的模块:https://github.com/repsheet/repsheet-nginx

反过来,它会将您的真实(重复)用户视为优秀的参与者,并且您可以设置规则来对他们进行优先排序。

最后,因为大多数 HTTP 机器人都很愚蠢,您可以使用 Nginx 的测试 Cookie 模块来测试这是否是真正的用户代理:

https://github.com/kyprizel/testcookie-nginx-module

(但要小心阻止像 Google 这样的好机器人,不要毁掉你的 SEO,将它们列入白名单!)

相关内容