1

BACKGROUND: I am running a LEMP server with Ubuntu Server 20.04 with Nginx v1.25.1 Mainline and php7.4-fpm. In my virtual hosts file I am trying to set the proper and working fastcgi_split_path_info in the location ~ \.php$ { directive, but I'm not sure exactly what to put as the value, and I don't think my current fastcgi_split_path_info is correct.

NOTE: Instead of using "try_files $fastcgi_script_name =404", I am using the "if" statement

if (!-f $document_root$fastcgi_script_name) {
    return 404;
}

recommended by Nginx.org. I'm not sure if this matters when splitting fastcgi path info, but it should be noted just in case.

NOTE2: I am using cgi.fix_pathinfo = 1 (which is the default for PHP 7.4) in my php.ini file.

QUESTION: Could someone please take a look at my Nginx Virtual host and tell me the correct value that I should put for fastcgi_split_path_info in location ~\.php$?

Below is my Nginx virtual host example.com.conf

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server { listen *:443 ssl; http2 on; server_name example.com www.example.com; root /var/www/example.com/;

##
# SECURITY HEADERS
##

# Strict Transport Security Response Header
# Use "always" Paramater to help prevent MITM attacks.
# ADMIN Note: Including the Preload Paramerter will cause web browsers to cache this header
# permanently in their browser code for about two months. Use only if you want to permanently
# commit this header to your site. If you change it, it will take a long time for changes to
# be reflected in the web browsers.
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

# Content Security Policy (CSP)
#add_header Content-Security-Policy "frame-ancestors 'self';";
# https://gabriel.nu/tutorials/Ubuntu-20.04-NGINX-LEMP-secure-web-server-for-WordPress-DIY.html
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
#add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'";
# https://walterebert.com/blog/using-csp-wordpress/
#add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com;" always;
# https://nowherelan.com/2018/12/27/secure-your-wordpress-site-with-the-content-security-policy-csp-http-header-in-apache/
#add_header Content-Security-Policy "default-src 'self'; img-src 'self' data: http: https: *.gravatar.com *.wp.com *.wordpress.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: *.wp.com *.wordpress.com; style-src 'self' 'unsafe-inline' http: https: fonts.googleapis.com *.wp.com *.wordpress.com; font-src 'self' data: http: https: fonts.googleapis.com themes.googleusercontent.com *.wp.com *.wordpress.com; frame-src 'self' 'unsafe-inline' 'unsafe-eval' http: https: *.wp.com *.wordpress.com"

# Secure MIME Types with X-Content-Type-Options. Below line adds the X-Frame-Options header in Nginx.
add_header X-Content-Type-Options "nosniff" always;

# Referrer Policy
#add_header Referrer-Policy "strict-origin";
# https://gabriel.nu/tutorials/Ubuntu-20.04-NGINX-LEMP-secure-web-server-for-WordPress-DIY.html
add_header Referrer-Policy "no-referrer-when-downgrade" always;

# Permissions Policy
add_header Permissions-Policy "geolocation=(), autoplay=(), encrypted-media=(), midi=(), usb=(), sync-xhr=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), fullscreen=(self), payment=(self)";

# X-FastCGI-Cache
# This line adds the X-FastCGI-Cache header in the HTTP response. It can be used to validate whether
# the request has been served from the FastCGI cache or not.
# ADMIN Note: Linuxbabe originally had this directive in "location ~ \.php$ {", however, we don't use it
# there because it invalidates any other currently used headers and only implements itself.
add_header X-FastCGI-Cache $upstream_cache_status always;

# Clear Site Data
# When we use a webpage, we can leave various pieces of data in the browser that we’d like to clear
# out if the user logs out or deletes their account. Clear Site Data gives us a reliable way to do
# that.
# ADMIN Note: We decided to enable it globally on all pages via:
add_header Clear-Site-Data "*";

# X-Frame Options
# Prevent click jacking by adding an X-Frame-Options header
add_header x-frame-options "SAMEORIGIN" always;

# X-SSS Protections
# Enable X-XSS-Protection header in Nginx
add_header X-XSS-Protection "1; mode=block" always;

# LINUXBABE
# If you allow people to upload files, or are concerned about intruders using a different flaw to get
# files onto your server AND the content on your domain should not be accessed via other websites
# possibly trying to impersonate you, then yes X-Permitted-Cross-Domain-Policies "none" will provide a
# security benefit. The attack is less relevant these days, as any user of modern software first
# needs to be tricked into allowing Flash or active PDF content.
# If your website is just a regular website with nothing that requires a login to access, then you don't need it.
# https://www.linuxbabe.com/ubuntu/install-wordpress-ubuntu-20-04-nginx-mariadb-php7-4-lemp
# https://security.stackexchange.com/questions/166024/does-the-x-permitted-cross-domain-policies-header-have-any-benefit-for-my-websit
add_header X-Permitted-Cross-Domain-Policies none;

# LINUXBABE (User recommendation)
# Ignore Cache Control
# Keep fastcgi working if it's not getting hits
# ADMIN Note: Only use this if fastcgi cache status is not getting hits
#fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

##
# SSL
##

# Certificate Path (signed)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # Managed by ADMIN
# Certificate Path (intermediate)
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # Managed by ADMIN
# Certificate Path (Chain of trust of OCSP response using Root CA and intermediate certificates)
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; # Managed by ADMIN
# Perfect Forward Secrecy (Diffie Hellman 4096) Path
ssl_dhparam /etc/ssl/private/dhparams4096.pem; # Managed by ADMIN

# Mozilla Modern Compatibilty
# Strict Settings with OCSP stapling turned on for A+ Rating at ssllabs.com
ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLERequires nginx >= 1.13.0 else use TLSv1.2 # Dropping TLSv1.1 for modern compatability.
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256: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_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_prefer_server_ciphers on;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # About 40000 sessions
ssl_session_tickets off;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1;

##
# LOGS
##

# ADMIN Note: Adding "if=$log_ip" to the end of access log lines will exclude your own ip address from access logs to prevent skewing data

# Access Log (Netdata)
access_log /var/log/nginx/example.com.access.log netdata if=$log_ip;
# Access Log (Amplify)
access_log /var/log/nginx/example.com.access.log apm if=$log_ip;
# Error Log
error_log /var/log/nginx/example.com.error.log warn;

##
# PAGESPEED
##

# ADMIN Note: Pagespeed is broken on Nginx v1.25.1 and up, so we should comment all of it out here and in the "nginx.conf" file

# Settings per this virtual host
# Enable Pagespeed module
#pagespeed on;
#pagespeed Domain http*://*.example.com;

# Settings per all virtual hosts
#include /etc/nginx/pagespeed.conf;

##
# LOCATION DIRECTIVES 1
##

index index.php index.html index.htm index.nginx-debian.html;

# ADMIN
# https://serverfault.com/questions/1137324/difference-between-3-similar-nginx-location-directives-provided-in-three-separat/1137342#1137342
location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

### BEGIN: "Converter for Media" Wordpress Plugin
set $ext_avif ".avif";
if ($http_accept !~* "image/avif") {
    set $ext_avif "";
}

set $ext_webp ".webp";
if ($http_accept !~* "image/webp") {
    set $ext_webp "";
}

location ~ /wp-content/(?<path>.+)\.(?<ext>jpe?g|png|gif|webp)$ {
    add_header Vary Accept;
    expires 365d;
    try_files
        /wp-content/uploads-webpc/$path.$ext$ext_avif
        /wp-content/uploads-webpc/$path.$ext$ext_webp
        $uri =404;
}
### END: "Converter for Media" Wordpress Plugin

# ADMIN
# https://serverfault.com/questions/755662/nginx-disable-htaccess-and-hidden-files-but-allow-well-known-directory
# location ~ /.well-known {
location ~ /\.well-known {
    allow all;
}

# ADMIN
location = /favicon.ico {
    log_not_found off;
    access_log off;
}

# ADMIN
location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
}

# LINUXBABE
location ~ ^/wp-json/ {
    rewrite ^/wp-json/(.*?)$ /?rest_route=/$1 last;
}

# LINUXBABE
location ~ /wp-sitemap.*\.xml {
    try_files $uri $uri/ /index.php$is_args$args;
}

# LINUXBABE
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

# LINUXBABE
location = /50x.html {
    root /var/www/html;
}

# ADMIN
# DISALLOW ACCESS of /xmlrpc.php
# EXCEPT FROM internal IP's and Home & Apartment IP's.
#location ^~ /xmlrpc.php$ {
    #allow xxx.xxx.xx.x/24; #   LAN IP Address
    #allow xxx.xxx.xx.x/32; # Home IP address
    #allow xxx.xxx.xx.x/32; # Apt. IP Address
    #deny all;
#}

# ADMIN
# DISALLOW ACCESS of /admin
# EXCEPT FROM internal IP's and Home & Apartment IP's
location ^~ /admin/ {
    #satify all;
    allow xxx.xxx.xx.x/24; #   LAN IP Address
    allow xxx.xxx.xx.x/32; # Home IP address
    allow xxx.xxx.xx.x/32; # Apt. IP Address
    deny all;
    # Require basic auth login for allowed IP's
    auth_basic "You Don't belong here. Get out!";
    auth_basic_user_file /etc/nginx/basic_auth/auth.admin;
}

# ADMIN
# DISALLOW ACCESS of /wp-login.php
# EXCEPT FROM internal IP's and Home & Apartment IP's.
#location ^~ /wp-login.php {
    #allow xxx.xxx.xx.x/24; #   LAN IP Address
    #allow xxx.xxx.xx.x; # Home IP address
    #allow xxx.xxx.xx.x; # Apt. IP Address
    #deny all;
    # Require basic auth login for allowed IP's
    #auth_basic "You Don't belong here. Get out!";
    #auth_basic_user_file /etc/nginx/basic_auth/auth.wp-login;
#}

# ADMIN
# DISALLOW ACCESS of PHP In Upload Folder
location /wp-content/uploads/ {
    location ~ \.php$ {
        deny all;
    }
}

# ADMIN
# DISALLOW ACCESS of hidden files
location ~ /\. {
    access_log off;
    log_not_found off;
    deny all;
}

##
# BEGIN: CACHE / SKIP CACHE
##

# LINUXBABE
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# Don't Skip Cache by Default
set $skip_cache 0;

# LINUXBABE
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# POST requests should always go to PHP
if ($request_method = POST) {
    set $skip_cache 1;
}

# LINUXBABE
# URLs containing query strings should always go to PHP
# ADMIN Note: You might want to be sure to turn off query strings in H-code wordpress theme, and other themes
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
if ($query_string != "") {
    set $skip_cache 1;
}

# LINUXBABE
# Don't cache uris containing the following segments
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# https://easyengine.io/wordpress-nginx/tutorials/plugins/woocommerce/
# https://docs.cleavr.io/guides/woocommerce/
if ($request_uri ~* "/wp-admin/|/wp-json/|/login/|/register/|/shopping-cart.*|.*add-to-cart.*|.*empty-cart.*|/cart.*|/checkout.*|/addons.*|/my-account.*|/wishlist.*|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|index.php|/.*sitemap.*\.(xml|xsl)") {
    set $skip_cache 1;
}

# LINUXBABE
# Don't use the cache for logged in users or recent commenters
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
    set $skip_cache 1;
}

