This guide is for HTTPS, however it works exactly the same for HTTP.

This is a short and sweet guide, however its something that needs to be documented as it is extremely fiddly!

At home I have a few KVM-based virtual machines, and quite a few Docker containers running using internal networks that (by design) only the server and themselves can access.

This is all well and good and secure, however its a bit of a pain in the ass when you want to test things or even worse use them (without a plethora of routes, or having to NAT the hell out of everything…).

In this example, I have a virtual machine listening on the internal 192.168.70.0/24 network running an Apache based application. I know it works because if I hit it up on telnet it works:

[email protected]:/me# telnet 192.168.70.72 80
Trying 192.168.70.72...
Connected to 192.168.70.72.
Escape character is '^]'.

Naturally if i try that from a desktop not containing a route (or if my server didnt have NAT) then it wouldnt work.

What I want to be able to do is hit a URL, i.e. ‘site.ehertz.uk’, and have that Apache application, on that VM (or container) appear.

You can do this with iptables, as mentioned earlier:

iptables -t nat -I PREROUTING -p tcp -d 192.168.0.176 --dport 8000 -j DNAT --to-destination 192.168.70.72:80
iptables -I FORWARD -m state -d 192.168.70.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

.. along with enabling conntrack, ipv4_forward, etc.

(In my example above i’ve got port 80 in use, which is common, so im having to redirect on a different port).

This is a pain in the ass as you have to connect to the host and remember to enter the port every time, and its not hugely elegant.

So, whats the answer?

ProxyPass

What I ended up with, was using ProxyPass and DNS to allow me to hit a URL, i.e. site.ehertz.uk and have the Apache application on the VM load.

First, simply create a DNS A record to your server’s IP using your chosen DNS server – i.e. in bind it’ll be:

siteĀ IN A 192.168.0.176

Once you can dig that address and get the correct IP (i.e. ‘dig site.ehertz.uk’ returns the IP 192.168.0.176), you can crack on with the ProxyPass configuration.

First, ensure that you have the correct modules enabled:

[email protected]:/me# a2enmod proxy_http
Considering dependency proxy for proxy_http:
Module proxy already enabled
Module proxy_http already enabled

Next, navigate to /etc/apache2/sites-available/ and create a new site:

[email protected]:/me# cd /etc/apache2/sites-available/
[email protected]:/etc/apache2/sites-available# nano site.conf

Within this new conf, paste something similar to the following:

ServerName site.ehertz.uk
ServerAlias *.site.ehertz.uk
####Configuration for SSL #####
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
SSLHonorCipherOrder on
 SSLCertificateFile /etc/apache2/ssl/site.ehertz.uk/ssl.crt
 SSLCertificateKeyFile /etc/apache2/ssl/site.ehertz.uk/ssl.key
 SSLCertificateChainFile /etc/apache2/ssl/site.ehertz.uk/sub.class1.server.ca.pem 
#### End of SSL Configuration #### 
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so ProxyPass / http://192.168.70.72/ disablereuse=On
 ProxyPassReverse / http://192.168.70.72/

Few points:

  • Ensure your SSL crt, key and pem file paths are all correct.
  • Ensure your VirtualHost IP is correct.
  • Ensure your port is set to 443 for SSL.
  • If you are not using SSL, change 443 to 80 and remove all the lines between ‘Configuration for SSL’ and ‘End of SSL configuration’.
  • Ensure the IP (192.168.70.72) is set to the IP of the internal VM/container on both lines at the bottom of the config!

Thats about it really. Restart apache2 using ‘service apache2 reload’, and then test it out. If you have any issues then double check /var/log/apache2/error.log.