Resource icon

Tutorial Synology Reverse Proxy under the hood

Introduction
Rusty made a fabulous beginner friendly tutorial on how to configure reverse proxy configurations using the UI: Tutorial - Synology Reverse Proxy.

This tutorial is aimed for advanced users: if you feel uncomfortable with working in the shell (or if you don't know what it means) this tutorial is probably not suited for you.

It covers the limitations of the reverse proxy configurations created in the UI and how to bypass them.
Though, it is not going to illustrate how to actualy write nginx configurations (which is used under the hood).

How the reverse proxy in the Application Portal works

All reverse proxy configurations from the Application Portal end up beeing rendered in the file /etc/nginx/app.d/server.ReverseProxy.conf.
Since changes in the UI result in a immediatly fresh rendered file, all manual changes to that file will be lost... so better not touch it ;)

For every reverse proxy entry in the Application Portal, it renders such a block into the file:
NGINX:
server {
    listen ${source port};                # if ${source protocol} is http
    listen [::]:${source port};           # if ${source protocol} is http
    listen ${source port} ssl;            # or if ${source protocol} is https
    listen [::]:${source port} ssl;       # or if ${source protocol} is https
    listen ${source port} ssl http2;      # or if ${source protocol} is https and ${source port http2} is enabled
    listen [::]:${source port} ssl http2; # or if ${source protocol} is https and ${source port http2} is enabled

    server_name ${source hostname};

    ssl_certificate ${path to fullchain.pem for the assigned certificate in the cert manager};   # if ${source protocol} is https
    ssl_certificate_key ${path to privkey.pem for the assigned certificate in the cert manager}; # if ${source protocol} is https
    add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload" always;  # if ${source port hsts} is enabled

    allow ${source port access control}   # if ${source port access control} is enabled and a profile is selected

    location / {
        proxy_connect_timeout 60;
        proxy_read_timeout 60;
        proxy_send_timeout 60;
        proxy_intercept_errors off;
        proxy_http_version 1.1;
        proxy_set_header        Host               $http_host;
        proxy_set_header        X-Real-IP          $remote_addr;
        proxy_set_header        X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto  $scheme;
        proxy_pass ${destination protocol}://${destination host}:${destination port};
    }

    error_page 403 404 500 502 503 504 @error_page;

    location @error_page {
        root /usr/syno/share/nginx;
        rewrite (.*) /error.html break;
        allow all;
    }
}
Note: the code block from above is rendered by the Application Portal in DSM6.2. DSM7 might render different directives inside the server block.

