| # to generate your dhparam.pem file, run in the terminal | |
| openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048 |
| # read more here http://tautt.com/best-nginx-configuration-for-security/ | |
| # 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'"; | |
| server { | |
| listen 443 ssl default deferred; | |
| 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 5m; | |
| # 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 TLSv1.1 TLSv1.2; | |
| # 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-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; | |
| # 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; | |
| ssl_stapling 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 | |
| add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; | |
| # ... the rest of your configuration | |
| } | |
| # redirect all http traffic to https | |
| server { | |
| listen 80; | |
| server_name .forgott.com; | |
| return 301 https://$host$request_uri; | |
| } |
@ryankearney updated, thanks :)
ssl_session_timeout 5m; <- Should this appear twice in the config?
@barrybingo that is probably a typo. once is just enough.
As you're already redirecting all HTTP traffic to HTTPS, have you looked into using SPDY to increase performance?
nginx 1.5.10 (mainline) has SPDY 3.1 support.
Also if you're running nginx as a proxy have you considered turning off the X-Powered-By header by adding the following line to the server config section.
proxy_hide_header X-Powered-By;
How to force redirect all request to www. version?
Here's my current config:
###
server {
server_name domain.com www.domain.com;
return 301 https://www.domain.com$request_uri;
}
server {
listen 443 ssl spdy;
server_name www.domain.com;
###
domain.com to https://www.domain.com = Works
www.domain.com to https://www.domain.com = Works
https://domain.com to https://www.domain.com = Not working
@barrybingo not really, thanks!
nice work
RoldanLT
ssltunnel.net to https://www.ssltunnel.net = Works
www.ssltunnel.net to https://www.ssltunnel.net = Works
https://ssltunnel.net to https://www.ssltunnel.net = Works
#ssltunnel.net
server {
listen 80;
server_name ssltunnel.net www.ssltunnel.net;
rewrite ^ https://www.ssltunnel.net$request_uri? permanent;
}
server {
listen 443 ssl spdy;
server_name ssltunnel.net;
rewrite ^ https://www.ssltunnel.net$request_uri? permanent;
ssl on;
ssl_certificate ssltunnel.net.crt;
ssl_certificate_key ssltunnel.net.key;
}
server {
listen 443 ssl spdy;
server_name www.ssltunnel.net
...
Thanks vincentclee!
I'm using this now and it works :)
###
server {
listen 80;
server_name phcorner.net www.phcorner.net;
return 301 https://www.phcorner.net$request_uri;
}
server {
listen 443 ssl spdy;
server_name phcorner.net;
return 301 https://www.phcorner.net$request_uri;
ssl on;
ssl_certificate /ssl-unified.crt;
ssl_certificate_key /net.key;
}
server {
listen 443 ssl spdy;
server_name www.phcorner.net;
...
###
The browser will only listen to the Strict-Transport-Security header if the connection was established via HTTPS. The first time the visitor connects to the website using HTTP, the visitor needs to be redirected using a 301 redirect. On subsequent requests, even it the connection uses HTTP, HSTS forces the browser to use HTTPS for connecting to a particular website instead of HTTP. Even if a user types in a http:// URL, the browser will automatically correct the URL and will connect to https://.
It appears the more correct way to implement HSTS in Nginx is as so:
map $scheme $hsts_header {
https max-age=31536000;
}
server {
listen 80;
listen 443 ssl;
add_header Strict-Transport-Security $hsts_header;
}
http://trac.nginx.org/nginx/ticket/289
Most examples use the following to implement HSTS, which does not follow the RFC.
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
@toddlahman : Shouldn't we avoid to set the header for http (port 80) ?
An HSTS Host MUST NOT include the STS header field in HTTP responses conveyed over non-secure transport.
In nginx >= 1.7.5 you should have (note the added "always"):
add_header Strict-Transport-Security max-age=31536000 always;
This forces the header to always be added regardless of the http code which is what is wanted for this type of header.
I'm a bit curious, you seem to use ssl_trusted_certificate with the same wildcard-certificate that you use with ssl_certificate but Nginx documentation[1] specifies that ssl_trusted_certificate
Specifies a file with trusted CA certificates in the PEM format used to verify client certificates and OCSP responses if ssl_stapling is enabled.
The file should be a certificate bundle containing root and intermediate CAs.
[1] http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_trusted_certificate
Use following ciphers to exclude RC4.
ssl_ciphers "EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA256:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EDH+aRSA+AESGCM:EDH+aRSA+SHA256:EDH+aRSA:EECDH:!aNULL:!eNULL:!MEDIUM:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED";
i am getting access denied error
From my fork, you may want to include it as well:
# enabling Public Key Pinning Extension for HTTP (HPKP)
# https://developer.mozilla.org/en-US/docs/Web/Security/Public_Key_Pinning
# to generate use on of these:
# $ openssl rsa -in my-website.key -outform der -pubout | openssl dgst -sha256 -binary | base64
# $ openssl req -in my-website.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64
# $ openssl x509 -in my-website.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | base64
add_header Public-Key-Pins 'pin-sha256="base64+info1="; max-age=31536000; includeSubDomains';
@chrisnew thanks for the RC4-less ciphers.
hello!
more one question about this
when try access https://myip not redirect to my https://mysite.com
how to redirect my ip to domian name?
works http my ip to dimain but https not
thanks
If you add a single 'add_header' inside the server directive (in your case, for HSTS), it will override all the 'add_header's that you've defined outside.
EDH+aRSA is now considered weak http://imgur.com/C5fKr38
I updated my ciphers string to:
EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH RSA+AESGCM RSA+AES !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS
maybe you could add keepalive_timeout 70;
(http://nginx.org/en/docs/http/configuring_https_servers.html)
@bryfry - They're considered weak in your case because you're still using a common Diffie-Hellman group with your ciphers, not because the cipher itself is weak. You don't need to disable EDH+aRSA ciphers, you just need to generate a new unique DH group, and configure it with your web server:
https://weakdh.org/sysadmin.html
The Strict-Transport-Security header needs to be moved inside the http block with the ssl listen statement or you risk sending Strict-Transport-Security headers over HTTP sites you may also have configured on the server.
Additionally, the rewrite for the http server block should be a return 301 instead. See this Nginx documentation for more details: http://wiki.nginx.org/Pitfalls#Taxing_Rewrites