Назад | Перейти на главную страницу

HTTP 405 Отправка комментариев Wordpress (Nginx / PHP-FPM / Memcached)

Я только что понял, что комментарии не работают на сайте Wordpress, над которым я работаю (LEMP + memcached), и не могу понять, почему. Я уверен, что это не связано ни с моей темой, ни с плагинами. По сути, если кто-то пытается оставить комментарий, nginx застревает на wp-comments-post.php с ошибкой HTTP 405 вместо выполнения POST запрос.

Насколько я могу судить, проблема заключается в том, как nginx обрабатывает POST просьба к wp-comments-post.php, где он возвращает HTTP 405 вместо правильного перенаправления.

У меня была похожая проблема Вот с выполнением POST запрос на плагин отправки электронной почты, и это было исправлено, сообщив memcached чтобы перенаправить ошибку 405. Memcached должен передавать 405 секунд обратно в nginx, но я не уверен, как nginx и php-fpm обрабатывают ошибки оттуда (особенно при использовании кеширования fastcgi).

Вот мой nginx.conf:

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

http {

##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 15;
keepalive_requests 65536;
client_body_timeout 12;
client_header_timeout 15;
send_timeout 15;
types_hash_max_size 2048;
server_tokens off;

server_names_hash_max_size 1024;
server_names_hash_bucket_size 1024;

include /etc/nginx/mime.types;  

index index.php index.html index.htm;

client_body_temp_path /tmp/client_body;
proxy_temp_path /tmp/proxy;
fastcgi_temp_path /tmp/fastcgi;
uwsgi_temp_path /tmp/uwsgi;
scgi_temp_path /tmp/scgi;   
fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
default_type application/octet-stream;

client_body_buffer_size 16K;
client_header_buffer_size 1K;
client_max_body_size 8m;
large_client_header_buffers 2 1k;

##
# Logging Settings
##

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";
gzip_min_length 1000;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 2;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json image/svg+xml image/png image/gif image/jpeg application/x-javascript text/xml application/xml application/xml+rss text/javascript font/ttf font/otf font/eot x-font/woff application/x-font-ttf application/x-font-truetype application/x-font-opentype application/font-woff application/font-woff2 application/vnd.ms-fontobject audio/mpeg3 audio/x-mpeg-3 audio/ogg audio/flac audio/mpeg application/mpeg application/mpeg3 application/ogg;

etag off;

##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

upstream php {
    server unix:/var/run/php/php7.0-fpm.sock;
}

server {    
    listen 80; # IPv4
    listen [::]:80; # IPv6
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    server_name example.com www.example.com;
    listen 443 default http2 ssl; # SSL
    listen [::]:443 default http2 ssl; # IPv6
    ssl on;
    ssl_certificate /etc/nginx/ssl/tls.crt;
    ssl_certificate_key /etc/nginx/ssl/priv.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 24h;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES256+EECDH:AES256+EDH:!aNULL;
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;

    add_header Public-Key-Pins 'pin-sha256="...; max-age=63072000; includeSubDomains;';
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header X-Content-Type-Options "nosniff";
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Dns-Prefetch-Control 'content=on';

    root /home/user/selfhost/html;
    include /etc/nginx/includes/*.conf; # Extra config

    client_max_body_size 10M;

    location / {
        set $memcached_key "$uri?$args";
        memcached_pass  127.0.0.1:11211;
        error_page 404 403 405 502 504 = @fallback;     
        expires 86400;

            location ~ \.(css|ico|jpg|jpeg|js|otf|png|ttf|woff) {
                                set $memcached_key "$uri?$args";
                                memcached_pass 127.0.0.1:11211;
                                error_page 404 502 504 = @fallback;
                                #expires epoch;
                    }

    }

    location @fallback {
        try_files $uri $uri/ /index.php$args;
        #root /home/user/selfhost/html;
        if ($http_origin ~* (https?://[^/]*\.example\.com(:[0-9]+)?)) {
                    add_header 'Access-Control-Allow-Origin' "$http_origin";
                    }
        if (-f $document_root/maintenance.html) {
            return 503;
        }

    }
    location ~ [^/]\.php(/|$) {
        # set cgi.fix_pathinfo = 0; in php.ini
        include proxy_params;
        include fastcgi_params;
        #fastcgi_intercept_errors off;
        #fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_pass php;
        fastcgi_cache phpcache;
        fastcgi_cache_valid 200 60m;
        #error_page 404 405 502 504 = @fallback;
    }

    location ~ /nginx.conf {
        deny all;
    }

            location /nginx_status {
                    stub_status on;
                    #access_log off;
        allow 159.203.18.101;
                    allow 127.0.0.1/32;
        allow 2604:a880:cad:d0::16d2:d001;
                    deny all;
            }


    location ^~ /09qsapdglnv4eqxusgvb {
        auth_basic "Authorization Required";
        auth_basic_user_file htpass/adminer;
        #include fastcgi_params;

                location ~ [^/]\.php(/|$) {
                        # set cgi.fix_pathinfo = 0; in php.ini
                        #include fastcgi_params;
            include fastcgi_params;
                        #fastcgi_intercept_errors off;
                        #fastcgi_pass unix:/var/run/php7.0-fpm.sock;
                        fastcgi_pass php;
                        fastcgi_cache phpcache;
                        fastcgi_cache_valid 200 60m;
                }



    }


    error_page 503 @maintenance;
    location @maintenance {
        rewrite ^(.*)$ /.maintenance.html break;
    }

}

А вот и fastcgi_params:

fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
fastcgi_param   QUERY_STRING        $query_string;
fastcgi_param   REQUEST_METHOD      $request_method;
fastcgi_param   CONTENT_TYPE        $content_type;
fastcgi_param   CONTENT_LENGTH      $content_length;

#fastcgi_param  SCRIPT_FILENAME     $request_filename;
fastcgi_param   SCRIPT_NAME         $fastcgi_script_name;
fastcgi_param   REQUEST_URI         $request_uri;
fastcgi_param   DOCUMENT_URI        $document_uri;
fastcgi_param   DOCUMENT_ROOT       $document_root;
fastcgi_param   SERVER_PROTOCOL     $server_protocol;

fastcgi_param   GATEWAY_INTERFACE   CGI/1.1;
fastcgi_param   SERVER_SOFTWARE     nginx/$nginx_version;

fastcgi_param   REMOTE_ADDR     $remote_addr;
fastcgi_param   REMOTE_PORT     $remote_port;
fastcgi_param   SERVER_ADDR     $server_addr;
fastcgi_param   SERVER_PORT     $server_port;
fastcgi_param   SERVER_NAME     $server_name;

fastcgi_param   HTTPS           $https if_not_empty;

fastcgi_param AUTH_USER $remote_user;
fastcgi_param REMOTE_USER $remote_user;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param   REDIRECT_STATUS     200;

fastcgi_param   PATH_INFO       $fastcgi_path_info;

fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
fastcgi_max_temp_file_size 0;
fastcgi_index index.php;

fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_keep_conn on;

Вот журналы запросов:

xxx.xxx.xxx.xxx - - [26/Apr/2017:00:11:59 +0000] "GET /2016/12/31/hello-world/ HTTP/2.0" 200 9372 "https://example.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"
xxx.xxx.xxx.xxx - - [26/Apr/2017:00:12:01 +0000] "POST /wp-comments-post.php HTTP/2.0" 405 626 "https://example.com/2016/12/31/hello-world/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"
xxx.xxx.xxx.xxx - - [26/Apr/2017:00:12:01 +0000] "GET /favicon.ico HTTP/2.0" 200 571 "https://example.com/wp-comments-post.php" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"
xxx.xxx.xxx.xxx - - [26/Apr/2017:00:21:20 +0000] "POST /wp-comments-post.php HTTP/2.0" 405 626 "https://example.com/2016/12/31/hello-world/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"
xxx.xxx.xxx.xxx - - [26/Apr/2017:00:21:21 +0000] "GET /favicon.ico HTTP/2.0" 200 571 "https://example.com/wp-comments-post.php" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"
xxx.xxx.xxx.xxx - - [26/Apr/2017:00:24:07 +0000] "POST /wp-comments-post.php HTTP/2.0" 405 626 "https://example.com/2016/12/31/hello-world/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"
xxx.xxx.xxx.xxx - - [26/Apr/2017:00:24:07 +0000] "GET /favicon.ico HTTP/2.0" 200 571 "https://example.com/wp-comments-post.php" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/57.0.2987.98 Chrome/57.0.2987.98 Safari/537.36"

На самом деле это не было связано с кешированием, как я подозревал, но оказалось, что виноват какой-то конфиг nginx, который поставляется с iThemes Security. Когда я отключил плагин и совершенно забыл, что он включает собственную конфигурацию nginx.

Я идиот, что недостаточно копался в моей конфигурации nginx, но спасибо всем за предложения. В частности, это было причиной:

location = /wp-comments-post.php {
    limit_except POST { deny all; }
    if ($http_user_agent ~ "^$") { return 403; }
    valid_referers server_names jetpack.wordpress.com/jetpack-comment/;
    if ($invalid_referer) { return 403; }
}

Когда я добавил $server_name к valid_referrers it это исправило это, поэтому я собираюсь отключить эту часть плагина и использовать настраиваемую конфигурацию. Что-то внутри вызывает это, просто нужно повозиться с этим, чтобы понять, что.