What we see is the declaration of a server block, which is included in a http block (regardless whether http or https are configured) in the /etc/nginx/nginx.conf .

  • The listen directive will look different depending whether the https protocol and http2 are configured.
  • The ssl_certificate* directives are only used if the https protocoll is selected.
  • The Strict-Transport-Security header is only used if hsts is enabled for the source port.
  • The allow directive is only used if access control is enabled for the source port (can be used to allow/deny source ip's or cidr).

If you add websocket in the custom headers, following lines will be added to the location block:
NGINX:
proxy_set_header        Upgrade           $http_upgrade;
proxy_set_header        Connection        $connection_upgrade;

Hint: it is possible to add further custom headers using the UI, though be aware that only alpahnumeric character and the - character are allowed for the name.

If the reverse proxied application just requires additional headers, they can be set directly in the UI. Though, in many cases adding headers is still insufficient.

And now the parts that are missing
- location other than /
- directives (~=nginx configuration items)

Why are those missing parts important? Well, some applications do require either a special location and/or directives beeing set in order to work behind a reverse proxy.

How to workaround the limitation
The main nginx configuration file /etc/nginx/nginx.conf by default provides three includes, which can be leveraged to hook custom reverse proxy configurations in.

In DSM6.2:
  1. /etc/nginx/conf.d/main.conf: can be used to configure high level blocks like http (=layer7 http/https based reverse proxy), stream (=layer4 TCP/UDP Port based reverse proxy) or mail. Just edit the existing file.
  2. /etc/nginx/conf.d/http.*.conf: can be used to configure one or more server block(s) (which are implicitly included in a http block) to create configurations, which allow custom location and directives! Create a new file matching the naming convention.
  3. /etc/nginx/sites-enabled/*: same as 2, though instead of a naming convention, every filename is valid.
In DSM7:
  1. /etc/nginx/conf.d/main.*.conf: can be used to configure high level blocks like http (=layer7 http/https based reverse proxy), stream (=layer4 TCP/UDP Port based reverse proxy) or mail. Create a new file matching the naming convention.
  2. /etc/nginx/conf.d/http.*.conf: can be used to configure one or more server block(s) (which are implicitly included in a http block) to create configurations, which allow custom location and directives! Create a new file matching the naming convention.
  3. /etc/nginx/sites-enabled/*: same as 2, though instead of a naming convention, every filename is valid.
These files are not managed by the Application Portal's reverse proxy configuration, and as such not overwritten/replaced by generated configurations. This also means those configuration won't be listed there! So don't be surprised if you don't see them in the UI :)

After adding/modifying a conf file, it is recommended to test whether the configuration is valid. If you'd load an invalid configuration, the whole nginx will stop working, until the invalid configuration is fixed and reloaded. This will not only affect the reverse proxy part, but also the dsm ui and whatever else depends on the nginx!

Test configuration for validity: sudo nginx -t
Reload configuration: sudo nginx -s reload

If you find an application that does not work well with the Application Portal`s reverse proxy configuration from the UI, you typicaly want to add a new file in /etc/nginx/conf.d/http.${myapp}.conf and configure a server block.

Make sure to read the docs of the application and lookout for their reverse proxy recommendations for nginx.

Words of advice
  • Make sure you always test your configuration before you reload it!
  • Make sure to never reboot the NAS with an invalid configuration! Nginx does NOT(!) start with an invalid configuration, the same holds true for the DSM ui on port 5000!
  • When you stop working on a configuration and it is still invalid, make sure to rename it to NOT match the naming convention. If invalid configs exist in /etc/nginx/sites-enabled/*, make sure to move them out of the folder instead.
  • For https, make sure to check how hardend your configuraiton is: SSL Server Test (Powered by Qualys SSL Labs)
    • You will want to at least lock down the allowed ssl_protocols and ssl_ciphers based on the scan result of ssllabs.com

Enjoy!
Related resources



Similar resources
Resource starter Title Category
Rusty Tutorial Synology Reverse Proxy Tutorials
fredbert Tutorial Adding a User to the Administrators Group on a Synology Router Tutorials
wwwampy Tutorial Back up your Mac with Time Machine to Synology NAS Tutorials
jeyare App How to monitor, control, damage check of disks in your Synology NAS Apps and Packages
Geeked Tutorial How to setup and run Reactive Resume in Docker on Synology Tutorials
jeyare Ubiquiti Migrating existing Ubiquiti UniFi Controller to Docker in Synology NAS Tutorials
Robbie Tutorial Native macOS Finder integration with Synology Universal Search Tutorials
WST16 Network ports used by Synology services Tutorials
SynoMan Docker NextCloud on Synology NAS using Docker compose (with Portainer) Tutorials
wizard99 Tutorial Performing the Synology Memory Test and Extracting the "HIDDEN" Memtest Results via a New Method Tutorials
Rusty Tutorial PXE boot via Synology NAS Tutorials
Rusty Tutorial Synology - Pushover notification integration Tutorials
skavans App Synology DS Manager – Download Station macOS app and Safari Extension [2020 NEW] Apps and Packages
fredbert Security Synology Product Security Advisory Tutorials
Rusty TeamViewer for Synology NAS Other
marco App Weemple Video Station Validator - App to validate the metadata of Synology Video Station Apps and Packages
NAS Newbie Tutorial NAS Remote Access for Newbies: Part 2 - Port 443 & Reverse Proxy Tutorials
NAS Newbie Tutorial NAS Remote Access for Newbies: Part 3 - Accessing Mobile Apps via Reverse Proxy Tutorials
NAS Newbie Tutorial NAS Remote Access for Newbies: Part 4 - Reverse Proxy for Multiple NAS on a Single LAN Tutorials
jphermans Docker Install nginx-proxy-manager Tutorials
Top