Security hardening nginx

This commit is contained in:
David Petric 2023-04-07 19:11:46 +02:00
parent 4d5c5cbf58
commit 1d0a36ae45
2 changed files with 128 additions and 14 deletions

View File

@ -1,6 +1,6 @@
# Ansible-WordPress-Nginx-Docker # Ansible-WordPress-Nginx-Docker
This Ansible project automates the setup and configuration of an Ubuntu machine to host a WordPress website using Nginx, PHP, Docker, MySQL, and Redis. This Ansible project automates the setup and configuration of an Ubuntu machine to host a WordPress website using Nginx, PHP, Docker, MySQL, and Redis. The Nginx vhost configuration is hardened for improved security.
## Features ## Features
@ -8,7 +8,7 @@ The Ansible playbook in this project will:
1. Update Ubuntu packages 1. Update Ubuntu packages
2. Install Nginx 2. Install Nginx
3. Configure Nginx 3. Configure Nginx with hardened vhost settings
4. Install PHP 4. Install PHP
5. Configure PHP 5. Configure PHP
6. Install WordPress 6. Install WordPress
@ -43,9 +43,7 @@ Run the playbook:
ansible-playbook -i inventory/target.ini setup_server.yml ansible-playbook -i inventory/target.ini setup_server.yml
``` ```
After the playbook has run successfully, you should have a fully functional WordPress website running on your Ubuntu machine with Nginx, PHP, MySQL, and Redis. After the playbook has run successfully, you should have a fully functional WordPress website running on your Ubuntu machine with Nginx, PHP, MySQL, and Redis, with a hardened Nginx vhost configuration.
Please make sure to install Redis plugin which already has a pre-set configuration
## Variables ## Variables

View File

@ -8,30 +8,30 @@ map $sent_http_content_type $expires {
server { server {
root /var/www/{{ vhost_name }}; root /var/www/{{ vhost_name }};
index index.php index.html index.htm; index index.php;
server_name {{ domain }}; server_name {{ domain }};
listen 80; listen 80;
#Cache settings
expires $expires; expires $expires;
#Upload max size
client_max_body_size 50M; client_max_body_size 50M;
ErrorLog /var/log/nginx/{{ vhost_name }}-error.log ErrorLog /var/log/nginx/{{ vhost_name }}-error.log
CustomLog /var/log/nginx/{{ vhost_name }}-access.log combined CustomLog /var/log/nginx/{{ vhost_name }}-access.log combined
autoindex off; #Disable directory listing
autoindex off;
location / { location / {
try_files $uri $uri/ @handler; try_files $uri $uri/ @handler;
} }
location /admin {
try_files $uri $uri/ /admin/index.php?$args;
}
location @handler { location @handler {
if (!-e $request_filename) { rewrite / /index.php last; } if (!-e $request_filename) { rewrite / /index.php last; }
rewrite ^(.*.php)/ $1 last; rewrite ^(.*.php)/ $1 last;
} }
location ~ \.php$ { location ~ \.php$ {
include snippets/fastcgi-php.conf; include snippets/fastcgi-php.conf;
@ -39,4 +39,120 @@ server {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; include fastcgi_params;
} }
#Disable access to wp-config.php
location ~* /(wp-config.php) {
deny all;
}
#Limit XMLRPC access
location ~* /xmlrpc.php$ {
allow 172.0.1.1;
deny all;
}
#Limit request types
if ($request_method !~ ^(GET|POST)$ ) {
return 444;
}
#Limit direct PHP access
location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/.*.php$ {
deny all;
access_log off;
log_not_found off;
}
#Hide nginx version
server_tokens off;
#Hide PHP version
fastcgi_hide_header X-Powered-By;
proxy_hide_header X-Powered-By;
#Security headers
add_header X-Frame-Options SAMEORIGIN; #Comment it to allow iframe
add_header Strict-Transport-Security "max-age=31536000";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# Disable logs for favicon and robots
location = /favicon.ico {
try_files /favicon.ico @empty;
access_log off;
log_not_found off;
expires max;
}
location @empty {
empty_gif;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
try_files $uri /index.php?$args;
}
# Deny access to uploads that are not media files
location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf)$ {
deny all;
}
# Nginx common security
location ~* "(eval\()" {
deny all;
}
location ~* "(127\.0\.0\.1)" {
deny all;
}
location ~* "([a-z0-9]{2000})" {
deny all;
}
location ~* "(javascript\:)(.*)(\;)" {
deny all;
}
location ~* "(base64_encode)(.*)(\()" {
deny all;
}
location ~* "(GLOBALS|REQUEST)(=|\[|%)" {
deny all;
}
location ~* "(<|%3C).*script.*(>|%3)" {
deny all;
}
location ~ "(\\|\.\.\.|\.\./|~|`|<|>|\|)" {
deny all;
}
location ~* "(boot\.ini|etc/passwd|self/environ)" {
deny all;
}
location ~* "(thumbs?(_editor|open)?|tim(thumb)?)\.php" {
deny all;
}
location ~* "(\'|\")(.*)(drop|insert|md5|select|union)" {
deny all;
}
location ~* "(https?|ftp|php):/" {
deny all;
}
location ~* "(=\\\'|=\\%27|/\\\'/?)\." {
deny all;
}
location ~ "(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\")" {
deny all;
}
location ~ "(~|`|<|>|:|;|%|\\|\s|\{|\}|\[|\]|\|)" {
deny all;
}
location ~* "/(=|\$&|_mm|(wp-)?config\.|cgi-|etc/passwd|muieblack)" {
deny all;
}
location ~* "(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ)" {
deny all;
}
location ~* "/(^$|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell|config|settings|configuration)\.php" {
deny all;
}
} }