Scenario
You have a single incoming IP address and want to run multiple web servers for multiple sites behind this IP address on your local network. The best way to do this is using a reverse proxy server For example:
- Your External IP is: 8.8.8.8 with and internal LAN of 10.1.1.X
- Ports 80 (http) and 443 (https) have been forwarded from your external ip to an internal server at 10.1.1.2 which will handle the reverse proxy and SSL/TLS work using letsencrypt
- You have other application web servers listening on port 80 on your internal LAN at 10.1.1.11 and 10.1.1.12 but these are not accessible from outside your network.
- You have subdomain11.yourdomain.com and subdomain12.yourdomain.com both pointed to 8.8.8.8 and you want visitors to them to see the application servers at 10.1.1.11 and 10.1.1.12 respectively.
- You want to provide secure https access to both subdomains but don’t want to configure this on each of the three servers separately.
This guide is based on using Apache2 on Ubuntu 16.04, some commands may differ slightly between different flavours of Linux but the core configuration for Apache2 should work on any distribution.
Instructions (Run All on the Reverse Proxy server – for this example it is 10.1.1.2)
- Set up Apache
On the reverse proxy server, install apache web server and enabled the required modules by executing the lines below in terminalsudo apt-get install apache2 -y a2enmod proxy a2enmod proxy_http a2enmod proxy_ajp a2enmod rewrite a2enmod deflate a2enmod headers a2enmod proxy_balancer a2enmod proxy_connect a2enmod proxy_html service apache2 restart
- Set up vhost files for each subdomain as per the examples below – this is the key to the super easy reverse proxy config that will support automatic use of letsencrypt and forward incoming traffic to and from each of the application servers from the single incoming IP.
File: /etc/apache2/sites-enabled/subdomain11.conf<VirtualHost *:80> ServerName subdomain11.yourdomain.com ProxyPreserveHost On DocumentRoot /var/www/html ProxyPass /.well-known ! ProxyPass / http://10.1.1.11:80/ ProxyPassReverse / http://10.1.1.11:80/ </VirtualHost>
Ok so what is going on in this file?
ServerName – tells apache to use the config file when a visitor arrives at your IP address using the domain specified.
DocumentRoot – is the local directory on the ReverseProxy server which will be used to authenticate the server using lets encrypt in the next step
ProxyPass /.well-known ! – tells apache not to forward traffic for the sub directory subdomain11.yourdomain.com/.well-known to the application server. This directory is used by letsencrypt to authenticate your server for SSL so we want to keep that heading to the local directory on the reverse proxy server.
ProxyPass / http:/10.1.1.11:80/ and ProxyPassReverse / http://10.1.1.11:80/ tells apache to forward all other traffic for this domain to the server 10.1.1.11 on port 80Once created you can run the command:
sudo service apache2 restart
Then browse to http://subdomain11.yourdomain.com and you should see the content hosted on the application server at 10.1.1.11. Once this is working you can create the virtualhost file for your other domain as per below:
File: /etc/apache2/sites-enabled/subdomain12.conf
<VirtualHost *:80> ServerName subdomain12.yourdomain.com ProxyPreserveHost On DocumentRoot /var/www/html ProxyPass /.well-known ! ProxyPass / http://10.1.1.12:80/ ProxyPassReverse / http://10.1.1.12:80/ </VirtualHost>
- This is all good and well but we do not yet have secure https access to these domains. To set this up we are going to use LetsEncrypt which is a great free service for obtaining https certificates for web servers. Install CertBot by following the instructions at their page. For Apache on Ubuntu 16.04 the command is as simple as running the command:
sudo apt-get install python-letsencrypt-apache
- Once certbot is installed we should be able to run it as per the instructions for your operating system. For Ubuntu 16.04 it is:
letsencrypt --apache
Which will take you through a wizard to automatically install the certificates to enable https access. Once complete you should be able to visit https://subdomain11.yourdomain.com and https://subdomain12.yourdomain.com. If you encounter any issues you may want to restart Apache one more time:
sudo service apache2 restart
Considerations
One note is that while you will be providing secure connections to visitors from the public internet the traffic between your reverse proxy server and the application servers will not be encrypted. You will need to ensure that the private LAN (in the example 10.1.1.X) is secure from monitoring or MITM attacks (eg. this is a fully private LAN behind a firewall and without any publicly accessible WiFi or Ethernet connections.)
Sources and Thanks
This guide was assembled after a fair session of google-fu. Big thanks to the posts and guides below which have all been drawn upon to create this single guide.
https://serverfault.com/questions/80123/how-to-add-exceptions-to-apache-reverse-proxy-rules
really awesome.thanks for share
Many thanks, finally one that worked for me. Only changes:-
$ a2dissite 000-default
virtual host files created in
$ /etc/apache2/sites-available
so
$ sudo nano /etc/apache2/sites-available/”hostname”.conf
$ a2ensite “hostname”
I then got Let’s Encrypt error
“Client does not support any combination of challenges that will satisfy the CA”
so loaded certbot
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-apache
$ sudo certbot –apache
thanks to https://certbot.eff.org/
I’m glad I wasn’t the only one that had this issue. Using the certbot client, which I can only assume it more up-to-date than the letsencrypt client, worked without an issue!
I wonder whether you should replace
ProxyPass /.well-known !
with
ProxyPass /.well-known/acme-challenge !
Eg, I use letsencrypt with a reverse proxy for a nextcloud server. That server which is configured to
Redirect 301 /.well-known/caldav /remote.php/dav, etc.
Also, I am running my reverse proxy server without proxy_ajp, proxy_balancer, proxy_connect or proxy_html, and all works fine on apache 2.4.29
This is a clear and concise illustration of the Apache Reverse Proxy functionality that I have reviewed so far. It has been extremely helpful to me.
My only wish is that you could point out a few ways to achieve your caution “You will need to ensure that the private LAN (in the example 10.1.1.X) is secure from monitoring or MITM attacks.”
It is a very good article, and I will continue my research on the LAN security aspect.
Thanks again.
Hi Glen, fair call I’ve added some basic prompts but happy to include any other general suggestions.
Very interesting and well written tutorial.
I am applying the same model but I’m stuck when it comes to enforcing https strictly.
in the *:80 part, I added the directive :
Redirect permanent / https://MyDomain.com/
But it simply doesn’t work!
Any idea?
The way I have https redirects working is below in the host file for the http site. Hope that might help?
RewriteEngine on
RewriteCond %{SERVER_NAME} =mydomain.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
By far the more straightforward tuto i found on the internet.
great many thanks to you !
To make it work, i had to correct the vhost generated by certbot (switching http to https and 80 to 443 and adding a line “SSLProxyEngine”).
I also followed used Mark’s suggestions.