HSTS for SKS Keyservers

Every website should be using HTTPS by default, and ideally use HTTPS Strict Transport Security (HSTS). However, running a server in the SKS keyserver pool makes this tricky. Here's how I have my setup that works okay.

Config features

Downsides

If you visit my domain's normal https port 443 (https://sks.daylightpirates.org/), your browser will cache the HSTS property, so if you try to visit the HKP port (11371), you will be automatically try to load a TLS certificate, which can't being served, so you'll get a "Secure Connection Failed" error in your browser. However, if you haven't visited my domain normally (e.g. if you get linked to http://sks.daylightpirates.org:11371/ from the sks-keyservers.net website), you won't know that the domain is using HSTS, so the page will load fine.

In normal practice, this usually isn't a big deal because the people who come to my keyserver via sks-keyservers.net are likely not the same people who go to my keyserver from somewhere else on my domain (which would mean they have the HSTS cache).

Nginx config

server {
    listen 104.131.30.118:443;
    listen [2604:a880:800:10::688:e001]:443;
    server_name sks.daylightpirates.org;

    ssl on;
    ssl_certificate sks.daylightpirates.org.crt;
    ssl_certificate_key sks.daylightpirates.org.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_dhparam /etc/nginx/sks.daylightpirates.org.dhparam;
    ssl_session_cache shared:SSL:50m;
    ssl_prefer_server_ciphers on;

    access_log off;

    location / {
        proxy_pass http://127.0.0.1:11371/;
        proxy_pass_header Server;
        add_header Via "1.1 sks.daylightpirates.org:11371 (nginx)";
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        proxy_ignore_client_abort on;
        client_max_body_size 8m;
    }
}

server {
    listen 104.131.30.118:443;
    listen [2604:a880:800:10::688:e001]:443;
    server_name *.sks-keyservers.net;
    server_name *.pool.sks-keyservers.net;
    server_name keys.gnupg.net;

    ssl on;
    ssl_certificate pool.sks-keyservers.net.crt;
    ssl_certificate_key pool.sks-keyservers.net.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_session_cache shared:SSL:50m;
    ssl_prefer_server_ciphers on;

    access_log off;

    location / {
        proxy_pass http://127.0.0.1:11371/;
        proxy_pass_header Server;
        add_header Via "1.1 sks.daylightpirates.org:11371 (nginx)";
        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        proxy_ignore_client_abort on;
        client_max_body_size 8m;
    }
}

server {
    listen 104.131.30.118:11371;
    listen [2604:a880:800:10::688:e001]:11371;
    server_name sks.daylightpirates.org;
    server_name *.sks-keyservers.net;
    server_name *.pool.sks-keyservers.net;
    server_name keys.gnupg.net;

    access_log off;

    location / {
        proxy_pass http://127.0.0.1:11371/;
        proxy_pass_header Server;
        add_header Via "1.1 sks.daylightpirates.org:11371 (nginx)";
        proxy_ignore_client_abort on;
        client_max_body_size 8m;
    }
}

server {
    listen 104.131.30.118:80;
    listen [2604:a880:800:10::688:e001]:80;
    server_name sks.daylightpirates.org;
    server_name *.sks-keyservers.net;
    server_name *.pool.sks-keyservers.net;
    server_name keys.gnupg.net;

    access_log off;

    location /.well-known/acme-challenge/ {
        alias /home/acme/challenges/;
        try_files $uri =404;
    }

    location / {
        proxy_pass http://127.0.0.1:11371/;
        proxy_pass_header Server;
        add_header Via "1.1 sks.daylightpirates.org:11371 (nginx)";
        proxy_ignore_client_abort on;
        client_max_body_size 8m;
    }
}

Published 2016-05-25 on daylightpirates.org