Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Questions about HTTP Access/Mods may go here
Forum rules
Please note the disclaimer before modifying your Synology Product.
2mny
Trainee
Trainee
Posts: 11
Joined: Wed Nov 21, 2012 3:47 am

Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby 2mny » Sun Mar 06, 2016 8:41 am

Edit: Updated guide with a more permanent http redirect method.
Edit: With the release of DSM 6, the entire process changes and most steps can now be performed directly from DSM.

This is a guide for setting up web services that are hosted on various port numbers to be accessible through a sub-domain (*.example.com) and then protecting those services with SSL encryption using a free let's encrypt certificate. To set this up you will need:
  • your own domain
  • a virtual machine running your favorite linux distro that can mount the web root of your diskstation
  • web station enabled on your diskstation
If you already have a single domain letsencrypt cert, letsencrypt will allow you to replace it with an expanded cert covering up to 100 sub-domains.

Why would you want to do this?
  • provide free ssl protection for all web services, even those that do not natively support it
  • simplify ssl protection for apps that support ssl but have complicated setup steps
  • no more security exceptions in your web browsers for self-signed certs
  • simplify router/firewall port forwarding (only open ports needed are 80 and 443)
  • domain names are easier to remember that port numbers
This configuration does not encrypt traffic between your diskstation on your local network. If you need to encrypt local area network traffic, block direct requests to your diskstation's web services or find an alternative solution.

DSM 6
It looks like DSM 6 switches the internal webserver from Apache to nginx. With these changes, the reverse proxy scripts that worked in DSM 5 no longer function. Luckily, Synology has added reverse proxy features directly into the DSM web interface.

