From time to time my website is getting hammered by requests to all sort of php files (we don't host any php files) and all sort of wp-content
and wp-includes
things, which I want to deny at the Nginx config level, rather than serving a nice-looking 404 page from our website.
Right now I have added two location
rules to a bunch of server
blocks:
server {
server_name www.example.com;
location ~* /wp- {
return 404;
}
location ~ \.php$ {
return 404;
}
location / {
# ...the site's proxy_pass config...
}
listen [::]:443 ssl http2; # managed by Certbot
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
server_name www.example.com;
location ~* /wp- {
return 404;
}
location ~ \.php$ {
return 404;
}
location / {
return 301 https://$host$request_uri;
}
listen 80;
listen [::]:80;
}
server {
server_name example.com;
location ~* /wp- {
return 404;
}
location ~ \.php$ {
return 404;
}
return 301 http://www.example.com$request_uri;
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
server_name example.com;
location ~* /wp- {
return 404;
}
location ~ \.php$ {
return 404;
}
if ($host = example.com) {
return 301 https://www.$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
return 404; # managed by Certbot
}
These different server
blocks make sure that http requests go to https, and that requests to the naked domain go to the www subdomain. Right now accessing any kind of php url result in different behavior:
How can I make it so that the two naked domains behave the same as the two www subdomains, as in: a request that matches one of these 2 rules immediately results in a 404, without first triggering a 301 redirect?
(These redirects are picked up by the server monitoring software and we constantly get warnings about a high percentage of redirects and a low percentage of successful responses. It's really quite annoying. And no, we don't want to license those warning, we just want these kinds of requests to no longer result in a redirect.)
I managed to solve it by wrapping the redirects to the https www version like so:
location / {
return 301 https://www.example.com$request_uri;
}
I did this in both bottom server
blocks, and this seems to work just fine. The if ($host = example.com)
check seemed completely unnecessary, and I removed this check, as well as the very bottom return 404
that was added by Certbot.