diff --git a/h5bp/basic.conf b/h5bp/basic.conf index 2b85ad4..fe9ad6c 100644 --- a/h5bp/basic.conf +++ b/h5bp/basic.conf @@ -1,6 +1,7 @@ -# Basic h5bp rules +# Nginx Server Configs | MIT License +# https://github.com/h5bp/server-configs-nginx -include h5bp/directive-only/x-ua-compatible.conf; -include h5bp/location/expires.conf; -include h5bp/location/cross-domain-fonts.conf; -include h5bp/location/protect-system-files.conf; +include h5bp/internet_explorer/x-ua-compatible.conf; +include h5bp/location/security_file_access.conf; +include h5bp/location/cross-origin_web_fonts.conf; +include h5bp/location/security_file_access.conf; diff --git a/h5bp/cross-origin/requests.conf b/h5bp/cross-origin/requests.conf new file mode 100644 index 0000000..7692fe9 --- /dev/null +++ b/h5bp/cross-origin/requests.conf @@ -0,0 +1,19 @@ +# ---------------------------------------------------------------------- +# | Cross-origin requests | +# ---------------------------------------------------------------------- + +# Allow cross-origin requests. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS +# https://enable-cors.org/ +# https://www.w3.org/TR/cors/ + +# (!) Do not use this without understanding the consequences. +# This will permit access from any other website. +# +# Instead of using this file, consider using a specific rule such as: +# +# Allow access based on [sub]domain: +# add_header Access-Control-Allow-Origin "subdomain.example.com"; + +add_header Access-Control-Allow-Origin "*"; diff --git a/h5bp/cross-origin/resource_timing.conf b/h5bp/cross-origin/resource_timing.conf new file mode 100644 index 0000000..bcd4531 --- /dev/null +++ b/h5bp/cross-origin/resource_timing.conf @@ -0,0 +1,16 @@ +# ---------------------------------------------------------------------- +# | Cross-origin resource timing | +# ---------------------------------------------------------------------- + +# Allow cross-origin access to the timing information for all resources. +# +# If a resource isn't served with a `Timing-Allow-Origin` header that +# would allow its timing information to be shared with the document, +# some of the attributes of the `PerformanceResourceTiming` object will +# be set to zero. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin +# https://www.w3.org/TR/resource-timing/ +# https://www.stevesouders.com/blog/2014/08/21/resource-timing-practical-tips/ + +add_header Timing-Allow-Origin "*"; diff --git a/h5bp/directive-only/cross-domain-insecure.conf b/h5bp/directive-only/cross-domain-insecure.conf deleted file mode 100644 index 034939a..0000000 --- a/h5bp/directive-only/cross-domain-insecure.conf +++ /dev/null @@ -1,14 +0,0 @@ -# Cross domain AJAX requests - -# https://www.w3.org/TR/cors/#access-control-allow-origin-response-header - -# **Security Warning** -# Do not use this without understanding the consequences. -# This will permit access from any other website. -# -add_header "Access-Control-Allow-Origin" "*"; - -# Instead of using this file, consider using a specific rule such as: -# -# Allow access based on [sub]domain: -# add_header "Access-Control-Allow-Origin" "subdomain.example.com"; diff --git a/h5bp/directive-only/extra-security.conf b/h5bp/directive-only/extra-security.conf deleted file mode 100644 index 25a78f8..0000000 --- a/h5bp/directive-only/extra-security.conf +++ /dev/null @@ -1,17 +0,0 @@ -# The X-Frame-Options header indicates whether a browser should be allowed -# to render a page within a frame or iframe. -add_header X-Frame-Options SAMEORIGIN always; - -# MIME type sniffing security protection -# There are very few edge cases where you wouldn't want this enabled. -add_header X-Content-Type-Options nosniff always; - -# The X-XSS-Protection header is used by Internet Explorer version 8+ -# The header instructs IE to enable its inbuilt anti-cross-site scripting filter. -add_header X-XSS-Protection "1; mode=block" always; - -# with Content Security Policy (CSP) enabled (and a browser that supports it (https://caniuse.com/#feat=contentsecuritypolicy), -# you can tell the browser that it can only download content from the domains you explicitly allow -# CSP can be quite difficult to configure, and cause real issues if you get it wrong -# There is website that helps you generate a policy here https://www.cspisawesome.com/ -# add_header Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' https://www.google-analytics.com;" always; diff --git a/h5bp/directive-only/no-transform.conf b/h5bp/directive-only/no-transform.conf deleted file mode 100644 index eda5464..0000000 --- a/h5bp/directive-only/no-transform.conf +++ /dev/null @@ -1,11 +0,0 @@ -# Prevent mobile network providers from modifying your site -# -# (!) If you are using `ngx_pagespeed`, please note that setting -# the `Cache-Control: no-transform` response header will prevent -# `PageSpeed` from rewriting `HTML` files, and, if -# `pagespeed DisableRewriteOnNoTransform off` is not used, also -# from rewriting other resources. -# -# https://developers.google.com/speed/pagespeed/module/configuration#notransform - -add_header "Cache-Control" "no-transform"; diff --git a/h5bp/directive-only/ssl-stapling.conf b/h5bp/directive-only/ssl-stapling.conf deleted file mode 100644 index d15bf97..0000000 --- a/h5bp/directive-only/ssl-stapling.conf +++ /dev/null @@ -1,9 +0,0 @@ -# OCSP stapling... -ssl_stapling on; -ssl_stapling_verify on; - -#trusted cert must be made up of your intermediate certificate followed by root certificate -#ssl_trusted_certificate /path/to/ca.crt; - -resolver 8.8.8.8 8.8.4.4 216.146.35.35 216.146.36.36 valid=60s; -resolver_timeout 2s; diff --git a/h5bp/directive-only/ssl.conf b/h5bp/directive-only/ssl.conf deleted file mode 100644 index 4b43e98..0000000 --- a/h5bp/directive-only/ssl.conf +++ /dev/null @@ -1,47 +0,0 @@ -# Protect against the BEAST and POODLE attacks by not using SSLv3 at all. If you need to support older browsers (IE6) you may need to add -# SSLv3 to the list of protocols below. -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - -# Ciphers set to best allow protection from Beast, while providing forwarding secrecy, as defined by Mozilla (Intermediate Set) - https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx -ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS; -ssl_prefer_server_ciphers on; - -# Optimize SSL by caching session parameters for 10 minutes. This cuts down on the number of expensive SSL handshakes. -# The handshake is the most CPU-intensive operation, and by default it is re-negotiated on every new/parallel connection. -# By enabling a cache (of type "shared between all Nginx workers"), we tell the client to re-use the already negotiated state. -# Further optimization can be achieved by raising keepalive_timeout, but that shouldn't be done unless you serve primarily HTTPS. -ssl_session_cache shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so we can hold 40000 sessions -ssl_session_timeout 24h; - -# SSL buffer size was added in 1.5.9 -#ssl_buffer_size 1400; # 1400 bytes to fit in one MTU - -# Session tickets appeared in version 1.5.9 -# -# nginx does not auto-rotate session ticket keys: only a HUP / restart will do so and -# when a restart is performed the previous key is lost, which resets all previous -# sessions. The fix for this is to setup a manual rotation mechanism: -# https://trac.nginx.org/nginx/changeset/1356a3b9692441e163b4e78be4e9f5a46c7479e9/nginx -# -# Note that you'll have to define and rotate the keys securely by yourself. In absence -# of such infrastructure, consider turning off session tickets: -#ssl_session_tickets off; - -# Use a higher keepalive timeout to reduce the need for repeated handshakes -keepalive_timeout 300s; # up from 75 secs default - -# HSTS (HTTP Strict Transport Security) -# This header tells browsers to cache the certificate for a year and to connect exclusively via HTTPS. -#add_header Strict-Transport-Security "max-age=31536000" always; -# This version tells browsers to treat all subdomains the same as this site and to load exclusively over HTTPS -#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; -# This version tells browsers to treat all subdomains the same as this site and to load exclusively over HTTPS -# Recommend is also to use preload service -#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - -# This default SSL certificate will be served whenever the client lacks support for SNI (Server Name Indication). -# Make it a symlink to the most important certificate you have, so that users of IE 8 and below on WinXP can see your main site without SSL errors. -#ssl_certificate /etc/nginx/default_ssl.crt; -#ssl_certificate_key /etc/nginx/default_ssl.key; - -# Consider using OCSP Stapling as shown in ssl-stapling.conf diff --git a/h5bp/directive-only/x-ua-compatible.conf b/h5bp/directive-only/x-ua-compatible.conf deleted file mode 100644 index a51bb31..0000000 --- a/h5bp/directive-only/x-ua-compatible.conf +++ /dev/null @@ -1,2 +0,0 @@ -# Force the latest IE version -add_header "X-UA-Compatible" "IE=Edge"; diff --git a/h5bp/errors/custom_errors.conf b/h5bp/errors/custom_errors.conf new file mode 100644 index 0000000..6b3e796 --- /dev/null +++ b/h5bp/errors/custom_errors.conf @@ -0,0 +1,9 @@ +# ---------------------------------------------------------------------- +# | Custom error messages/pages | +# ---------------------------------------------------------------------- + +# Customize what Nginx returns to the client in case of an error. +# +# https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page + +error_page 404 /404.html; diff --git a/h5bp/internet_explorer/x-ua-compatible.conf b/h5bp/internet_explorer/x-ua-compatible.conf new file mode 100644 index 0000000..64ea268 --- /dev/null +++ b/h5bp/internet_explorer/x-ua-compatible.conf @@ -0,0 +1,19 @@ +# ---------------------------------------------------------------------- +# | Document modes | +# ---------------------------------------------------------------------- + +# Force Internet Explorer 8/9/10 to render pages in the highest mode +# available in the various cases when it may not. +# +# https://hsivonen.fi/doctype/#ie8 +# +# (!) Starting with Internet Explorer 11, document modes are deprecated. +# If your business still relies on older web apps and services that were +# designed for older versions of Internet Explorer, you might want to +# consider enabling `Enterprise Mode` throughout your company. +# +# https://msdn.microsoft.com/en-us/library/ie/bg182625.aspx#docmode +# https://blogs.msdn.microsoft.com/ie/2014/04/02/stay-up-to-date-with-enterprise-mode-for-internet-explorer-11/ +# https://msdn.microsoft.com/en-us/library/ff955275.aspx + +add_header X-UA-Compatible "IE=Edge"; diff --git a/h5bp/location/cache-busting.conf b/h5bp/location/cache-busting.conf deleted file mode 100644 index 6afe34a..0000000 --- a/h5bp/location/cache-busting.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Built-in filename-based cache busting - -# https://github.com/h5bp/html5-boilerplate/blob/5370479476dceae7cc3ea105946536d6bc0ee468/.htaccess#L403 -# This will route all requests for /css/style.20120716.css to /css/style.css -# Read also this: github.com/h5bp/html5-boilerplate/wiki/cachebusting -# This is not included by default, because it'd be better if you use the build -# script to manage the file names. -location ~* (.+)\.(?:\d+)\.(js|css|png|jpg|jpeg|gif)$ { - try_files $uri $1.$2; -} diff --git a/h5bp/location/cross-domain-fonts.conf b/h5bp/location/cross-domain-fonts.conf deleted file mode 100644 index bfc06ae..0000000 --- a/h5bp/location/cross-domain-fonts.conf +++ /dev/null @@ -1,12 +0,0 @@ -# Cross domain webfont access -location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ { - include h5bp/directive-only/cross-domain-insecure.conf; - - # Also, set cache rules for webfonts. - # - # See https://nginx.org/en/docs/http/ngx_http_core_module.html#location - # And https://github.com/h5bp/server-configs/issues/85 - # And https://github.com/h5bp/server-configs/issues/86 - access_log off; - expires 1M; -} diff --git a/h5bp/location/cross-origin_images.conf b/h5bp/location/cross-origin_images.conf new file mode 100644 index 0000000..ed100b2 --- /dev/null +++ b/h5bp/location/cross-origin_images.conf @@ -0,0 +1,18 @@ +# ---------------------------------------------------------------------- +# | Cross-origin images | +# ---------------------------------------------------------------------- + +# Send the CORS header for images when browsers request it. +# +# https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image +# https://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html + +location ~* \.(?:bmp|cur|gif|ico|jpe?g|png|svgz?|webp?)$ { + include h5bp/cross-origin/requests.conf; + + # Also, set cache rules for images. + # + # https://nginx.org/en/docs/http/ngx_http_core_module.html#location + access_log off; + expires 1M; +} diff --git a/h5bp/location/cross-origin_web_fonts.conf b/h5bp/location/cross-origin_web_fonts.conf new file mode 100644 index 0000000..3f700cd --- /dev/null +++ b/h5bp/location/cross-origin_web_fonts.conf @@ -0,0 +1,19 @@ +# ---------------------------------------------------------------------- +# | Cross-origin web fonts | +# ---------------------------------------------------------------------- + +# Allow cross-origin access to web fonts. +# +# https://developers.google.com/fonts/docs/troubleshooting + +location ~* \.(?:eot|otf|tt[cf]|woff2?)$ { + include h5bp/cross-origin/requests.conf; + + # Also, set cache rules for web fonts. + # + # https://nginx.org/en/docs/http/ngx_http_core_module.html#location + # https://github.com/h5bp/server-configs/issues/85 + # https://github.com/h5bp/server-configs/issues/86 + access_log off; + expires 1M; +} diff --git a/h5bp/location/protect-system-files.conf b/h5bp/location/protect-system-files.conf deleted file mode 100644 index 128c49a..0000000 --- a/h5bp/location/protect-system-files.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Prevent clients from accessing hidden files (starting with a dot) -# This is particularly important if you store .htpasswd files in the site hierarchy -# Access to `/.well-known/` is allowed. -# https://www.mnot.net/blog/2010/04/07/well-known -# https://tools.ietf.org/html/rfc5785 -location ~* /\.(?!well-known\/) { - deny all; -} - -# Prevent clients from accessing to backup/config/source files -location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|psd|sh|sql|sw[op])|~)$ { - deny all; -} diff --git a/h5bp/location/security_file_access.conf b/h5bp/location/security_file_access.conf new file mode 100644 index 0000000..fcf9204 --- /dev/null +++ b/h5bp/location/security_file_access.conf @@ -0,0 +1,42 @@ +# ---------------------------------------------------------------------- +# | File access | +# ---------------------------------------------------------------------- + +# Block access to all hidden files and directories with the exception of +# the visible content from within the `/.well-known/` hidden directory. +# +# These types of files usually contain user preferences or the preserved +# state of an utility, and can include rather private places like, for +# example, the `.git` or `.svn` directories. +# +# The `/.well-known/` directory represents the standard (RFC 5785) path +# prefix for "well-known locations" (e.g.: `/.well-known/manifest.json`, +# `/.well-known/keybase.txt`), and therefore, access to its visible +# content should not be blocked. +# +# https://www.mnot.net/blog/2010/04/07/well-known +# https://tools.ietf.org/html/rfc5785 + +location ~* /\.(?!well-known\/) { + deny all; +} + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Block access to files that can expose sensitive information. +# +# By default, block access to backup and source files that may be +# left by some text editors and can pose a security risk when anyone +# has access to them. +# +# https://feross.org/cmsploit/ +# +# (!) Update the `location` regular expression from below to +# include any files that might end up on your production server and +# can expose sensitive information about your website. These files may +# include: configuration files, files that contain metadata about the +# project (e.g.: project dependencies), build scripts, etc.. + +location ~* (?:\.(?:bak|conf|dist|fla|in[ci]|log|orig|psd|sh|sql|sw[op])|~)$ { + deny all; +} diff --git a/h5bp/location/expires.conf b/h5bp/location/web_performance_cache_expiration.conf similarity index 56% rename from h5bp/location/expires.conf rename to h5bp/location/web_performance_cache_expiration.conf index 3dc41df..cdb2596 100644 --- a/h5bp/location/expires.conf +++ b/h5bp/location/web_performance_cache_expiration.conf @@ -1,4 +1,16 @@ -# Expire rules for static content +# ---------------------------------------------------------------------- +# | Cache expiration | +# ---------------------------------------------------------------------- + +# Serve resources with far-future expiration date. +# +# (!) If you don't control versioning with filename-based +# cache busting, you should consider lowering the cache times +# to something like one week. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires +# https://nginx.org/en/docs/http/ngx_http_headers_module.html#expires # No default expire rule. This config mirrors that of apache as outlined in the # html5-boilerplate .htaccess file. However, nginx applies rules by location, @@ -8,17 +20,17 @@ # future (if the default expire rule is 1 month). Therefore, do not use a # default expire rule with nginx unless your site is completely static -# cache.appcache, your document html and data +# Documents location ~* \.(?:manifest|appcache|html?|xml|json)$ { expires 0; } -# Feed +# Feeds location ~* \.(?:rss|atom)$ { expires 1h; } -# Media: images, icons, video, audio, HTC +# Media files location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|mp4|ogg|ogv|webm|htc)$ { access_log off; expires 1M; @@ -31,15 +43,15 @@ location ~* \.svgz$ { expires 1M; } -# CSS and Javascript +# CSS and JavaScript location ~* \.(?:css|js)$ { expires 1y; access_log off; } -# WebFonts +# Web fonts # If you are NOT using cross-domain-fonts.conf, uncomment the following directive -# location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ { -# expires 1M; -# access_log off; +# location ~* \.(?:eot|otf|tt[cf]|woff2?)$ { +# expires 1M; +# access_log off; # } diff --git a/h5bp/location/web_performance_filename-based_cache_busting.conf b/h5bp/location/web_performance_filename-based_cache_busting.conf new file mode 100644 index 0000000..c2c9435 --- /dev/null +++ b/h5bp/location/web_performance_filename-based_cache_busting.conf @@ -0,0 +1,14 @@ +# ---------------------------------------------------------------------- +# | Filename-based cache busting | +# ---------------------------------------------------------------------- + +# If you're not using a build process to manage your filename version +# revving, you might want to consider enabling the following directives +# +# To understand why this is important and even a better solution than +# using something like `*.css?v231`, please see: +# https://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ + +location ~* (.+)\.(?:\d+)\.(bmp|css|cur|gif|ico|jpe?g|m?js|png|svgz?|webp|webmanifest)$ { + try_files $uri $1.$2; +} diff --git a/h5bp/security/content-security-policy.conf b/h5bp/security/content-security-policy.conf new file mode 100644 index 0000000..fb36a5e --- /dev/null +++ b/h5bp/security/content-security-policy.conf @@ -0,0 +1,23 @@ +# ---------------------------------------------------------------------- +# | Content Security Policy (CSP) | +# ---------------------------------------------------------------------- + +# Mitigate the risk of cross-site scripting and other content-injection +# attacks. +# +# This can be done by setting a `Content Security Policy` which +# whitelists trusted sources of content for your website. +# +# The example header below allows ONLY scripts that are loaded from +# the current website's origin (no inline scripts, no CDN, etc). +# That almost certainly won't work as-is for your website! +# +# To make things easier, you can use an online CSP header generator +# such as: https://www.cspisawesome.com/. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy +# https://www.w3.org/TR/CSP3/ +# https://content-security-policy.com/ +# https://www.html5rocks.com/en/tutorials/security/content-security-policy/ + +add_header Content-Security-Policy "script-src 'self'; object-src 'self'" always; diff --git a/h5bp/security/referrer-policy.conf b/h5bp/security/referrer-policy.conf new file mode 100644 index 0000000..58136e8 --- /dev/null +++ b/h5bp/security/referrer-policy.conf @@ -0,0 +1,18 @@ +# ---------------------------------------------------------------------- +# | Referrer Policy | +# ---------------------------------------------------------------------- + +# A web application uses HTTPS and a URL-based session identifier. +# The web application might wish to link to HTTPS resources on other +# web sites without leaking the user's session identifier in the URL. +# +# This can be done by setting a `Referrer Policy` which +# whitelists trusted sources of content for your website. +# +# To check your referrer policy, you can use an online service +# such as: https://securityheaders.io/. +# +# https://scotthelme.co.uk/a-new-security-header-referrer-policy/ +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy + +add_header Referrer-Policy "no-referrer-when-downgrade" always; diff --git a/h5bp/security/server_software_information.conf b/h5bp/security/server_software_information.conf new file mode 100644 index 0000000..5e1bf00 --- /dev/null +++ b/h5bp/security/server_software_information.conf @@ -0,0 +1,10 @@ +# ---------------------------------------------------------------------- +# | Server software information | +# ---------------------------------------------------------------------- + +# Prevent Nginx from sending in the `Server` response header its +# exact version number. +# +# https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens + +server_tokens off; diff --git a/h5bp/security/ssl_policy.conf b/h5bp/security/ssl_policy.conf new file mode 100644 index 0000000..15eaa34 --- /dev/null +++ b/h5bp/security/ssl_policy.conf @@ -0,0 +1,64 @@ +# ---------------------------------------------------------------------- +# | SSL Policy | +# ---------------------------------------------------------------------- + +# Cipher suites and directive for strong security +# +# https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations +# https://mozilla.github.io/server-side-tls/ssl-config-generator/ +# https://nginx.org/en/docs/http/ngx_http_ssl_module.html + +# Protect against the BEAST and POODLE attacks by not using SSLv3 at all. If you need to support older browsers (IE6) you may need to add +# SSLv3 to the list of protocols below. +ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + +# Ciphers set to best allow protection from Beast, while providing forwarding secrecy, as defined by Mozilla (Intermediate Set) - https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx +ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS; +ssl_prefer_server_ciphers on; + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Optimize SSL by caching session parameters for 10 minutes. This cuts down on the number of expensive SSL handshakes. +# The handshake is the most CPU-intensive operation, and by default it is re-negotiated on every new/parallel connection. +# By enabling a cache (of type "shared between all Nginx workers"), we tell the client to re-use the already negotiated state. +# Further optimization can be achieved by raising keepalive_timeout, but that shouldn't be done unless you serve primarily HTTPS. +ssl_session_cache shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so we can hold 40000 sessions +ssl_session_timeout 24h; + +# SSL buffer size +# ssl_buffer_size 1400; # 1400 bytes to fit in one MTU + +# Session tickets +# +# nginx does not auto-rotate session ticket keys: only a HUP / restart will do so and +# when a restart is performed the previous key is lost, which resets all previous +# sessions. The fix for this is to setup a manual rotation mechanism: +# https://trac.nginx.org/nginx/changeset/1356a3b9692441e163b4e78be4e9f5a46c7479e9/nginx +# +# Note that you'll have to define and rotate the keys securely by yourself. In absence +# of such infrastructure, consider turning off session tickets: +ssl_session_tickets off; + +# Use a higher keepalive timeout to reduce the need for repeated handshakes +keepalive_timeout 300s; # up from 75 secs default + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# This default SSL certificate will be served whenever the client lacks support for SNI (Server Name Indication). +# Make it a symlink to the most important certificate you have, so that users of IE 8 and below on WinXP can see your main site without SSL errors. + +# ssl_certificate /etc/nginx/default_ssl.crt; +# ssl_certificate_key /etc/nginx/default_ssl.key; + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# OCSP stapling + +# ssl_stapling on; +# ssl_stapling_verify on; + +# Trusted certificate must be made up of your intermediate certificate followed by root certificate +# ssl_trusted_certificate /path/to/ca.crt; + +# resolver 8.8.8.8 8.8.4.4 216.146.35.35 216.146.36.36 valid=60s; +# resolver_timeout 2s; diff --git a/h5bp/security/strict-transport-security.conf b/h5bp/security/strict-transport-security.conf new file mode 100644 index 0000000..7fe0e6e --- /dev/null +++ b/h5bp/security/strict-transport-security.conf @@ -0,0 +1,42 @@ +# ---------------------------------------------------------------------- +# | HTTP Strict Transport Security (HSTS) | +# ---------------------------------------------------------------------- + +# Force client-side SSL redirection. +# +# If a user types `example.com` in their browser, even if the server +# redirects them to the secure version of the website, that still leaves +# a window of opportunity (the initial HTTP connection) for an attacker +# to downgrade or redirect the request. +# +# The following header ensures that browser will ONLY connect to your +# server via HTTPS, regardless of what the users type in the browser's +# address bar. +# +# (!) Be aware that this, once published, is not revokable and you must ensure +# being able to serve the site via SSL for the duration you've specified +# in max-age. When you don't have a valid SSL connection (anymore) your +# visitors will see a nasty error message even when attempting to connect +# via simple HTTP. +# +# (!) Remove the `includeSubDomains` optional directive if the website's +# subdomains are not using HTTPS. +# +# (1) If you want to submit your site for HSTS preload (2) you must +# * ensure the `includeSubDomains` directive to be present +# * the `preload` directive to be specified +# * the `max-age` to be at least 31536000 seconds (1 year) according to the current status. +# +# It is also advised (3) to only serve the HSTS header via a secure connection. +# +# (2) https://hstspreload.org/ +# (3) https://tools.ietf.org/html/rfc6797#section-7.2 +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security +# https://tools.ietf.org/html/rfc6797#section-6.1 +# https://www.html5rocks.com/en/tutorials/security/transport-layer-security/ +# https://blogs.msdn.microsoft.com/ieinternals/2014/08/18/strict-transport-security/ + +add_header Strict-Transport-Security "max-age=16070400; includeSubDomains" always; +# (1) or if HSTS preloading is desired (respect (2) for current requirements): +# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; diff --git a/h5bp/security/x-content-type-options.conf b/h5bp/security/x-content-type-options.conf new file mode 100644 index 0000000..3c24518 --- /dev/null +++ b/h5bp/security/x-content-type-options.conf @@ -0,0 +1,16 @@ +# ---------------------------------------------------------------------- +# | Reducing MIME type security risks | +# ---------------------------------------------------------------------- + +# Prevent some browsers from MIME-sniffing the response. +# +# This reduces exposure to drive-by download attacks and cross-origin +# data leaks, and should be left uncommented, especially if the server +# is serving user-uploaded content or content that could potentially be +# treated as executable by the browser. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options +# https://blogs.msdn.microsoft.com/ie/2008/07/02/ie8-security-part-v-comprehensive-protection/ +# https://mimesniff.spec.whatwg.org/ + +add_header X-Content-Type-Options nosniff always; diff --git a/h5bp/security/x-frame-options.conf b/h5bp/security/x-frame-options.conf new file mode 100644 index 0000000..f0a5e9e --- /dev/null +++ b/h5bp/security/x-frame-options.conf @@ -0,0 +1,36 @@ +# ---------------------------------------------------------------------- +# | Clickjacking | +# ---------------------------------------------------------------------- + +# Protect website against clickjacking. +# +# The example below sends the `X-Frame-Options` response header with +# the value `DENY`, informing browsers not to display the content of +# the web page in any frame. +# +# This might not be the best setting for everyone. You should read +# about the other two possible values the `X-Frame-Options` header +# field can have: `SAMEORIGIN` and `ALLOW-FROM`. +# https://tools.ietf.org/html/rfc7034#section-2.1. +# +# Keep in mind that while you could send the `X-Frame-Options` header +# for all of your website’s pages, this has the potential downside that +# it forbids even non-malicious framing of your content (e.g.: when +# users visit your website using a Google Image Search results page). +# +# Nonetheless, you should ensure that you send the `X-Frame-Options` +# header for all pages that allow a user to make a state changing +# operation (e.g: pages that contain one-click purchase links, checkout +# or bank-transfer confirmation pages, pages that make permanent +# configuration changes, etc.). +# +# Sending the `X-Frame-Options` header can also protect your website +# against more than just clickjacking attacks: +# https://cure53.de/xfo-clickjacking.pdf. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options +# https://tools.ietf.org/html/rfc7034 +# https://blogs.msdn.microsoft.com/ieinternals/2010/03/30/combating-clickjacking-with-x-frame-options/ +# https://www.owasp.org/index.php/Clickjacking + +add_header X-Frame-Options DENY always; diff --git a/h5bp/security/x-xss-protection.conf b/h5bp/security/x-xss-protection.conf new file mode 100644 index 0000000..71a5154 --- /dev/null +++ b/h5bp/security/x-xss-protection.conf @@ -0,0 +1,39 @@ +# ---------------------------------------------------------------------- +# | Reflected Cross-Site Scripting (XSS) attacks | +# ---------------------------------------------------------------------- + +# (1) Try to re-enable the cross-site scripting (XSS) filter built +# into most web browsers. +# +# The filter is usually enabled by default, but in some cases it +# may be disabled by the user. However, in Internet Explorer for +# example, it can be re-enabled just by sending the +# `X-XSS-Protection` header with the value of `1`. +# +# (2) Prevent web browsers from rendering the web page if a potential +# reflected (a.k.a non-persistent) XSS attack is detected by the +# filter. +# +# By default, if the filter is enabled and browsers detect a +# reflected XSS attack, they will attempt to block the attack +# by making the smallest possible modifications to the returned +# web page. +# +# Unfortunately, in some browsers (e.g.: Internet Explorer), +# this default behavior may allow the XSS filter to be exploited, +# thereby, it's better to inform browsers to prevent the rendering +# of the page altogether, instead of attempting to modify it. +# +# https://hackademix.net/2009/11/21/ies-xss-filter-creates-xss-vulnerabilities +# +# (!) Do not rely on the XSS filter to prevent XSS attacks! Ensure that +# you are taking all possible measures to prevent XSS attacks, the +# most obvious being: validating and sanitizing your website's inputs. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection +# https://blogs.msdn.microsoft.com/ie/2008/07/02/ie8-security-part-iv-the-xss-filter/ +# https://blogs.msdn.microsoft.com/ieinternals/2011/01/31/controlling-the-xss-filter/ +# https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29 + +# (1) (2) +add_header X-XSS-Protection "1; mode=block" always; diff --git a/h5bp/directive-only/cache-file-descriptors.conf b/h5bp/web_performance/cache-file-descriptors.conf similarity index 93% rename from h5bp/directive-only/cache-file-descriptors.conf rename to h5bp/web_performance/cache-file-descriptors.conf index ed312c0..c03dcb7 100644 --- a/h5bp/directive-only/cache-file-descriptors.conf +++ b/h5bp/web_performance/cache-file-descriptors.conf @@ -13,6 +13,9 @@ # A maximum of the 1000 most recently used file descriptors can be cached at any time. # # Production servers with stable file collections will definitely want to enable the cache. + +# https://nginx.org/en/docs/http/ngx_http_core_module.html#open_file_cache + open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; diff --git a/h5bp/web_performance/compression.conf b/h5bp/web_performance/compression.conf new file mode 100644 index 0000000..de6b077 --- /dev/null +++ b/h5bp/web_performance/compression.conf @@ -0,0 +1,73 @@ +# ---------------------------------------------------------------------- +# | Compression | +# ---------------------------------------------------------------------- + +# https://nginx.org/en/docs/http/ngx_http_gzip_module.html + +# Enable gzip compression. +# Default: off +gzip on; + +# Compression level (1-9). +# 5 is a perfect compromise between size and CPU usage, offering about +# 75% reduction for most ASCII files (almost identical to level 9). +# Default: 1 +gzip_comp_level 5; + +# Don't compress anything that's already small and unlikely to shrink much +# if at all (the default is 20 bytes, which is bad as that usually leads to +# larger files after gzipping). +# Default: 20 +gzip_min_length 256; + +# Compress data even for clients that are connecting to us via proxies, +# identified by the "Via" header (required for CloudFront). +# Default: off +gzip_proxied any; + +# Tell proxies to cache both the gzipped and regular version of a resource +# whenever the client's Accept-Encoding capabilities header varies; +# Avoids the issue where a non-gzip capable client (which is extremely rare +# today) would display gibberish if their proxy gave them the gzipped version. +# Default: off +gzip_vary on; + +# Compress all output labeled with one of the following MIME-types. +# text/html is always compressed by gzip module. +# Default: text/html +gzip_types + application/atom+xml + application/javascript + application/json + application/ld+json + application/manifest+json + application/rss+xml + application/geo+json + application/vnd.ms-fontobject + application/x-font-ttf + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + application/rdf+xml + font/collection + font/opentype + font/otf + font/ttf + image/bmp + image/svg+xml + image/x-icon + text/cache-manifest + text/css + text/javascript + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + +# This should be turned on if you are going to have pre-compressed copies (.gz) of +# static files available. If not it should be left off as it will cause extra I/O +# for the check. It is best if you enable this in a location{} block for +# a specific directory, or on an individual server{} level. +# gzip_static on; diff --git a/h5bp/web_performance/no-transform.conf b/h5bp/web_performance/no-transform.conf new file mode 100644 index 0000000..82b2f4b --- /dev/null +++ b/h5bp/web_performance/no-transform.conf @@ -0,0 +1,20 @@ +# ---------------------------------------------------------------------- +# | Content transformation | +# ---------------------------------------------------------------------- + +# Prevent intermediate caches or proxies (e.g.: such as the ones +# used by mobile network providers) from modifying the website's +# content. +# +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control +# https://tools.ietf.org/html/rfc2616#section-14.9.5 +# +# (!) If you are using `ngx_pagespeed`, please note that setting +# the `Cache-Control: no-transform` response header will prevent +# `PageSpeed` from rewriting `HTML` files, and, if the +# `pagespeed DisableRewriteOnNoTransform off` directive isn't used, +# also from rewriting other resources. +# +# https://developers.google.com/speed/pagespeed/module/configuration#notransform + +add_header Cache-Control "no-transform"; diff --git a/nginx.conf b/nginx.conf index f5120cf..6025fe9 100644 --- a/nginx.conf +++ b/nginx.conf @@ -3,51 +3,68 @@ # Run as a unique, less privileged user for security reasons. # Default: nobody nobody +# https://nginx.org/en/docs/ngx_core_module.html#user user www www; # Sets the worker threads to the number of CPU cores available in the system for best performance. # Should be > the number of CPU cores. # Maximum number of connections = worker_processes * worker_connections # Default: 1 +# https://nginx.org/en/docs/ngx_core_module.html#worker_processes worker_processes auto; # Maximum number of open files per worker process. # Should be > worker_connections. # Default: no limit +# https://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile worker_rlimit_nofile 8192; +# Provides the configuration file context in which the directives +# that affect connection processing are specified. +# https://nginx.org/en/docs/ngx_core_module.html#events events { + # If you need more connections than this, you start optimizing your OS. # That's probably the point at which you hire people who are smarter than you as this is *a lot* of requests. # Should be < worker_rlimit_nofile. # Default: 512 + # https://nginx.org/en/docs/ngx_core_module.html#worker_connections worker_connections 8000; + } # Log errors and warnings to this file # This is only used when you don't override it on a server{} level # Default: logs/error.log error -error_log logs/error.log warn; +# https://nginx.org/en/docs/ngx_core_module.html#error_log +error_log logs/error.log warn; # The file storing the process ID of the main process -# Default: nginx.pid -pid /var/run/nginx.pid; +# Default: logs/nginx.pid +# https://nginx.org/en/docs/ngx_core_module.html#pid +pid /var/run/nginx.pid; http { # Hide nginx version information. - # Default: on - server_tokens off; + include h5bp/security/server_software_information.conf; # Specify MIME types for files. - include mime.types; + # https://nginx.org/en/docs/http/ngx_http_core_module.html#types + include mime.types; # Default: text/plain - default_type application/octet-stream; + # https://nginx.org/en/docs/http/ngx_http_core_module.html#default_type + default_type application/octet-stream; + + # Specify a charset + # https://nginx.org/en/docs/http/ngx_http_charset_module.html#charset + charset utf-8; # Update charset_types to match updated mime.types. # text/html is always included by charset module. # Default: text/html text/xml text/plain text/vnd.wap.wml application/javascript application/rss+xml + # https://nginx.org/en/docs/http/ngx_http_charset_module.html#charset_types charset_types text/css text/plain @@ -58,6 +75,7 @@ http { application/xml; # Include $http_x_forwarded_for within default format used in log files + # https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; @@ -65,12 +83,14 @@ http { # Log access to this file # This is only used when you don't override it on a server{} level # Default: logs/access.log combined + # https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log access_log logs/access.log main; # How long to allow each connection to stay idle. # Longer values are better for each individual client, particularly for SSL, # but means that worker connections are tied up longer. # Default: 75s + # https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout keepalive_timeout 20s; # Speed up file transfers by using sendfile() to copy directly @@ -79,84 +99,22 @@ http { # this option should be disabled as ZFS's ARC caches # frequently used files in RAM by default. # Default: off - sendfile on; + # https://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile + sendfile on; # Don't send out partial frames; this increases throughput # since TCP frames are filled up before being sent out. # Default: off - tcp_nopush on; + # https://nginx.org/en/docs/http/ngx_http_core_module.html#tcp_nopush + tcp_nopush on; # Enable gzip compression. - # Default: off - gzip on; - - # Compression level (1-9). - # 5 is a perfect compromise between size and CPU usage, offering about - # 75% reduction for most ASCII files (almost identical to level 9). - # Default: 1 - gzip_comp_level 5; - - # Don't compress anything that's already small and unlikely to shrink much - # if at all (the default is 20 bytes, which is bad as that usually leads to - # larger files after gzipping). - # Default: 20 - gzip_min_length 256; - - # Compress data even for clients that are connecting to us via proxies, - # identified by the "Via" header (required for CloudFront). - # Default: off - gzip_proxied any; - - # Tell proxies to cache both the gzipped and regular version of a resource - # whenever the client's Accept-Encoding capabilities header varies; - # Avoids the issue where a non-gzip capable client (which is extremely rare - # today) would display gibberish if their proxy gave them the gzipped version. - # Default: off - gzip_vary on; - - # Compress all output labeled with one of the following MIME-types. - # text/html is always compressed by gzip module. - # Default: text/html - gzip_types - application/atom+xml - application/javascript - application/json - application/ld+json - application/manifest+json - application/rss+xml - application/geo+json - application/vnd.ms-fontobject - application/x-font-ttf - application/x-web-app-manifest+json - application/xhtml+xml - application/xml - application/rdf+xml - font/collection - font/opentype - font/otf - font/ttf - image/bmp - image/svg+xml - image/x-icon - text/cache-manifest - text/css - text/javascript - text/plain - text/vcard - text/vnd.rim.location.xloc - text/vtt - text/x-component - text/x-cross-domain-policy; - - # This should be turned on if you are going to have pre-compressed copies (.gz) of - # static files available. If not it should be left off as it will cause extra I/O - # for the check. It is best if you enable this in a location{} block for - # a specific directory, or on an individual server{} level. - # gzip_static on; + include h5bp/web_performance/compression.conf; # Include files in the sites-enabled folder. server{} configuration files should be # placed in the sites-available folder, and then the configuration should be enabled # by creating a symlink to it in the sites-enabled folder. # See doc/sites-enabled.md for more info. include sites-enabled/*; + } diff --git a/sites-available/example.com b/sites-available/example.com index 01af103..4d94697 100644 --- a/sites-available/example.com +++ b/sites-available/example.com @@ -28,9 +28,6 @@ server { # Path for static files root /sites/example.com/public; - # Specify a charset - charset utf-8; - # Custom 404 page error_page 404 /404.html; diff --git a/sites-available/ssl.example.com b/sites-available/ssl.example.com index c51c5c4..0556cd5 100644 --- a/sites-available/ssl.example.com +++ b/sites-available/ssl.example.com @@ -43,9 +43,6 @@ server { # Path for static files root /var/www/example.com/public; - #Specify a charset - charset utf-8; - # Custom 404 page error_page 404 /404.html;