WordPress + Nginx

ネタがないので、NginxでWordPressを動作させる時の雛形を用意してみる。

  • /etc/nginx/conf.d/sitename.conf
server {
    ### TLS + HTTP/2
    listen 443 ssl http2 default_server;
    server_name www.foofoomywebsite.jp;

    ### 基本I/O制御
    client_max_body_size 10m;
    etag off;        # ETagはキャッシュ不整合の温床になりやすい
    autoindex off;   # ディレクトリ列挙を抑止

    ### ドキュメント配置
    root  /var/www/www.foofoomywebsite.jp/document_root;
    index index.php index.html index.htm;

    ### ログ
    access_log /var/log/nginx/www.foofoomywebsite.jp_access.log combined;
    error_log  /var/log/nginx/www.foofoomywebsite.jp_error.log warn;

    ### TLS証明書(Let's Encrypt前提)
    ssl_certificate     "/etc/letsencrypt/live/www.foofoomywebsite.jp/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/www.foofoomywebsite.jp/privkey.pem";

    ### TLSセッション
    ssl_session_timeout 1d;
    ssl_session_cache   shared:MozSSL:10m;
    ssl_session_tickets off;

    ### DHパラメータ(2048bit以上推奨)
    ssl_dhparam /etc/nginx/dhparam.pem;

    ### プロトコル/暗号(TLS1.2/1.3のみ)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers  "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:"
                 "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:"
                 "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:"
                 "DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
    ssl_prefer_server_ciphers off; # TLS1.3では無視される

    1. OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/www.foofoomywebsite.jp/fullchain.pem;

    ### セキュリティヘッダ(CSPは別途要件に合わせて)
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Frame-Options           "SAMEORIGIN"       always;
    add_header X-Content-Type-Options    "nosniff"          always;
    add_header X-XSS-Protection          "1; mode=block"    always;
    add_header Referrer-Policy           "no-referrer-when-downgrade" always;

    ### --- Harden: 明示deny/制限 ---------------------------------------------

    ### xmlrpcは仕様上の脆弱点が多い。原則遮断(必要時のみ解除)
    location = /xmlrpc.php { deny all; }

    ### 隠し/管理系: .ht*, .git*, .env など一括deny
    location ~* ^/\. { deny all; }

    ### バックアップ/設定/ビルド関連の生ファイルを露出させない
    location ~* \.(?:sql|bak|orig|dist|ini|log|conf|env)$ { deny all; }
    location ~* ^/(?:readme\.html|license\.txt|wp-config\.php)$ { deny all; }

    ### composer/node等の開発資材は公開不要
    location ~* ^/(?:vendor/|node_modules/|composer\.(?:json|lock)|package\.json|yarn\.lock) { deny all; }

    ### wp-includes直下のPHP実行は原則不要(WPコアの直接実行を抑止)
    location ~* ^/wp-includes/.*\.php$ { deny all; }

    ### アップロードディレクトリ内のPHP実行は禁止(RCE対策)
    location ~* ^/wp-content/uploads/.*\.php$ { deny all; }

    ### wp-cronは外部からの直叩きを抑止(systemd/cronでの内部実行を前提)
    location = /wp-cron.php {
        allow 127.0.0.1;
        deny  all;
        include /etc/nginx/conf.d/php-fpm.conf;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
    }

    ### --- 例外: フロントで必要なエンドポイントの許可 -----------------------

    ### admin-ajaxはフロントから利用される。制限より前で許可
    location = /wp-admin/admin-ajax.php {
        auth_basic off;
        include /etc/nginx/conf.d/php-fpm.conf;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
        1. 必要なら軽いレート制限を適用(limit_req_zoneはhttp{}側で定義)
        1. limit_req zone=ajax burst=20 nodelay;
    }

    #### REST APIはテーマ/プラグイン依存で使われることが多い
    location ^~ /wp-json/ {
        auth_basic off;
        try_files $uri $uri/ /index.php?$args;
    }

   ### --- 通常ルーティング --------------------------------------------------

    ### author列挙対策:?author= をトップへ逃がす
    location / {
        if ($query_string ~* "author=") { return 301 /; }
        try_files $uri $uri/ /index.php?$args;
    }

    #### PHPハンドオフ
    location ~ \.php$ {
        try_files $uri /index.php?$args;
        include /etc/nginx/conf.d/php-fpm.conf;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
    }

    #### 管理画面: wp-login/wp-admin はIP許可 + BASIC(二重の摩擦で総当たりを抑止)
    location ~* (?:/wp-login\.php|/wp-admin/(?!.*(?:admin-ajax\.php|css/|js/)).*)$ {
        allow 192.168.10.1;
        allow 127.0.0.1;
        auth_basic "Restricted Area";
        auth_basic_user_file /etc/nginx/.htpasswd;

        client_max_body_size 1g; # 管理系アップロードは大きめ許容
        include /etc/nginx/conf.d/php-fpm.conf;
        fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
    }
}

/etc/nginx/conf.d/php-fpm.con

fastcgi_index index.php;
fastcgi_read_timeout 300;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;

fastcgi_pass は Unix socketを利用

ななし: