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).
Update Changelog
04.11.2021 Distinguish DSM6 Application Portal and DSM7 Login Portal.
04.11.2021 Distinguish DSM6 and DSM7 commands, add commands to get current status or restart nginx.
DSM6: How the reverse proxy in the Application Portal works
All reverse proxy configurations from the Application Portal -> Tab "Reverse Proxy" end up beeing rendered in the file
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:
What we see is the declaration of a
If you add
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.
DSM7: How the reverse proxy in the Login Portal works
All reverse proxy configurations from the Login Portal -> Tab "Advanced" -> Reverse Proxy end up beeing rendered in the file
Once again: changes in the UI result in a immediatly fresh rendered file, all manual changes to that file will be lost...
For every reverse proxy entry in the Internet Portal, it renders such a block into the file:
What we see is the declaration of a
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
In DSM6.2:
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:
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
Make sure to read the docs of the application and lookout for their reverse proxy recommendations for nginx.
Words of advice
Enjoy!
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).
Update Changelog
04.11.2021 Distinguish DSM6 Application Portal and DSM7 Login Portal.
04.11.2021 Distinguish DSM6 and DSM7 commands, add commands to get current status or restart nginx.
DSM6: How the reverse proxy in the Application Portal works
All reverse proxy configurations from the Application Portal -> Tab "Reverse Proxy" 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; # can be configure in advanced tab
proxy_read_timeout 60; # can be configure in advanced tab
proxy_send_timeout 60; # can be configure in advanced tab
proxy_intercept_errors off; # can be configure in advanced tab
proxy_http_version 1.1; # can be configure in advanced tab
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;
}
}
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.
DSM7: How the reverse proxy in the Login Portal works
All reverse proxy configurations from the Login Portal -> Tab "Advanced" -> Reverse Proxy end up beeing rendered in the file
/etc/nginx/sites-enabled/server.ReverseProxy.conf
.Once again: changes in the UI result in a immediatly fresh rendered file, all manual changes to that file will be lost...
For every reverse proxy entry in the Internet 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
# note: it seems the is no way to configure a ssl http2 listener in DSM7 anymore
server_name ${source hostname};
if ( $host !~ "(^${source hostname}$)" ) { return 404; }
include /usr/syno/etc/www/certificate/ReverseProxy_*/cert.conf*; # if ${source protocol} is https
include /usr/syno/etc/security-profile/tls-profile/config/ReverseProxy_.conf*; # if ${source protocol} is https
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload" always; # if ${source port hsts} is enabled
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
include conf.d/${name of acl config}.conf*; # if ${source access control profile} is selected
location / {
proxy_connect_timeout 60; # can be configure in advanced tab
proxy_read_timeout 60; # can be configure in advanced tab
proxy_send_timeout 60; # can be configure in advanced tab
proxy_intercept_errors off; # can be configured in advanced tab
proxy_http_version 1.1; # can be configure in advanced tab
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 /dsm_error_page;
location /dsm_error_page {
internal;
root /usr/syno/share/nginx;
rewrite (.*) /error.html break;
allow all;
}
}
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.run
.- The
listen
directive will look different depending whether the https protocol and http2 are configured. - The
include
directives will only be used if the https protocoll is selected, the included conf files will be responsible to actualy include certificate related directives - The
Strict-Transport-Security
header is only used if hsts is enabled for the source port. - The
allow
directive is only used if an access control is selected (can be used to allow/deny source ip's or cidr).
websocket
in the tab "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 include
s, which can be leveraged to hook custom reverse proxy configurations in.In DSM6.2:
/etc/nginx/conf.d/main.conf
: can be used to configure high level blocks likehttp
(=layer7 http/https based reverse proxy),stream
(=layer4 TCP/UDP Port based reverse proxy) ormail
. Just edit the existing file./etc/nginx/conf.d/http.*.conf
: can be used to configure one or moreserver
block(s) (which are implicitly included in ahttp
block) to create configurations, which allow custom location and directives! Create a new file matching the naming convention./etc/nginx/sites-enabled/*
: same as 2, though instead of a naming convention, every filename is valid.
/etc/nginx/conf.d/main.*.conf
: can be used to configure high level blocks likehttp
(=layer7 http/https based reverse proxy),stream
(=layer4 TCP/UDP Port based reverse proxy) ormail
. Create a new file matching the naming convention./etc/nginx/conf.d/http.*.conf
: can be used to configure one or moreserver
block(s) (which are implicitly included in ahttp
block) to create configurations, which allow custom location and directives! Create a new file matching the naming convention./etc/nginx/sites-enabled/*
: same as 2, though instead of a naming convention, every filename is valid.
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:
- DSM6:
sudo nginx -t
- DSM7:
sudo nginx -t -c /etc/nginx/nginx.conf.run
- DSM6:
sudo nginx -s reload
- DSM7:
sudo nginx -s reload -c /etc/nginx/nginx.conf.run
- DSM6:
sudo synoservice -restart nginx
- DSM7:
sudo systemctl restart nginx
- DSM6:
sudo synoservice -status nginx
- DSM7:
sudo systemctl status nginx
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
andssl_ciphers
based on the scan result of ssllabs.com
- You will want to at least lock down the allowed
Enjoy!
- Related resources
Tutorial - Synology Reverse Proxy
This tutorial will cover a few short steps that you need to know and setup in order to make your apps and services accessible via the internet (or LAN) using a specific domain name and custom (or default) port. It will also help you to avoid...www.synoforum.com