Certainly, I am not a world master at all things computers. But I sure do seem to have a broad knowledge in many things. Today's example is using Apache2 as a webproxy, specifically for redirecting traffic intended for another server.
The best example I have for this is the LDSGamers Minecraft server we are currently hosting. I'm a part of their gaming community as well, and when their Minecraft host took a years payment (facts may be exaggerated) then closed up shop, they were hosed on where to put their server for a while. Luckily, I had a little machine available that would be perfect for such a thing. The only problem being, I only have one IP address, and I am already hosting a Factorio Server on a different machine. The game server itself isn't a problem, since it should run on a different port from factorio. But to easily manage the server via web gui? It's much easier to not need worry about using different ports in URL's just to manage something. My work place also blocks all ports but basic web traffic, so if I need to administer the server, using a different port isn't an option for me.
Que in, ProxyPass: A feature optional in Apache that allows the server to channel traffic destined for one place to traverse (unknowingly to the client) to another. In my fun case, we're also using multiple domain names directed at my IP, and my server is effectively routing the traffic to the proper servers management gui's.
Have a code example:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName fac-admin.3ragaming.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/factorio/certificate.crt
SSLCertificateKeyFile /etc/ssl/factorio/private.key
</VirtualHost>
<VirtualHost *:443>
ServerName mine.ldsgamers.com
SSLEngine On
SSLCertificateFile /etc/ssl/mine.ldsgamers.org/certificate.crt
SSLCertificateKeyFile /etc/ssl/mine.ldsgamers.org/private.key
ProxyPass / http://192.168.1.117:8080/
ProxyPassReverse / http://192.168.1.117:8080/
</VirtualHost>
</IfModule>
I should add a disclaimer: I would not be surprised if a couple things in this code could be done better. But what I have works none the less. Also, the actual domain name paths have been changed for the sake of this example.
Now that that's out of the way. As we see in the code, this is specifically to use SSL (that fancy "secure" https) for these web servers. We have the 3Ra factorio management (mgmt), "fac-admin.3ragaming.com", and the LDSGamers Minecraft mgmt, "mine.ldsgamers.com". Factorio mgmt is local to the same server, while the Minecraft mgmt is hosted on another machine in the local network. The Minecraft mgmt is also not secure by default (although the program we use (McMyAdmin) does support it natively. I'll get to this later), so this proxy is also applying some secure SSL to the connection.
Should be simple enough to read. We have ServerName, for the dns addresses. We have the filepath to each SSL file needed for each server. Factorio has it's web directory set. And Minecraft has the IP and port number to both redirect the traffic to, and expect return traffic from.
Easy peasy, we are sharing one public IP address with two different web servers on the same network. We take this one step further with our Minecraft DynMap. The map plugin, by default, uses port 8123. Although I have this port forwarded through the router, we're back to the scenario of "using ports on URL's is annoying." So we add a proxy pass rule for that!
ProxyPassMatch ^/map$ !
RedirectMatch ^/map$ /map/
ProxyPass /map/ http://192.168.1.117:8123/
ProxyPassReverse /map/ http://192.168.1.117:8123/
ProxyPass / http://192.168.1.117:8080/
ProxyPassReverse / http://192.168.1.117:8080/
Now we can use the same URL (mine.ldsgamers.com) only need to add /map to it, and we can view the map, proxy tunneled to the server, but on a different port from the regular web traffic. I found that this only worked if the full URL included a trailing / on the address (mine.ldsgamers.com/map/ intead of just /map), but that was easy enough to protect against using a smart redirect rule to force the trailing / to be added. I'm glad to be recording all of this as well, since I found no examples including this being a requirement. I believe this to be due to some sort of coding flaw in the javascript. Perhaps an example will do
<script type="text/javascript" src="version.js"></script>
Given the URL, https://mine.ldsgamers.com/, this will attempt to pull the "version.js" file from mine.ldsgamers.com/version.js. Normal, and expected. If the javascript attempts to pull from another other source, they will likely also be pulled from / or the root address.
Given the URL, https://mine.ldsgamers.com/map, however, it appears that version.js loaded properly from /map/, but it's sources are still attempting to pull from mine.ldsgamers.com/ or the root address. When a trailing / is added to the URL, they then seem to source from the correct /map/ directory. Odd behavior, but this was corrected both by using /map/ as the proxy pass path, and using a redirect filer to ensure /map is changed to /map/. Otherwise /map is send to the mgmt gui, which reports a 404 error.
Tricky, yet effective.
Lastly, regarding SSL forwarding. I mentioned that the Minecraft mgmt software allows SSL natively. However, if the target server is using SSL, then the proxy server must know how to negotiate that SSL also. I had to discover how to make this work with an OpenVPN Access Server I am running for a business. OpenVPN supports SSL, and I had the certificate installed. But in development, they were wanting to use the same server for Apache web traffic if possible. The only way to make OpenVPN allow this was to change it's management port away from 443, and proxy tunnel the vpn domain to the new port. OpenVPN-AS will only do SSL though. So a way to proxy the SSL traffic had to be found. For sake of regularity, I'm going to use the minecraft server as the example still, and pretend that the McMyAdmin software is configured for SSL also. The steps really aren't that much more difficult. As long as both servers have he proper certificate and key files, and the Apache service is configured for it, A simple SSLProxyEngine On is used below SSLEngine On, and the service will now to Proxy the traffic securely. This method would be recommended more specifically for proxying traffic that is external to the proxy server.
I hope this helps someone searching for guidance on some proxypass rules. I use Proxy pass a lot now. One thing I would like to figure out would be a way to send the client IP along with the proxy pass, so the target server knows who's sending the request. Right now it only knows of the proxy server. Supposedly, there is a way to do this. I just have not attempted it yet.
EDIT: Got it work, and was much easier than expected once I found the right informaion. Apache2 comes with the mod "remoteip", it just needs to be enabled on the target server (not the proxy) with: "a2enmod remoteip". Then you add "RemoteIPHeader X-Forwarded-For". Now the target server can report the client. Useful for php and tracking IPs.
To future expeditions!