Skip to content

Instantly share code, notes, and snippets.

@Timi7007
Last active December 20, 2022 15:09
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save Timi7007/2b6cf34ea88220794c17b35b31607178 to your computer and use it in GitHub Desktop.
Save Timi7007/2b6cf34ea88220794c17b35b31607178 to your computer and use it in GitHub Desktop.
Collection on all things HTTPS. Includes settings for TLS on nginx (which desperately need an update!).

Why HTTPS?

Collection on all things HTTPS. Includes settings for TLS on nginx (which desperately need an update!).


Until I update this, I'd recommend you take a look at https://github.com/jukbot/setup-nginx-webserver

My current settings for TLS on nginx/1.10.3 on Ubuntu Server 16.04 LTS

See https://www.nginx.com/resources/wiki/start/topics/tutorials/install/#official-debian-ubuntu-packages on how to install the lastest version of nginx.

Most settings are sourced from https://bettercrypto.org/static/applied-crypto-hardening.pdf#subsection.2.1.3, https://danpalmer.me/blog/ssl-labs-grade-a, https://gist.github.com/plentz/6737338 and https://scotthelme.co.uk/

Background

I'm a newbie to large scale webhosting, but really interested in it. This is my take on a nginx config to deploy on my servers.

So if you find a way to do something better: Please leave a comment! Thanks!

Tests

Additional Links

You should definitely subscribe to the "Bulletproof TLS Newsletter"!

Also have a look at the alternative webserver Caddy.

Fix for Comodo certificates

I use Let's Encrypt cert's for my private stuff, but at work we use a Comodo wildcard certificate. As there is a reseller in between us, we only got a .pfx-file. This can be converted into two files (cert & key).

However this still breaks the certificate-chain, as the intermediate certificate is missing. The SSL Test reduces your grade to B because of this.

To fix this you can use ssl_certificate_key /etc/tls-cert/example-com.key; with the key you got by converting your .pfx into two files.

Paste the second file (public key as .crt-file) into https://certificatechain.io/ to get a .crt-file containing the full chain (your cert, intermediate cert and root cert). Put this in your config using ssl_certificate /etc/tls-cert/example-com.crt;.

This should fix the chain and give you an A grade on SSL Labs' SSL Test.

This may also work for other vendors!

You may use Chrome for https://certificatechain.io/ as my Firefox didn't work there.

## /etc/nginx/sites-enabled/example-com.conf
server {
listen 443 http2;
listen [::]:443 http2;
server_name example.com; # Replace all "example.com" in this config with your domain name. You can also set "server_name _;" to accept every request to server.
include /etc/nginx/tls.conf; # include your TLS-config
### Block for webhosting ###
location / {
root /var/www/example.com;
index index.html index.htm; # add index.php and enable php below if you need php
#autoindex on; # Turn this on to list directory contents like on apache
autoindex_exact_size off; # Make autoindex fancy
autoindex_localtime on; # and even more fancy
}
### Block for Reverse Proxy ###
location / {
proxy_pass http://172.16.0.5/;
#proxy_set_header Host $host; # Tell the software running on the server behind the proxy on which DNS-Name it should listen. This isn't required, but sometimes it can fix missing js, css, images or broken links.
#proxy_set_header X-Forwarded-Proto https; # Tell an apache2 server behind the proxy that the proxy is https. This isn't required, but sometimes it can fix missing js, css, images or broken links. You need to put "SetEnvIfNoCase X-Forwarded-Proto https HTTPS=on" in apache2.conf on the apache-server behind the proxy. See https://forum.joomla.org/viewtopic.php?t=845318#p3313092
}
### Block for internal hosting ###
location / {
root /var/www/example.com;
index index.html index.htm;
allow 5.189.139.136; # Put your company IP here to just allow this from your offices
deny all; # Deny everything else
}
### Block for redirect ###
location / {
return 301 https://example.org;
}
### Block for "Access denied" message ###
location / {
return 403;
}
### DEFAULT STUFF FROM HERE ###
#charset koi8-r; # modify and enable if you need
#access_log /var/log/nginx/access.log main; # Modify if you want, also avalible in /etc/nginx/nginx.conf
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html; # just don't
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
### DEFAULT STUFF TILL HERE ###
}
## /etc/nginx/nginx.conf
user nginx;
worker_processes 1; # use your number of cores
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024; # connection limit
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main; # Comment this out to disable access-logs. Also check out the tool "goaccess"
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip off; # Turn this off/comment it out and see https://github.com/h5bp/server-configs-nginx/issues/72 on why
server_tokens off; # don't send the nginx version number in error pages and Server header
# redir every http-request to https
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri; # "Please be sure to not use the $host variable here because it contains data controlled by the user." - bettercrypto.org
}
include /etc/nginx/sites-enabled/*.conf;
}
# /etc/nginx/tls.conf
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # 4096 Bit cert form letsencypt
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_stapling on; # Enable OCSP stapling
ssl_stapling_verify on;
ssl_session_cache shared:SSL:50m; # enable session resumption to improve https performance http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html
ssl_session_timeout 5m;
ssl_session_tickets off; # https://github.com/mozilla/server-side-tls/issues/135
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # You can remove TLSv1 but at cost of Android <4.4, the Baidu crawler, IE <11, OpenSSL <1.0 and Safari <7
ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA'; # allows most current browsers, most notable exceptions are IE on Windows XP and Java. You could also use Dan Palmer's 100% cipher strength recommendation, but at cost of most notably Android pre-4.4, Internet Explorer before version 11, and anything before Windows 7.
ssl_dhparam /etc/nginx/dhparams/dhparams.pem; # generated using "openssl dhparam -out /etc/nginx/dhparams/dhparams.pem 4096" however not sure if thats a good thing https://wiki.mozilla.org/Security/Server_Side_TLS#Pre-defined_DHE_groups
ssl_ecdh_curve secp384r1; # from NIST’s ECC curve recommendation
add_header Strict-Transport-Security max-age=15768000; # six months
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"; # use this only if all subdomains support HTTPS!
#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"; # One year with HSTS preload. See https://hstspreload.org/
add_header X-Frame-Options SAMEORIGIN; # or "add_header X-Frame-Options DENY;" allow iframes only frome same origin or deny it completely to avoid clickjacking
add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always; # not the best way to do it
add_header X-Xss-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin"; # Chrome doesn't like this yet https://productforums.google.com/forum/#!topic/chrome/UBp_FtxonXU
add_header X-Emoji "<U+1F47D>"; # Why does this exist?!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment