less snippets-ispconfig-directive-for-nginx.md
Snippets: ISPConfig directive for nginx
# historical archive — written years ago, kept as it was. Some info is dated.
Snippets, that is, bits of code. ISPConfig lets you save small code fragments that can be easily recalled when you add a site to our system. They can relate to PHP, Apache, Proxy or, as in our case, to nginx. The ones that follow are some of those I use when setting up a WordPress site.
They are examples, and please take them for what they are: ideas that may be more or less useful depending on your needs.
Disclaimer: Be careful when using these or other snippets. They override ISPConfig’s default settings and therefore could compromise the system’s security rather than increase it. An error in a snippet added to one site could affect all the others.
W3 Total Cache
This plugin generates an nginx.conf file in your site’s ROOT directory. The file contains various directives depending on the type of configuration you have chosen. To include the file, you just need to generate a snippet like this:
include {DOCROOT}/nginx.conf;
Security
Some general security directives that can be used with all the websites you host. In the code I’ve kept the comments that explain what the various parts are for:
### Prevent access to this file generated by various plugins (W3 Total Cache, AkeebaBackup, etc)
location = /nginx.conf {
log_not_found off;
access_log off;
return 404;
break;
}
## Block some common exploits
set $common_exploit 0;
if ($query_string ~ "proc/self/environ") {
set $common_exploit 1;
}
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") {
set $common_exploit 1;
}
if ($query_string ~ "base64_(en|de)code\(.*\)") {
set $common_exploit 1;
}
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") {
set $common_exploit 1;
}
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") {
set $common_exploit 1;
}
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") {
set $common_exploit 1;
}
if ($common_exploit = 1) {
return 403;
}
## File injection protection
set $file_injection 0;
if ($query_string ~ "[a-zA-Z0-9_]=http://") {
set $file_injection 1;
}
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") {
set $file_injection 1;
}
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") {
set $file_injection 1;
}
if ($file_injection = 1) {
return 403;
}
## SQL injection first line of defence (NOT comprehensive!)
set $sql_injection 0;
if ($query_string ~ "concat.*\(") {
set $sql_injection 1;
}
if ($query_string ~ "union.*select.*\(") {
set $sql_injection 1;
}
if ($query_string ~ "union.*all.*select.*") {
set $sql_injection 1;
}
if ($sql_injection = 1) {
return 403;
}
## Basic anti-spam
set $looks_like_spam 0;
if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") {
set $looks_like_spam 1;
}
if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") {
set $looks_like_spam 1;
}
if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") {
set $looks_like_spam 1;
}
if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") {
set $looks_like_spam 1;
}
if ($looks_like_spam = 1) {
return 403;
}
## User agent blocking
##
## Disables access to your site by user agent. Useful to block some
## bandwidth hoggers.
set $bad_ua 0;
# This also disables Akeeba Remote Control 2.5 and earlier
if ($http_user_agent ~ "Indy Library") {
set $bad_ua 1;
}
# Disabling Wget will also block the most common method to run CRON jobs
if ($http_user_agent ~ "Wget") {
set $bad_ua 1;
}
# Common bandwidth hoggers and hacking tools. Each rule is three lines, beginning with "if"
if ($http_user_agent ~ "libwww-perl") {
set $bad_ua 1;
}
if ($http_user_agent ~ "Download Demon") {
set $bad_ua 1;
}
if ($http_user_agent ~ "GetRight") {
set $bad_ua 1;
}
if ($http_user_agent ~ "GetWeb!") {
set $bad_ua 1;
}
if ($http_user_agent ~ "Go!Zilla") {
set $bad_ua 1;
}
if ($http_user_agent ~ "Go-Ahead-Got-It") {
set $bad_ua 1;
}
if ($http_user_agent ~ "GrabNet") {
set $bad_ua 1;
}
if ($http_user_agent ~ "TurnitinBot") {
set $bad_ua 1;
}
# If you enable any of the above don't remove this. It's what blocks
# the bad user agents!
if ($bad_ua = 1) {
return 403;
}
WordPress Security
The following fragment prevents direct access to some default files present in the WordPress archive. In particular, as you can see, they relate to the Italian localization:
## Block access to wp-config-sample.php and other WP defaults file
location = /wp-config-sample.php {
log_not_found off;
access_log off;
return 404;
break;
}
location = /wp-config.php {
log_not_found off;
access_log off;
return 404;
break;
}
location = /htaccess.txt {
log_not_found off;
access_log off;
return 404;
break;
}
location = /LEGGIMI.txt {
log_not_found off;
access_log off;
return 404;
break;
}
location = /license.txt {
log_not_found off;
access_log off;
return 404;
break;
}
location = /licenza.html {
log_not_found off;
access_log off;
return 404;
break;
}
location = /readme.html {
log_not_found off;
access_log off;
return 404;
break;
}
Cloudflare
Since CloudFlare acts as a reverse proxy, all connections come from one of the CloudFlare IP addresses. CloudFlare follows industry standards and includes the originating IP address in the X-Forwarded-For header. The CF-Connecting-IP header can also be used. To preserve the visitor’s original IP, use the following snippet for nginx:
## CloudFlare support - see https://support.cloudflare.com/hc/en-us/articles/200170706-Does-CloudFlare-have-an-IP-module-for-Nginx-
## IPv4
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
## IPv6
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
real_ip_header X-Forwarded-For;
Akeeba Backup Pro for WordPress
If you are using this plugin, you’ll need to grant direct access to the file shown in the snippet. This example can be used with any other file that requires direct access permission:
## Advanced server protection rules exceptions
location = /wp-content/plugins/akeebabackupwp/app/restore.php {
{FASTCGIPASS}
break;
}