First you will want to set up a HTTP -> HTTPS redirect in the moustache template for the nginx config. Without the redirect in place, visitors to your sites using http:// will receive a HTTP 403 error from the nginx server and links within services may not function. You may need to reapply the changes to the moustache file after installing DSM updates as new updates may overwrite the edited file:
  1. SSH into your synology with an admin account.
  2. switch to the root account with

    Code: Select all

    sudo su -
    Alternatively, prepend 'sudo' to all of the following terminal commands
  3. open /usr/syno/share/nginx/WWWService.mustache in a text editor like vi. To be safe, backup your config before making any changes

    Code: Select all

    cp /usr/syno/share/nginx/WWWService.mustache /usr/syno/share/nginx/WWWService.mustache.bak
  4. locate the first lines of the file that look like this:

    Code: Select all

    server {
        listen 80 default_server{{#reuseport}} reuseport{{/reuseport}};
        listen [::]:80 default_server{{#reuseport}} reuseport{{/reuseport}};
        listen 443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};
        listen [::]:443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};

        server_name _;

        {{> /usr/syno/share/nginx/X-Accel}}

    change it to look like this

    Code: Select all

    server {
        listen 80 default_server{{#reuseport}} reuseport{{/reuseport}};
        listen [::]:80 default_server{{#reuseport}} reuseport{{/reuseport}};

        server_name _;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};
        listen [::]:443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};

        server_name _;

        {{> /usr/syno/share/nginx/X-Accel}}
  5. The next time the nginx config file is changed through the DSM web interface, the http > https redirect added to the template will be applied to the config
  6. You may also manually add the 301 redirect to the nginx config file at /etc/nginx/nginx.conf, then reload nginx to apply the changes

    Code: Select all

    nginx -s reload

Now add a reverse proxy for each service from the DSM web interface at "Control Panel > Application Portal > Reverse Proxy".

As I upgraded from DSM 5 and kept my existing Let's Encrypt certs, I have not had a chance to try out the new integrated Let's Encrypt functionality in DSM 6. This post will be updated with instructions once I have had a chance to use it.

DSM 5.X
Get a certificate
DSM 5.x does not support running letsencrypt locally and DSM 6 has reportedly had issues with requests for sub-domains(Certificate Subject Alt Name). To get around these issues, we can run the letsencrypt certificate request code inside an external linux vm.

dip987's post is a great guide to get started with a single domain letsencrypt cert. When requesting multiple sub-domains, manually handling acme challenges for every domain becomes a pain. Letting letsencrypt handle creating the challenge files by using the webroot option simplifies the request.

I ran into problems requesting certs with the Apache reverse proxies for my sub-domains active, I recommend disabling these while making the cert request. Web station should route web requests for nonexistent sub-domains back to your main domain without any additional configuration (http://does-not-exist.example.com/.well-known > http://example.com/.well-known).

  1. Disable any existing url forwarding rules set up to map sub-domains to your synology web services.
  2. Spin up a linux vm
  3. Mount the web root of your diskstation to the local vm. There are multiple ways of doing this that vary greatly so I won't get into details here. Just make sure that the mount path is writable by the root user of your vm as letsencrypt runs as root. For this guide we will say the web root path is mounted on the vm at '/mnt/example/web'.
  4. Test the acme url. On the vm:

    Code: Select all

    mkdir -p /mnt/example/web/.well-known/acme-challenge
    sudo echo "test" > /mnt/example/web/.well-known/acme-challenge/test
    now make sure you can bring up http://example.com/.well-known/acme-challenge/test in a web browser.
  5. Download the latest letsencrypt request code on the vm:

    Code: Select all

    git clone https://github.com/letsencrypt/letsencrypt
    cd letsencrypt
  6. Make the certificate request:

    Code: Select all

    letsencrypt certonly --webroot-path /mnt/example/web/ -d example.com -d mail.example.com -d files.example.com -d dsm.example.com
    here we are requesting a single cert that validates the example.com domain and the mail, files and dsm sub-domains. Add as many sub-domains as needed.
  7. If all goes well the request will be successful and letsencrypt will have issued you a single certificate that is valid for your primary domain and the sub-domains you requested. You can find the new cert components at /etc/letsencrypt/archive/example.com on your vm. Import privkey#.pem, cert#.pem and chain#.pem to your Synology (control panel > Security > Certificate > "Import certificate"). The #'s in these files will increment by one every time you make a successful request.

Redirect synology package web services to sub-domain urls
We'll be using the built-in apache web server to redirect sub-domains to our web services using reverse proxies. Primal Cortex has already provided a great guide to setting this up. Scroll down to the bottom of the guide to the section detailing setting up the script provided by Michi.
  1. Open Michi's script in a text editor
  2. Add the missing # to the first line of the script so it reads

    Code: Select all

    #!/bin/sh
  3. Change the url variable on the 4th line of the script to match your site domain name
  4. Edit the section near the bottom of the script to match the sub-domain names to the port numbers your web services run on:

    Code: Select all

    #Usage: subdomain redirected port. So for example audio 8800 will redirect audio.mydomain.com to the internal 8800 port.
    redirectSubdomainTo audio 8800
    redirectSubdomainTo dsm 5000
    redirectSubdomainTo file 7000
    redirectSubdomainTo note 9350
    redirectSubdomainTo video 9007
  5. (optional) Redirect future acme sub-domain cert requests back to your primary domain by adding a redirect rule to the following section:

    Code: Select all

    <VirtualHost *:80>
      ServerName $1.$URL
      <Location />
        RedirectPermanent / https://$1.$URL/
      </Location>
    </VirtualHost>
    Now becomes:

    Code: Select all

    <VirtualHost *:80>
      ServerName $1.$URL
      <Location />
        RedirectPermanent /.well-known/ http://${URL}/.well-known/
        RedirectPermanent / https://$1.$URL/
      </Location>
    </VirtualHost>
    Without this rule you will need to temporarily disable redirects when requesting a new cert. Note that even with the rule in place you may still encounter issues with certificate requests.
  6. Save the script to /usr/local/etc/rc.d/S99subdomains.sh on your diskstation so it will run on startup.
  7. Make the script executable with

    Code: Select all

    chmod +x /usr/local/etc/rc.d/S99subdomains.sh
  8. Start the script with

    Code: Select all

    /usr/local/etc/rc.d/S99subdomains.sh start

Everything should now be in place. Open a sub-domain url in a web browser and you should see a lock icon in the browser url bar indicating the site is protected by a verified ssl certificate. Requests using http:// should automatically be redirected to https://.
Last edited by 2mny on Thu Jun 30, 2016 2:33 am, edited 3 times in total.
User avatar
ilkevinli
Sharp
Sharp
Posts: 165
Joined: Thu Apr 19, 2012 2:05 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby ilkevinli » Mon Mar 07, 2016 1:52 pm

Thanks for the guide. It would be a lot better if this could all be done from the NAS itself without using a VM.
scyto
Rookie
Rookie
Posts: 31
Joined: Sun Jul 19, 2015 11:10 am

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby scyto » Sat Apr 02, 2016 10:39 pm

ilkevinli wrote:Thanks for the guide. It would be a lot better if this could all be done from the NAS itself without using a VM.

Given that DSM 6 allows you to request the certs and export the files in the UI there should be no reason to spin up a VM or mess about installing lets encrypt. Getting certs via the UI has worked perfectly for me.
jce221
I'm New!
I'm New!
Posts: 3
Joined: Fri Mar 25, 2016 12:04 am

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby jce221 » Tue Apr 05, 2016 3:23 am

scyto

You were able to complete the entire process using the UI on DSM 6 and it worked successfully? I just received my DS and will be trying this out over the next couple of days. Thanks for the posts everyone!
CarrollLewis
I'm New!
I'm New!
Posts: 3
Joined: Thu Jun 23, 2016 8:25 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby CarrollLewis » Thu Jun 23, 2016 10:25 pm

@2mny, although I am using DSM 6.0.1-7393 Update 1, I could not get your instructions for DSM 6 to work.

I finally had success with [https://primalcortex.wordpress.com/2016/04/25/synology-reverse-proxy-with-dsm-6-0/#comment-2425][a hint from trent on primalcortex], but would have loved to get it all done your way.
CarrollLewis
I'm New!
I'm New!
Posts: 3
Joined: Thu Jun 23, 2016 8:25 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby CarrollLewis » Thu Jun 23, 2016 10:46 pm

Ugh, I'm still learning the synology forum UI and accidentally posted too soon. Let me try again.

@2mny, I'm using DSM 6.0.1-7393 Update 1, but couldn't get your instructions for DSM 6 to work for a virtual host domain. I want

Code: Select all

http://my.example.com
to 301 to

Code: Select all

https://my.example.com
, using the standard ports 80 and 443.

I finally had success with a hint from Trent on primalcortex, but would have preferred to do things your way.

First, I edited WWWService.mustache as you suggested, then created a test virtual host in the DSM Web Station. It created the virtual host, but did not update

Code: Select all

/etc/nginx/nginx.conf
with the new block.

Then I edited

Code: Select all

/etc/nginx/nginx.conf
directly, per your instructions, and restarted nginx with

Code: Select all

nginx -t && nginx -s reload
, also per your instructions. The

Code: Select all

-t
verified that my syntax was correct.

The last instruction you give is to create a reverse proxy, and here I had total failure. I have no experience with reverse proxies, so I don't know what it was supposed to look like. I navigated to the Application Portal in the Control Panel, Reverse Proxy tab, and hit Create. I tried Source: {Protocol: HTTP, Hostname: my.example.com, Port: 80} and Destination: {Protocol: HTTPS, Hostname: <my router IP>, Port: 443}, but it complained that my.example.com was already created, so it was invalid.

So I kept trying all sorts of things, e.g. source hostname *, destination hostname localhost, etc, etc, with various errors, including complaints that ports 80 and 443 are already in use, and not valid.

Any idea how to apply your instructions to a web station virtual host?
seopr9utpo
I'm New!
I'm New!
Posts: 7
Joined: Mon May 30, 2016 11:53 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby seopr9utpo » Fri Jun 24, 2016 5:36 pm

I'm trying to figure out where the actual LE certs are stored so that I can update them via command line.

Any ideas? Thanks.
2mny
Trainee
Trainee
Posts: 11
Joined: Wed Nov 21, 2012 3:47 am

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby 2mny » Thu Jun 30, 2016 2:27 am

seopr9utpo wrote:I'm trying to figure out where the actual LE certs are stored so that I can update them via command line.

Any ideas? Thanks.


SSl cert paths can be found in the /etc/nginx/nginx.conf file.

Code: Select all

    ssl_certificate           /usr/syno/etc/certificate/system/default/fullchain.pem;
    ssl_certificate_key       /usr/syno/etc/certificate/system/default/privkey.pem;
    ssl_protocols             TLSv1.2;
    ssl_ciphers               ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256;
    ssl_dhparam               /usr/syno/etc/ssl/dh2048.pem;
    ssl_prefer_server_ciphers on;
cravaus
Novice
Novice
Posts: 58
Joined: Wed Jul 02, 2014 6:12 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby cravaus » Fri Aug 26, 2016 5:25 pm

This is very helpful. I wish there was a way to avoid having this change wiped out on updates. I have noticed that at least in the last update, the following did not work to load the new code:

nginx -s reload

I used this instead:

synoservicecfg --restart nginx
Froberg
I'm New!
I'm New!
Posts: 1
Joined: Wed Aug 23, 2017 10:58 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby Froberg » Wed Aug 23, 2017 11:02 pm

I was unable to get your method to work. I'm mostly interested in making sure my public-facing sites, a wordpress and owncloud installation, are forced to https. As far as I can discern, nginx actively ignores .htaccess files, so I had hoped your solution would be "the one".
As for editing the mustache file, I worry it gets over-written by Syno habitually?

At any rate, I had zero luck using your suggestion, here's my current config - unaltered - maybe you can see what's up! :)

Code: Select all

server {
    listen 80 default_server{{#reuseport}} reuseport{{/reuseport}};
    listen [::]:80 default_server{{#reuseport}} reuseport{{/reuseport}};

    gzip on;

    {{> /usr/syno/share/nginx/WWW_Main}}

    location ~ ^/$ {
        rewrite / http://$host:{{DSM.port}}/ redirect;
    }
}

server {
    listen 443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};
    listen [::]:443 default_server ssl{{#reuseport}} reuseport{{/reuseport}};

    {{#DSM.https.compression}}
    gzip on;
    {{/DSM.https.compression}}

    {{> /usr/syno/share/nginx/WWW_Main}}

    location ~ ^/$ {
        rewrite / https://$host:{{DSM.ssl.port}}/ redirect;
    }
}


Thanks! :) And yes, let's indeed SSL ALL THE THINGS! :P
hshah
Apprentice
Apprentice
Posts: 81
Joined: Thu Aug 22, 2013 7:26 pm

Re: Guide: SSL all the things! Proxying web services through sub-domains with letsencrypt SSL encryption

Postby hshah » Sun Oct 01, 2017 6:46 pm

The changes to WWWService.mustache do no seem to be applying either :(

Return to “HTTP/Apache Mods”

Who is online

Users browsing this forum: No registered users and 1 guest