From 17161c39ca521774f35e3bd823dd2219c1377333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kucharczyk?= Date: Fri, 14 May 2021 22:47:11 +0200 Subject: [PATCH] Add nginx snippets from Nginx Proxy Manager --- .../nginx/files/snippets/block-exploits.conf | 136 ++++++++++++++++++ roles/nginx/files/snippets/cache-assets.conf | 31 ++++ roles/nginx/files/snippets/force-ssl.conf | 3 + .../snippets/letsencrypt-acme-challenge.conf | 29 ++++ roles/nginx/files/snippets/proxy.conf | 7 + roles/nginx/files/snippets/ssl-ciphers.conf | 9 ++ 6 files changed, 215 insertions(+) create mode 100644 roles/nginx/files/snippets/block-exploits.conf create mode 100644 roles/nginx/files/snippets/cache-assets.conf create mode 100644 roles/nginx/files/snippets/force-ssl.conf create mode 100644 roles/nginx/files/snippets/letsencrypt-acme-challenge.conf create mode 100644 roles/nginx/files/snippets/proxy.conf create mode 100644 roles/nginx/files/snippets/ssl-ciphers.conf diff --git a/roles/nginx/files/snippets/block-exploits.conf b/roles/nginx/files/snippets/block-exploits.conf new file mode 100644 index 0000000..093bda2 --- /dev/null +++ b/roles/nginx/files/snippets/block-exploits.conf @@ -0,0 +1,136 @@ +## Block SQL injections +set $block_sql_injections 0; + +if ($query_string ~ "union.*select.*\(") { + set $block_sql_injections 1; +} + +if ($query_string ~ "union.*all.*select.*") { + set $block_sql_injections 1; +} + +if ($query_string ~ "concat.*\(") { + set $block_sql_injections 1; +} + +if ($block_sql_injections = 1) { + return 403; +} + +## Block file injections +set $block_file_injections 0; + +if ($query_string ~ "[a-zA-Z0-9_]=http://") { + set $block_file_injections 1; +} + +if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { + set $block_file_injections 1; +} + +if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { + set $block_file_injections 1; +} + +if ($block_file_injections = 1) { + return 403; +} + +## Block common exploits +set $block_common_exploits 0; + +if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { + set $block_common_exploits 1; +} + +if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { + set $block_common_exploits 1; +} + +if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { + set $block_common_exploits 1; +} + +if ($query_string ~ "proc/self/environ") { + set $block_common_exploits 1; +} + +if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { + set $block_common_exploits 1; +} + +if ($query_string ~ "base64_(en|de)code\(.*\)") { + set $block_common_exploits 1; +} + +if ($block_common_exploits = 1) { + return 403; +} + +## Block spam +set $block_spam 0; + +if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") { + set $block_spam 1; +} + +if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") { + set $block_spam 1; +} + +if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") { + set $block_spam 1; +} + +if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") { + set $block_spam 1; +} + +if ($block_spam = 1) { + return 403; +} + +## Block user agents +set $block_user_agents 0; + +# Disable Akeeba Remote Control 2.5 and earlier +if ($http_user_agent ~ "Indy Library") { + set $block_user_agents 1; +} + +# Common bandwidth hoggers and hacking tools. +if ($http_user_agent ~ "libwww-perl") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "GetRight") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "GetWeb!") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "Go!Zilla") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "Download Demon") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "Go-Ahead-Got-It") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "TurnitinBot") { + set $block_user_agents 1; +} + +if ($http_user_agent ~ "GrabNet") { + set $block_user_agents 1; +} + +if ($block_user_agents = 1) { + return 403; +} diff --git a/roles/nginx/files/snippets/cache-assets.conf b/roles/nginx/files/snippets/cache-assets.conf new file mode 100644 index 0000000..07305fa --- /dev/null +++ b/roles/nginx/files/snippets/cache-assets.conf @@ -0,0 +1,31 @@ +location ~* ^.*\.(css|js|jpe?g|gif|png|woff|eot|ttf|svg|ico|css\.map|js\.map)$ { + if_modified_since off; + + # use the public cache + proxy_cache public-cache; + proxy_cache_key $host$request_uri; + + # ignore these headers for media + proxy_ignore_headers Set-Cookie Cache-Control Expires X-Accel-Expires; + + # cache 200s and also 404s (not ideal but there are a few 404 images for some reason) + proxy_cache_valid any 30m; + proxy_cache_valid 404 1m; + + # strip this header to avoid If-Modified-Since requests + proxy_hide_header Last-Modified; + proxy_hide_header Cache-Control; + proxy_hide_header Vary; + + proxy_cache_bypass 0; + proxy_no_cache 0; + + proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_404; + proxy_connect_timeout 5s; + proxy_read_timeout 45s; + + expires @30m; + access_log off; + + include conf.d/include/proxy.conf; +} \ No newline at end of file diff --git a/roles/nginx/files/snippets/force-ssl.conf b/roles/nginx/files/snippets/force-ssl.conf new file mode 100644 index 0000000..23083a1 --- /dev/null +++ b/roles/nginx/files/snippets/force-ssl.conf @@ -0,0 +1,3 @@ +if ($scheme = "http") { + return 301 https://$host$request_uri; +} \ No newline at end of file diff --git a/roles/nginx/files/snippets/letsencrypt-acme-challenge.conf b/roles/nginx/files/snippets/letsencrypt-acme-challenge.conf new file mode 100644 index 0000000..2075713 --- /dev/null +++ b/roles/nginx/files/snippets/letsencrypt-acme-challenge.conf @@ -0,0 +1,29 @@ +# Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx) +# We use ^~ here, so that we don't check other regexes (for speed-up). We actually MUST cancel +# other regex checks, because in our other config files have regex rule that denies access to files with dotted names. +location ^~ /.well-known/acme-challenge/ { + # Since this is for letsencrypt authentication of a domain and they do not give IP ranges of their infrastructure + # we need to open up access by turning off auth and IP ACL for this location. + auth_basic off; + allow all; + + # Set correct content type. According to this: + # https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29 + # Current specification requires "text/plain" or no content header at all. + # It seems that "text/plain" is a safe option. + default_type "text/plain"; + + # This directory must be the same as in /etc/letsencrypt/cli.ini + # as "webroot-path" parameter. Also don't forget to set "authenticator" parameter + # there to "webroot". + # Do NOT use alias, use root! Target directory is located here: + # /var/www/common/letsencrypt/.well-known/acme-challenge/ + root /data/letsencrypt-acme-challenge; +} + +# Hide /acme-challenge subdirectory and return 404 on all requests. +# It is somewhat more secure than letting Nginx return 403. +# Ending slash is important! +location = /.well-known/acme-challenge/ { + return 404; +} \ No newline at end of file diff --git a/roles/nginx/files/snippets/proxy.conf b/roles/nginx/files/snippets/proxy.conf new file mode 100644 index 0000000..f086a73 --- /dev/null +++ b/roles/nginx/files/snippets/proxy.conf @@ -0,0 +1,7 @@ +add_header X-Served-By $host; +proxy_set_header Host $host; +proxy_set_header X-Forwarded-Scheme $scheme; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Forwarded-For $remote_addr; +proxy_set_header X-Real-IP $remote_addr; +proxy_pass $forward_scheme://$server:$port; \ No newline at end of file diff --git a/roles/nginx/files/snippets/ssl-ciphers.conf b/roles/nginx/files/snippets/ssl-ciphers.conf new file mode 100644 index 0000000..e9bae0c --- /dev/null +++ b/roles/nginx/files/snippets/ssl-ciphers.conf @@ -0,0 +1,9 @@ +ssl_session_timeout 5m; +ssl_session_cache shared:SSL:50m; + +# intermediate configuration. tweak to your needs. +ssl_protocols TLSv1.2 TLSv1.3; +ssl_ciphers 'EECDH+AESGCM:AES256+EECDH:AES256+EDH:EDH+AESGCM:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE- +ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AE +S128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES'; +ssl_prefer_server_ciphers on; \ No newline at end of file