Why do I need (want) to have a Reverse Proxy in the first place - and what does it actually do?
In my local home network (LAN) I have three QNAP NAS servers running various software apps serving my needs.
One of these apps is Madsonic (a nice music media- and player app). I’ll be using 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 - could be easily accomplished by just opening port 4040 in my firewall/router in my home network and forward incoming traffic to the Madsonic server (Madsonic uses port 4040 by default).
But there are several good reasons why one would not choose to do that:
- Every single app that I need (wish) to expose to internet visitors (myself included), has to have its own firewall opening and port forwarding.
- Authentication and access control takes place after the visitor is inside my LAN without any security and protection.
- Visitors would have to remember the port number for each app they wish to use.
- Traffic encryption (SSL) is a security measure that has to be added to each app (web service) individually.
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 itself.
Sounds great, eh?
Well, that isn’t all true. It depends where you choose to locate the reverse proxy (RProxy). 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.
- 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 or 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 - including usernames and passwords. However, to make it user friendly (visitor friendly), I don't expect visitors understand any of this. People use the default HTTP protocol unknowingly, and instead I'll 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 come through from the internet via port 80 in my router. Port 80 is the default HTTP port, and the router will then have to be configured to forward this traffic to the Reverse Proxy, which in turn will check the URL and upon a match, redirected it back out to the internet and in again, but this time on port 443 which is the default HTTPS port.
Keep in mind that whenever you type a regular web address (URL) in your browser, port 80 is by default assumed. You don’t even have to add the HTTP or the port number. But if you add HTTPS in front of your web address, port 443 is assumed. 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 several 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. - 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 the browser. This IP address is assigned to you 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 than 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 (as the IT-manager) still have to remember to update 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. I have a fiber connection to my house. A dial-up connection or ISDN connection would most likely receive a new WAN-IP address for each session. - 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 router. Port 80 is always default. Whether or not that will successfully take your visitor anywhere, depends on several things:
- Does your ISP allow traffic to port 80?
- Has port 80 been opened in your WAN routers firewall?
- Where is your firewall sending this traffic inside your LAN (port forwarding)?
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 forward port 80 for incoming traffic to a specific server on your LAN, specifying the servers local IP address and/or MAC address as well as selecting which port number to use.
You can find the IP addresses of your servers using a free network scanner like http://www.fing.io - Hello Reverse Proxy: This is what you want to do; Have all incoming traffic forwarded to your newly configured Reverse Proxy.
But we haven’t configured one yet! Well, so let’s do it.
Every QNAP server has an Apache Web server built into it. It is by default activated because it serves your QTS Web GUI by automatically forwarding your logon request to port 8080. It also serves all Web Apps installed from App Center through the default HTTP port – 80. But this is a user configurable setting. To check which port your Web server is configured to use, check this out:
a) Open your NAS Control Panel and under Applications choose Web Server
b) Here you can see what ports are set. The default setting is port 80 for HTTP traffic and port 8081 for HTTPS traffic. Since port 80 is already occupied by QTS Web Apps, you have to choose a different port for your Reverse Proxy. But regretfully, the Web server setting panel doesn’t allow you to configure additional ports (QNAP never thought of that possibility). However, the Apache Web server is capable of listening to more than one port. You need to modify the apache.conf file and add the additional port number to this file. You can choose any port number that isn’t already in use. In this tutorial I use port 81. See chapter 5 for instructions on how to edit the apache.conf file.
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.
Should you by mistake manage to screw up the port setting of your Web server and lock yourself out from the QTS logon Web UI, you may have to add 8080 after the IP address (or NetBIOSName) 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. The best solution is to avoid using port 80 internally. But you must use Port 80 in your WAN-router (Internet Firewall).
The web server in your NAS is a custom QNAP version of Apache Web Server. To activate (configure) the Proxy and reverse Proxy features in this Apache server, you modify the apache.conf file stored on your NAS. But regretfully, QNAP has customized its Apache server so much, that every time you reboot and/or update your NAS, your config edits may be lost (discarded) partly or fully. They’ve done this to ensure you will be able to log on again to the server should you screw up things too bad. However, this QNAP strategy has changed over time, and lately they are not as stringent in cleaning out your custom settings. In any case – make sure you keep a backup copy off the NAS of any config files that you have edited.
The ultimate solution is of course to install your own instance of an Apache server (or any other web server of your choice - like i.e. NGINX). But that’s a much too big task just to demonstrate the shortest and simplest way to achieve my goal. This guide use the integrated Apache Web Server to set up a Reverse Proxy. - Building the Apache Reverse Proxy Configuration:
Since modifying the apache.conf file too much can be risky, we will instead make a separate configuration file with all relevant settings for the Reverse Proxy, and name it custom.conf and store in a place where it is easily found by the Apache server; in the shared folder named Web which is found in every QNAP NAS.
But we need to make two changes to the apache.conf file;- Add a listen setting for port 81
- Add a link to your own custom.conf file.
- 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) - Once inside your NAS, goto /mnt/HDA_ROOT/.config/apache
Remember that all folders beginning with a dot, are invisible, hidden folders. Before you begin to edit any file, make a backup copy of the original and keep it in a safe place. - Open the file apache.conf in your favorite text editor. Look for the following line:
Listen 80
and add the following line:
Listen 81
Then, scroll down beyond the last line in the file and add the following line:Then save apache.conf back to where you found it. Now, remember that whenever your NAS is rebooted, this modification may be overwritten and you may have to redo it. There are ways to overcome this problem, but I’ll leave that for some other time.Code: Select all
Include /share/Web/custom.conf
- Now go to /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:
Explanation:Code: Select all
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so <VirtualHost *: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 my visitors, and I have named it: app.stevens.com
It can be named anything as long as it is a valid domain name. 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:
app.stevens.com
test.stevens.com
madsonic.stevens.com
and so on…
- 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 81, and that the port number for the secure connection is set to i.e. 8081, which are the two ports I use here in my example. You may choose any port number you like. Then, by adding the *:8081 in the line 3, the web server will know it is incoming traffic on port 8081 that it should look for. The asterix is to allow any domain name to pass through, but this can be restricted, if you wish.
Line4: You must tell the RProxy what URL to look for. In this tutorial I have named my server app.stevens.com. Replace it with the DNS name of your choice, or - if you own a domain, use 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.18: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 certificate files. 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. 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. - 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:
5960278_app.stevens.com.cert
5960278_app.stevens.com.key
The lead-in number for both files are random. The first file is your certificate, and the second is your private key. Both these files should be copied to the NAS where your Apache Web server is running. You can place them anywhere you want. In my example, I chose to make a special folder named «Certificates» directly under the main share: /share/HDA_DATA/ That’s an easy path to remember, and it keeps them invisible from File Station. Also, I removed the lead-in random number from the file names as these numbers make no sense.
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 81. This is it:
Remember that your WAN router has its port 80 open for incoming traffic, and it should forward this traffic to your Revers Proxy on port 81.Code: Select all
<VirtualHost *:81> ServerName app.stevens.com Redirect / https://app.stevens.com/ </VirtualHost>
This was easy enough to understand. All you have to do is to replace app.stevens.com with your domain name (or WAN-IP).
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.
To summarize: The second VirtualHost section captures incoming traffic on port 81 of the Reverse Proxy, verifies the URL and if recognized, forwards it to port 443 of your WAN router, which in turn forward this traffic to your Reverse Proxy port 8081. The First VirtualHost section captures this incoming traffic on port 8081 and establishes the secure connection, and finally redirects traffic to your internal App server.
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 81 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. - 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:
Every time you make a change to the custom.conf file, you have to issue the above command to force Apache to restart in order to reload it. Since the proxy modules are already loaded, you will get a warning message about that, but you can safely ignore those messages. Remember that if you instead reboot your whole NAS, then the content of your apache.config file may be lost.Code: Select all
/usr/local/apache/bin/apachectl restart
If everything you’ve done so far is correct, you should now be able to test the result:- 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)
- Double check that incoming traffic on port 80 is set to be forwarded to your NAS where your newly established ReverseProxy is now running.
- 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 should not 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.
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. - 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:- First, choose a NAS server where you plan to generate these certificates (if you have more then one NAS). If, not and you have to (or choose to) use the same NAS as your Reverse Proxy is running, then make sure your router is forwarding all incoming traffic on port 80, to port 80 on your NAS.
Now you see an additional benefit of not using port 80 for your Reverse Proxy. If you had choosen to use port 80 on your Reverse Proxy, you would have to manually disable all redirections done by the RProxy. Otherwise, Let’s Encrypts attempt to prove your ownership of the server would fail. It is easier to just change the port forwarding in your router from 81 to 80 while generating the certificates. - 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.
- 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:
mail.businessweb.com,private.businessweb.com,couchpotato.businessweb.com,media.businessweb.com
and so on….
Each name (alias) is separated by a comma (no space). It does not have to be the same domains.
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 Apache 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/ - 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.
- 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.
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;This will catch all port 80 traffic that could not be recognized and redirected, and instead send it off to Google. You can of course choose any URL you like. (Try the Pentagon)Code: Select all
<VirtualHost *:81> 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:
https://hub.docker.com/r/certbot/certbot/
https://www.developercookies.net/?p=400
viewtopic.php?f=320&t=132911&hilit=Let%27s+Encrypt - First, choose a NAS server where you plan to generate these certificates (if you have more then one NAS). If, not and you have to (or choose to) use the same NAS as your Reverse Proxy is running, then make sure your router is forwarding all incoming traffic on port 80, to port 80 on your NAS.