-
-
Save plentz/6737338 to your computer and use it in GitHub Desktop.
# to generate your dhparam.pem file, run in the terminal | |
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048 |
# don't send the nginx version number in error pages and Server header | |
server_tokens off; | |
# config to don't allow the browser to render the page inside an frame or iframe | |
# and avoid clickjacking http://en.wikipedia.org/wiki/Clickjacking | |
# if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri | |
# https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options | |
add_header X-Frame-Options SAMEORIGIN; | |
# when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header, | |
# to disable content-type sniffing on some browsers. | |
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers | |
# currently suppoorted in IE > 8 http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx | |
# http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx | |
# 'soon' on Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=471020 | |
add_header X-Content-Type-Options nosniff; | |
# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers. | |
# It's usually enabled by default anyway, so the role of this header is to re-enable the filter for | |
# this particular website if it was disabled by the user. | |
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers | |
add_header X-XSS-Protection "1; mode=block"; | |
# with Content Security Policy (CSP) enabled(and a browser that supports it(http://caniuse.com/#feat=contentsecuritypolicy), | |
# you can tell the browser that it can only download content from the domains you explicitly allow | |
# http://www.html5rocks.com/en/tutorials/security/content-security-policy/ | |
# https://www.owasp.org/index.php/Content_Security_Policy | |
# I need to change our application code so we can increase security by disabling 'unsafe-inline' 'unsafe-eval' | |
# directives for css and js(if you have inline css or js, you will need to keep it too). | |
# more: http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful | |
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://assets.zendesk.com; font-src 'self' https://themes.googleusercontent.com; frame-src https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none'"; | |
# redirect all http traffic to https | |
server { | |
listen 80 default_server; | |
listen [::]:80 default_server; | |
server_name .forgott.com; | |
return 301 https://$host$request_uri; | |
} | |
server { | |
listen 443 ssl http2; | |
listen [::]:443 ssl http2; | |
server_name .forgott.com; | |
ssl_certificate /etc/nginx/ssl/star_forgott_com.crt; | |
ssl_certificate_key /etc/nginx/ssl/star_forgott_com.key; | |
# enable session resumption to improve https performance | |
# http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html | |
ssl_session_cache shared:SSL:50m; | |
ssl_session_timeout 1d; | |
ssl_session_tickets off; | |
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits | |
ssl_dhparam /etc/nginx/ssl/dhparam.pem; | |
# enables server-side protection from BEAST attacks | |
# http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.html | |
ssl_prefer_server_ciphers on; | |
# disable SSLv3(enabled by default since nginx 0.8.19) since it's less secure then TLS http://en.wikipedia.org/wiki/Secure_Sockets_Layer#SSL_3.0 | |
ssl_protocols TLSv1.2 TLSv1.3; | |
# ciphers chosen for forward secrecy and compatibility | |
# http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html | |
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'; | |
# enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner) | |
# http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/ | |
resolver 8.8.8.8 8.8.4.4; | |
ssl_stapling on; | |
ssl_stapling_verify on; | |
ssl_trusted_certificate /etc/nginx/ssl/star_forgott_com.crt; | |
# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security | |
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping | |
# also https://hstspreload.org/ | |
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; | |
# ... the rest of your configuration | |
} |
The X-Content-Type-Options nosniff
should only be applied for Javascript and CSS files.
For anything else, it's just an extraneous useless HTTP header transferred with every request.
To avoid such pitfalls, use ngx_security_headers module which knows when to set respective header and also accounts for things like not sending headers during conditional GET
requests.
security_headers on;
Hi @plentz,
When use add_header
on multiple blocks, nginx only get the last one and ignore all parents blocks. Let check again plz
I compiled few optimization hacks to increase requests/second.
Optimizations: Tuning Nginx for better RPS of an HTTP API
☮️ 🍰 ✨
The
X-Content-Type-Options nosniff
should only be applied for Javascript and CSS files.
For anything else, it's just an extraneous useless HTTP header transferred with every request.To avoid such pitfalls, use ngx_security_headers module which knows when to set respective header and also accounts for things like not sending headers during conditional
GET
requests.security_headers on;
I see you currently have X-Content-Type-Options nosniff
applied to your own website's HTML (index page) and all other assets.
TLSv1.3 should be added: ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
TLSv1 & TLSv1.1 should be removed. Otherwise the HTTPS rating is capped at B
. ssl_protocols TLSv1.2 TLSv1.3;
https://blog.qualys.com/ssllabs/2018/11/19/grade-change-for-tls-1-0-and-tls-1-1-protocols
@rooch84 thanks, I've updated it.
These are my settings for nginx with LetsEncrypt SSL for an A+ score on Qualys:
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_buffer_size 1400;
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_session_tickets off;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;
resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001];
resolver_timeout 5s;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
For dhparam.pem I've used this:
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
I would suggest installing haveged and have it running prior of dhparam.pem generation (otherwise it would take quite some long time)
These are my settings for nginx with LetsEncrypt SSL for an A+ score on Qualys:
ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_buffer_size 1400;
ssl_ecdh_curve secp521r1:secp384r1:prime256v1;
ssl_session_tickets off;ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001];
resolver_timeout 5s;
ssl_stapling on;
ssl_stapling_verify on;add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;For dhparam.pem I've used this:
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096I would suggest installing haveged and have it running prior of dhparam.pem generation (otherwise it would take quite some long time)
Thanks for this! Very useful indeed!
Here is HTTP/3 support
https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/
server {
listen 443 ssl; # TCP listener for HTTP/1.1
listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3
ssl_protocols TLSv1.3; # QUIC requires TLS 1.3
ssl_certificate ssl/www.example.com.crt;
ssl_certificate_key ssl/www.example.com.key;
add_header Alt-Svc 'quic=":443"'; # Advertise that QUIC is available
add_header QUIC-Status $quic; # Sent when QUIC was used
}
You should probably change the resolver to
1.1.1.1
1.0.0.1
Which are Cloudflare's DNS servers, which are privacy focused and faster than Google
@rfl890 do you have any supporting evidence? I don't dispute your claims, but I think changes should be made objectively.
@rooch84 Well if you go to their website (https://1.1.1.1/) and scroll down a bit, it shows a comparison between DNS resolvers and it shows that it is indeed the fastest. They might be lying, but what reason would they have? You don't pay for using the DNS itself, it's free. And in the privacy policy (https://www.cloudflare.com/application/privacypolicy/), in section 2, they specifically say they only collect the minimum amount of data needed and all data is anonymized. I'm not trying to "root for them" or anything, but well, you asked for it
Thanks @rfl890 and @Peneheals for the info. Looks like a sensible change to me.
Getting an unknown variable "quic". Http/3 works on Chromium but not Firefox, what do I have to do?
EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES128+EDH
This prioritizes cipher suites that support PFS and use ECC, while also using 128-bit encryption for improved performance on older devices.
The config I've provided on the 7th of March 2020 is still working and you're getting an A+ grade on Qualys SSL check.
The config I've provided on the 7th of March 2020 is still working and you're getting an A+ grade on Qualys SSL check.
That does depend on what version of NGINX you're using it with, and what your target audience is..
Thanks for the config. I try to implement using nginx 1.16.0 stable.
My redirect point to proxy_pass. if user types " https://my.domain.com" or " https://my.domain.com/anything" I need to redirect.
Rest of it must show a error page. I reconfigure to point all the error page must shows the index.html.
What is wrong with my config (etc/nginx/conf.d/default.conf) file? I am keep getting nginx default 404. I can not override error 400 and 500 to points the my index.html file.
Any idea how to correct the issue.