# LINUXBABE
# Cache Bypass for specified IP's
# Test the upstream (PHP-FPM and MariaDB) response time. By adding the following
# lines we tell Nginx to bypass the FastCGI cache for our own public and local IP addresses.
# Skip the fastCGI Cache for "Apartment Public IP|Work Public IP|Apartment LAN Subdomain".
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
#if ($remote_addr ~* "xxx.xxx.xx.x|108.231.125.254|xxx.xxx.xx.x|192.168.25..*") {
#    set $skip_cache 1;
#}

##
# END: CACHE / SKIP CACHE
##

# LINUXBABE
# Google Sitemaps / Yoast SEO Rules:
# If you use the Yoast SEO or Google XML Sitemap plugins to generate sitemap, then
# you need to move the Yoast/Google XML rewrite rules here, below the skip cache rules (below this line).
# https://www.linuxbabe.com/nginx/setup-nginx-fastcgi-cache
# Rules:

##
# LOCATION DIRECTIVES 2
##

# LINUXBABE
# Pass Fastcgi to PHP
location ~ \.php$ {
    # Pass FastCGI to PHP 7.4
    fastcgi_pass unix:/run/php/php7.4-fpm.sock;

    # Add to SCRIPT_FILENAME to fastcgi params file
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

    # FastCGI Split Path Info (Possibly Incorrect, need help from serverfault.com)
    # There are a couple of options for fastcgi_split_path_info, but we don't know which one, if any, are correct (Question for serverfault.com)
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    #fastcgi_split_path_info ^(.+\.php)(.*)$;
    #fastcgi_split_path_info ^(.+\.php)(/.+)$;

    # Check that the PHP script exists before passing it by using an "if" statement instead of using "try_files $fastcgi_script_name =404"
    # The if lets NGINX check whether the *.php does indeed exist,
    # to prevent NGINX from feeding PHP FPM non php script files (like uploaded images).
    # see https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }

    # Mitigate https://httpoxy.org/ vulnerabilities
    # Note: see https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
    # also see https://www.digitalocean.com/community/tutorials/how-to-protect-your-server-against-the-httpoxy-vulnerability
    # if configuring Nginx for conventional HTTP proxying
    fastcgi_param HTTP_PROXY "";

    # Fastcgi index
    fastcgi_index index.php

    # Include fastcgi_params file
    include fastcgi_params;

    fastcgi_buffers 1024 4k;
    fastcgi_buffer_size 128k;

    # FastCGI Cache
    #fastcgi_cache off;
    fastcgi_cache example.com;
    fastcgi_cache_valid 200 301 302 12h;
    fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
    fastcgi_cache_min_uses 1;
    fastcgi_cache_lock on;
    # Tell Nginx to send requests to upstream PHP-FPM server, instead of trying to find files in the
    # cache. If the value of $skip_cache is 1, then the first directive tells Nginx to send request
    # to upstream PHP-FPM server, instead of trying to find files in the cache.
    # ADMIN Note: fastcgi_cache_bypass $skip_cache and fastcgi_no_cache $skip_cache should be
    # uncommented if using google XML sitemap plugin, or Yoast SEO Plugin, or if you want to
    # enable the skip cache rules above.
    fastcgi_cache_bypass $skip_cache;
    # This directive tells Nginx not to cache the response.
    fastcgi_no_cache $skip_cache;
}

# LINUXBABE (+ ADMIN Extra Extensions)
# Speed up repeat visits to your page with a long browser cache lifetime
location ~ \.(txt|flv|pdf|avi|mov|ppt|wmv|mp3|ogg|webm|aac|jpg|ogg|ogv|svgz|eot|otf|mp4|rss|atom|zip|tgz|gz|rar|bz2|doc|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|jpeg|gif|png|swf|jpeg|webp|svg|woff|woff2|ttf|css|js|ico|xml|otf|woff|woff2)$ {
    access_log off;
    log_not_found off;
    expires 1y;
}

}

DanRan
  • 133

0 Answers0