• To complete the “project” after finally managing to get the Reverse Proxy to operate flawlessly
• To include Secure Socket Layer communication (also known as HTTPS) using both self-signed as well as Lets Encrypt certificates.
This is my recipe:
1. Why do I need (want) to have a Reverse Proxy in the first place - and what is it actually?
In my local home network (LAN) I have three QNAP NAS servers running various software apps serving my needs.
One of these software apps is Madsonic (a nice music media- and player app). I’ll use this in my example below.
My ultimate goal is to be able to access Madsonic wherever I am in the world, in an easy, secure and effective way.
That in itself can be easily accomplished by just opening the right port in my firewall in the LAN gateway/router on my home network. Madsonic uses port 4040 by default.
But there are several good reasons why one would not choose to do that:
a) Every single app that I need (wish) to expose to internet visitors (myself included), has to have its own firewall opening and port forwarding.
b) Authentication and access control takes place after the visitor is inside my LAN without any security.
c) Visitor would have to remember the port number for each app they wish to use.
d) Traffic encryption (SSL) is a security measure that has to be added to each app (web service) individually.
- Just to mention a few valid points
By using a reverse proxy, most of these issues can be consolidated to a single point of entry and handled without allowing any visitor to ever enter my LAN beyond the ReverseProxy server.
Sounds great, eh?
Well, that isn’t all true. It depends where you choose to locate the reverse proxy (RProxy) itself. The best solution is to locate it in a separate DMZ, or at least in a separate subnet. But for simplicity and manageability, I have chosen to implement my RProxy using the default QNAP Apache Web server which comes bundled with every QNAP server. In my case, this implies that the RProxy itself is inside my LAN, but all the principles are still valid, and many of the benefits are still achieved - if not with maximum security. You may of course just use this guide as a steppingstone to further enhance your network security step by step as you move forward. Taking one step at a time, is a good strategy.
So, to summarize: I want a solution where all my visitor traffic is routed through a single port in my firewall, and that they never need to know where my internal servers are located, nor the IP address of these servers and the ports they use, their real names, or any other essentials. In fact, by using a RProxy, a visitor will never see anything inside the LAN itself. That’s the main purpose of a Reverse Proxy.
Secondly, I also want to force all visitors to use Secure Socket Layer (SSL) protocol. This – also known as HTTPS – provides end-to-end encryption of all browser-based traffic. This prevents anyone from injecting themselves as a “man-in-the-middle” and read all traffic data in clear text. However, to make it user friendly (visitor friendly), I want to allow visitors to initiate their visit using the default HTTP protocol, and instead have the ReverseProxy server redirect the traffic and change the communication to HTTPS without any user inventions.
This implies that initial traffic will be allowed to go through port 80 which is the default HTTP port, and when it hits the ReverseProxy, it is redirected to port 443 which is the default HTTPS port.
Keep in mind that whenever you type a regular web address (URL) in your browser, it automatically goes through port 80. You don’t even have to add the HTTP or the port number. But if you add HTTPS in front of your web address, it will automatically go to port 443. You can of course override the port numbers, but that only complicates matters.
Last, but not least, I want to add support for WebSocket protocol to be allowed to pass through the ProxyServer. Why? Because I have a server program that relies on WebSocket in order to support realtime data such as video and audio to pass effectively through. HTTP wasn’t designed to do that. WebSocket is much better.
2. First things first: How can you visit your home LAN from a hotel room in Bangkok?
Easy peasy, you just type in the IP address of you WAN router in the address field of your favorite browser. This IP address is assigned by your Internet Service Provider (ISP) when you sign up for an internet connection at home. Everyone has a unique IP address assigned to their internet connection. You can find this IP address by visiting https://whatismyipaddress.com from any PC connected to your LAN or WLAN. Be aware that your ISP typically assign such addresses on a lease basis, from a pool. That means that next week you may have a different address. How long you get to keep your current IP address depends on the strategy of your ISP. A way to permanently solve that problem is to use a so-called dynamic DNS name (Dyn-DNS). That way you can locate your home network using an easy to remember name like: http://www.stevens_home_lan.com (or something similar) instead of IP-numbers that can change all the time. I’m just mentioning this so that you are aware of the problem, but it is beyond the scope of this guide to explain how to set up your own dynamic DNS name. At least for now.
It is also possible to use clear text web address without resorting to DynDNS. If you buy a domain name from a domain provider. Most of them has a web-based domain manager where you can configure domain name forwards or make DNS name assignment. This is somewhat easier that using DynDNS, and this is what I myself use. But the only purpose of this is to make it easier for your visitors to remember your address. Obviously, visiting app.stevens.com is much easier that having to remember 244.134.86.188. But you still have to remember to modify your DNS assignments every time your ISP changes your IP address. My own experience is that I have had the same IP address for several years now, using a fiber connection. But a dial up connection or ISDN connection would most likely have a different IP address for each session. I am now talking about your home LAN connection and not your visitor connection.
3. The Front Gate: Now that you have found your own WAN IP, what happens when you type this IP in to the address bar of your browser from a hotel room in Bangkok?
Your browser automatically knocks on port 80 on your WAN routers internal firewall. Port 80 is always default. Whether or not that will successfully take your visitor anywhere, depends on several things:
a) Does your ISP allow traffic to port 80?
b) Has port 80 been opened in your WAN routers firewall?
c) Where is your firewall sending this traffic inside your LAN (port forwarding)?
For a) you have to check this yourself by contacting your ISP, or you can just assume that it will work, and go ahead. Many people have wasted hours of work scratching their head just to finally realize that the ISP was the problem.
For b) that is something you have to do yourself. How to do that is different from router to router and firewall to firewall. There is no common denominator on how this is implemented. You just have to consult your user documentation that came with your router.
For c) you need to open port 80 for incoming traffic and forward this traffic to a specific server on your LAN, specifying the servers local IP address and/or MAC address. You can normally find this information using a free network scanner like http://www.fing.io
4. Hello Reverse Proxy: That’s what you want to do - forward all incoming traffic to your newly configured Reverse Proxy.
But we haven’t configured one yet! Well, so let’s do it.
Every QNAP server has a Web server built into it. It is by default activated because it serves your QTS web interface on port 8080. But to be sure that it will also serve traffic on port 80, check this out:
a) Open your NAS Control Panel and under Applications choose Web Server
b) Make sure your web server is active and that it is set to use port 80
Note that this guide is somewhat rudimentary. It doesn’t take into account all possible aspects of the complex nature of a box like your QNAP NAS. But I will point out why some parts of this guide should be seen as educational purpose only, as we move along.
As an example; When you log on to your NAS web interface from your LAN, I assume you just type its IP address directly into your web browsers address bar, or perhaps you type its NetBIOSName. In any case, you are automatically taken to its port 80. But the NAS WEB interface is actually located on port 8080. The reason why this still works just fine, is because the NAS web server has a default index.php file that catches your request and sends you onwards to the right port. Now, since I wish to begin using port 80 for another purpose, I may eventually conflict with this nice feature - which then may cause your QTS web front to fail, unless your browser has cached the right address. Nevertheless, it does not mean that you will never again be able to log onto your NAS. No, it means that you may have to add 8080 after the IP address (or NetBIOSName) yourself, in order to get in to the NAS Web console. Now, there are several ways to avoid this conflict while at the same time building a Reverse Proxy that takes over port 80, but that would definitely derail this guide too much, so I will ignore that for now. Just so you are warned.
The web server in your NAS is realized using a customized QNAP version of Apache. To activate (wake up) the Proxy and reverse Proxy features in this Apache server, you typically modify the apache.conf file stored on your NAS. But regretfully, QNAP has customized its Apache server so much, that every time you reboot your NAS, all your config edits are lost (discarded). They’ve done this to ensure you will be able to log on again to the server should you screw up things too bad, by just rebooting.
So, the ultimate solution is to install your own instance of an Apache server (or any other web server of your choice - or perhaps a dedicated Reverse Proxy, like NGINX). But that’s a much too big task just to demonstrate the shortest and simplest way to achieve my goal. I will attempt to set up my Reverse Proxy using the built-in Apache server
5. Building the Apache Reverse Proxy Configuration:
Since modifying the apache.conf file is not such a good idea, I will instead make my own configuration file, put some essential content into it, name it custom.conf and store in a place where it is easily found by the apache server: The shared folder named Web which is found in every QNAP NAS.
But we need to make one single edit to the apache.conf file, to link it to our own custom.conf file. This is how:
a) SSH into your NAS using any telnet or SSH client of your choice. My favorite is WinSCP which you can download for free here: https://winscp.net/eng/download.php
(I’m not going to teach you how to use an SSH client, or how to traverse the directory structure of your NAS, or how to edit a text file like apache.conf)
b) Once inside your NAS, goto /mnt/HDA_ROOT/.config/apache (Remember that all folders beginning with a dot, are invisible, hidden folders).
c) Then open the file apache.conf in your favorite text editor, scroll down beyond the last line in this file and add the following line: Include /share/Web/custom.conf and then save apache.conf back to where you found it. Now, remember that whenever your NAS is rebooted, this modification is lost and you have to redo it. There are ways to overcome this problem, but I’ll leave that for some other time.
d) Now maneuver yourself into /share/HDA_DATA/Web and in here, create a text file named custom.conf, again using your favorite text editor.
Add the following to your newly created custom.conf file:
Code: Select all
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so <VirtualHost *:443 *:8081> ServerName app.stevens.com ProxyPass / http://NAS_IP:Port#/ ProxyPassReverse / http://NAS_IP:Port#/ SSLEngine on SSLCertificateKeyFile /share/HDA_DATA/certificates/app.stevens.com.key SSLCertificateFile /share/HDA_DATA/certificates/app.stevens.com.cert SetEnvIf User-Agent “.*MSIE.*” nokeepalive ssl-unclean-shutdown </VirtualHost>
Line1: This is to load the proxy module into the apache server
Line2: This is to load the Reverse Proxy module into the server
Both the above two lines only needs to be loaded once every time you reboot the NAS or restart the Apache server. If you manually reload the server config during trial and error sessions, these lines will generate a warning that the modules are already loaded, and then skip it. You can safely ignore these messages.
Line3: This initiates the section called Virtualhost. This section must be repeated for every valid server you intend to expose. In this tutorial, I’m using only a single web service example to serve visitors: app.stevens.com
It can be named anything as long as it is a valid web address. It could also be www.stevens.com. If you do not have an external domain service (or DynDNS) that converts this address to your correct WAN IP, then you’ll have to type the IP instead. But if that’s the case, you’ll have to tell your visitors that they must remember that IP.
Then your repeat the <VirtualHost> section for each and every server you wish to allow visitors to visit. For example:
and so on…
The name of the certificate files can be changed to anything (including the extension), as long as your reference in the config file (path + filename.ext), is correct.
6. Add an SSL certificate to secure your server traffic:
In order to make HTTPS work, you must change the configuration of your NAS web server to enable secure connection. Go to the control panel in your NAS. Under Applications, open the Webserver and make sure both «Enable Web Server» and «Enable secure connection (HTTPS)» is ticked off. Then make sure the port number for the Web server is set to 80, and that the port number for the secure connection is set to i.e. 8081, as I use here in my example. You may choose any port number you like. Then, by adding the *:443 and the *:8081 in the line 3, the web server will know that all incoming traffic on port 443 shall be sent onwards to 8081. The asterix is to allow any domain name to be used, but his can be restricted, if you wish.
Line4: You must tell the web server which name to allow. In this tutorial I have set the server name to app.stevens.com. Replace it with the DNS name of your domain, or - if you never made one - the http://<WAN-IP> address assigned to your internet connection by your ISP.
Line5: This is the Proxy statement that tells the apache server where to send incoming requests that has met the criteria. Insert the correct IP address of the server where your app is located, along with the correct port number of the app. In my example, I would use http://192.168.0.8:4040/ because - as you may remember - I’m using Madsonic as my example and this is the exact address I would type from a computer inside the LAN to reach Madsonic. You must replace this with the correct address of your application.
Line6: This is the reverse proxy statement that tells Apache web server what traffic to catch and relay back to the visitor. This is normally the same IP and port as above.
Line7: activates the secure connection engine.
Line8: and Line9: tells the web server where to find your certificates. Below is the explanation on how to get hold of self-signed certificates easily, as well as how to generate valid certificates using Let’s Encrypt
7. Self-Signed Certificates
Go visit www.selfsignedcertificate.com
In the green box, type in your server domain name. In my example it would be app.stevens.com Then click the big green button that says GENERATE.
This is where I have to admit that I haven’t tried to use this service for a direct IP address. Go ahead and try, but if it doesn’t work, I’m afraid you may have to find a way to get yourself a valid domain name. And it must be one that is pointing directly into, or somehow is redirected to your WAN-IP.
Assuming you’ve gotten this far, you’ll be presented with two downloadable files:
Code: Select all
Line10: is added to secure compatibility with Internet Explorer from Microsoft. I’m not going to explain it. Just add it as-is and accept that it’s good to have.
Line11: closes the VirtualHost section.
Remember you have to repeat this whole section as many times over as you wish, by exactly copying and pasting it inside the custom.conf file, and then edit the variables: Servername, NAS_IP:Port and certificate names of the new pair of files generated for each subdomain.
Now, keep in mind that these self-signed certificates are free and thus not authorized. That means that when someone visit you, their browser will warn them that the certificate cannot be validated. Visitors have to accept that before they can move on and get inside. This does not mean that the quality of the encryption or the features of the certificate is poor. By no means. It is just as good as any certificate. It just isn’t commercially validated. As long as you visitor trust you, they can also trust your certificates. Even though these are free self-signed certificates.
There is a way to silence the nagging warnings from the browsers, and that is to store a copy of the certificate in the root certificate repository on every visitors PC. You can do that easily from internet explorer as a local administrator. Look it up on Google, if you’re interested.
What we’ve done so far is to create the settings for the ReverseProxy. It will only work if your visitors come in via port 443 using HTTPS protocol. As I said earlier, I want visitors to be able to come in via Port 80 using ordinary HTTP, and automatically be kicked back out and re-routed in again on port 443 using HTTPS so that the above VistualHost comes into effect and the certificate is activated and secures the traffic by encryption.
In order to accommodate that, we must create another <VirtualHost> section on our custom.conf file that watches HTTP traffic on port 80. This is it:
Code: Select all
<VirtualHost *:80> ServerName app.stevens.com Redirect / https://app.stevens.com/ </VirtualHost>
Of course, these two VirtualHost sections always work in pairs. You can’t have one without the other.
As far as I know, the order of these sections is irrelevant.
So, to Summarize: The second VirtualHost section captures incoming traffic on port 80 and forwards it instead to port 443. The First VirtualHost section captures incoming traffic on port 443 and establishes the secure connection and the reverse Proxy feature.
Remember, that for this to work, your WAN router (firewall) must have been set up to forward both port 80 traffic as well as port 443 traffic to your NAS Web Server. In my example, port 80 traffic is forwarded to port 80 on the NAS, while port 443 is forwarded to port 8081 on the NAS. This is by choice only. You can choose anything else if you like, as long as you know what you’re doing.
8. Ready, set, go: Now is the time to test the result.
In order to force Apache to read (reload) the configuration files, go to a command line prompt in the NAS using your favorite SSH client (WinSCP can also do that for you, but I find PuTTY to be easier). Then, once you’ve logged in to your NAS, type:
Code: Select all
If everything you’ve done so far is correct, you should now be able to test the result:
a) Make sure your app (in my case Madsonic) isn’t forwarded anymore in your firewall/router through an external port. Deactivate any existing rules you may have set (in my case, this means closing port 4040)
b) Double check that incoming traffic on port 80 is set to be forwarded to your NAS where your newly established ReverseProxy is now running.
c) Open your favorite web browser from a PC outside your LAN and make sure you first clear its browsing cache. You can use a mobile phone as a HotSpot to get outside on the internet. You cannot test this while you are logged onto your LAN (or WLAN).
Then type in your domain name, or WAN-IP address, whatever you have chosen to use (you should not have to add port 80 to the URL, but you can). This should now redirect you to your app of choice. If you still end up anywhere else, something is wrong. Go over everything again.
If it works, congratulation.
Your all set.
The next step is to buy commercial certificates, and perhaps a DynDNS service. In the last section, I will explain how to use a free valid certificate from Let’s Encrypt.
Remember that what your visitors type in their browsers address bar, must match exactly what you have put into your VirtualHost sections. If they, or your DNS provider makes any modifications to the HTTP header, it will no longer work.
If a path is needed to start your Web application, you must add that to the VirtualHost section. Your visitors cannot do that.
9. Change to Let’s Encrypt:
As mentioned already, self-signed certificate has the same encrypting quality as any commercial certificate. But Microsoft, Google and other browser manufacturer have announced that they have plans to force all web traffic to be SSL based, and that the certificates must be validated. If not, traffic may be blocked on the internet by your browser.
So, it may be a good idea to move to valid certificates. There are many authorities that commercially sell valid certificates. You pay, and they deliver. But there is at least one, that is still free – and valid; Let’s Encrypt. There’s one catch though – certificates issued by Let’s Encrypt are only valid for 90 days. Then they expire and you have to regenerate them in order for them to continue working for another 90 days.
If you are prepared to take on this administrative burden, then read on. If not – then go somewhere else and buy commercial certificates that can last as long as you’re willing to pay.
In order to get a certificate for your website’s domain from Let’s Encrypt, you have to demonstrate/prove control over your own domain server. There are several ways to do that, but in common – it’s fairly complicated. But your QNAP NAS has a built-in feature that can do this for you.
Let’s try the QNAP method:
a) First, make sure your router is forwarding all incoming traffic on port 80, to port 80 on your NAS server where the certificates are to be generated. If you choose the same server that already has the Reverse Proxy configured, you must first disable all redirections done by the RProxy, otherwise, the attempt to prove your control over the server will fail. It may therefore be easier to temporarily route all port 80 traffic to another QNAP NAS that you are free to use.
b) But to temporarily disable the RProxy, you cannot just turn off the Apache server. After all, it is the Apache server’s response to generic port 80 calls, that is used by Let’s Encrypt to verify that you have control over the server. Therefore, you must allow the Apache server to run in its default configuration. That implies disabling all redirecting done by the RProxy. There are several ways to do that:
b) But to temporarily disable the RProxy, you cannot just turn off the Apache server. It’s the Apache server that runs your QTS Frontend. If you stop it, you are likely to lock yourself out. Let’s Encrypt use port 80 to communicate with QTS to verify that you have control over the server. You must allow the Apache server to run in its default configuration. That implies disabling all redirecting done by the RProxy. Otherwise port 80 calls will be redirected to another server (service), and the communication will fail. There are several ways to disable the RProxy redirect;
1) Just comment out the include statement in your apache.config file so the custom.config file is omitted temporarily.
That way, the RProxy is disabled (not loaded). (Remember to always restart the apache server after any modifications to any config file).
2) Just comment out all sections in your custom.config file where the redirecting is done. In the example used in this guide, that would be the section explained at the end of chapter 7:
Code: Select all
#<VirtualHost *:80> # ServerName app.stevens.com # Redirect / https://app.stevens.com/ #</VirtualHost>
(Alternative #1 is easier and quicker)
3) Then, go outside and visit your WAN-IP from the internet. (Use mobile phone as a hotspot for your PC so that you do not have to leave the house). The response you should get, is the default “Page not found” message or whatever is inside the index.html file on your Apache server. Then, you’re all set. If you get anything else, then the challenge will fail.
4) Now go to Control Panel --> Security --> Certificate & Private Key --> Replace Certificate
In the pull down menu, select Get From Let’s Encrypt and click on Next
In the Domain field, type the name of the domain that you wish to apply SSL certificate to, in the form xxx.yourdomain.yy where “xxx” can be “www” or any valid subdomain name, and yy is the abbreviation of the top domain used, normally .com, or - for example .de for Germany. A complete entry could look like this: shop.businessweb.com
Type your valid email address in the email field. This address is used by Let’s Encrypt to notify you when your certificates are about to expire.
In the Alternative name field (which is optional) you can type a series of valid domain names to be included in the same certificate. This is handy if you have many different services running that you wish to expose to the internet using several subdomains under your main domain, such as:
and so on…
Each name (alias) is separated by a comma (no space). It does not have to be in the same domain.
I have experienced that the process of generating Let’s Encrypt certificate with several alias’s often fail. This, I believe is a QNAP issue, and I can only recommend trying again, or try the same procedure on a different server. It doesn’t matter which server is used to generate the certificate. The resulting files (certificate and key) can be easily downloaded and later copied to the RProxy server.
If you loop into repeating fails trying to generate Let’s Encrypt certificates from your QNAP NAS, it may be that you have fallen into the limit trap. Read this document to understand the limitation rules: https://letsencrypt.org/docs/rate-limits/
5) When you generate or import certificates, the *.key file and the *.cert file is merged into the file: /mnt/HDA_ROOT/.config/stunnel/stunnel.pem (The path may vary on different version of QTS). Existing certificates are backed up to separate files named backup.key and backup.cert. Remember that filenames and extensions on these files can be anything in a Linux environment. In order to check the content of a certificate file, you can easily copy the file to a Windows machine, rename it with the extension *.crt and then doubleclick on it, and Windows will open it and reveal its content in a human readable form.
6) In order to put your new certificates to good use, you have to point to it from the custom.config file, just as I explained in chapter 5. If you find it convenient to keep these certificates stored as individual files in a folder of your own choice, that’s fine too. To do that, you have to download the files after successfully generating them. The Download command is a separate button found under;
Control Panel --> Security --> Certificate & Private Key --> Download certificate
The certificate is downloaded as a zip file, and you have to extract it to get to the content. Then you store the files where ever you want on your NAS, name the files whatever you want, and point to them in your custom.config as explained in chapter 5, with full path.
An alternative method – as mentioned above – is to use the stunnel.pem file instead. The advantage is that this allows you to easily update the certificate every time it expires, by simply clicking the button Control Panel --> Security --> Certificate & Private Key --> Update certificate (this button only becomes visible when , and – if the process works as it should – and a new certificate will be generated for you automatically, and last for another 90 days. This minimizes the administrative burden. In order to use this method, you have to point your custom.config to the *.pem file. Either use the path listed above, or use this symlink: /etc/stunnel/stunnel.pem.
In general, remember to add quotation marks if you have a path or filename containing spaces.
A few last word of advice; Check what happens if you just type your WAN-IP from the internet (no https). If that brings you to your exposed web service, then you may dislike that. Should any boot crawler or person who snoop around on the whole internet be able to hit your service unless they know it’s correct domain name? The reason this happens, is due to some of the more peculiar settings that QNAP has inside their apache.config file. If no match is found in your list of redirections, and no index.html file is found, then the traffic is simply sent to the redirector on the top of the list (!).
One way to avoid this, is to add a “catch-all” redirector to the end of the list;
Code: Select all
<VirtualHost *:80> ServerAlias * Redirect / https://www.google.com/ </VirtualHost>
Let me know if this guide worked for you, and/or if you find errors or mis-explanations in it.
A completely different (and perhaps more elegant way), is instead to use one of these methods: