original in en Atif Ghaffar
I live and work in Switzerland as a webmaster and unix administrator. My passions include, Linux, unix, Perl, Apache and GPL softwares. More about me can be found on my homepage
I run a small LAN at home masquarated with Linux using ip masquarading, and ip firewall. Although all machines on my network can access all information on the internet, only the machine which is doing the ip masquarading is available from the internet. In my last Apache article, I showed you how to recycle ip addresess, in this article I will demonstrates how to make a webserver behind a firewall available on the internet without changing rules on your firewall or compromising security. In this articel we will see how we can use Apache's ProxyPass directive to achive this goal. The target audience of this article is System Administrators or any one who is building a small to medium size LAN at home or at work.
For a long time on my LAN, the router (the machine that was doing that masquarating/firewall) was also acting as the web-server, mail-server, ftp-server, dns-server et all.
One day I had then the need to to serve web content from another machine that was behind the firewall.
I also wanted to serve some documents from an SGI IRIX box that was behind the network (a video server, serving streaming images). This machine had full access to the internet, but the internet users could not connect to the machine. Although I had no intentions to put this IRIX machine on the network, it was neccessary that people could connect to the web service that was available from this machine.
I was facing the same problem at work with a similar network and a Firewall.
Each time someone wanted a development webserver to be available from the internet for demo purpose, the rules on the firewall needed to be changed and you had to give the machine an external ip address and compromise the security of the network.
After considering several solutions I implemented one with Apache and its ProxyPass directive.
ProxyPass require mod_proxy to be compiled in or loaded as a module with your Apache server.
Following is the definition of ProxyPass from Apache manual
This directive allows remote servers to be mapped into the space of the local server; the local server does not act as a proxy in the conventional sense, but appears to be a mirror of the remote server. <path> is the name of a local virtual path; <url> is a partial URL for the remote server.
Suppose the local server has address http://wibble.org/; then
ProxyPass /mirror/foo/ http://foo.com/will cause a local request for the <http://wibble.org/mirror/foo/bar> to be internally converted into a proxy request to <http://foo.com/bar>.
Mapping the internal video server to the external web server.
Internal network: hometranet.home 192.168.1.0/255.255.255.0
(in the theme of internet, intranet, extranet, I call my home network hometranet)
External network: developer.ch 188.8.131.52
Video server (internal) running on host cam.hometranet.home serving
video streams from url http://cam.hometranet.home:5555/cams/sony/stream
still images from camera at http://cam.hometranet.home:5555/cams/sony/image
I wanted to view the result from those urls when I visit
This can be easily done by using the ProxyPass directive from Apache by simply adding the following lines in the httpd.conf or srm.conf
ProxyPass /video http://cam.hometranet.home:5555/cams/sony/stream
ProxyPass /video http://cam.hometranet.home:5555/cams/sony/stream
Now after restarting the web server (if mod_proxy was available), http://mozilla.developer.ch/image answers from the cam webserver.
For the user visiting the site its totally transparent, and almost* no security was compromised by using this method.
*I used the word almost, because there is no such thing as total security on the internet :)
The proxypass trick can be used to map a virtual host entirely to a different machine.
docs.sun.developer.ch mapped to solsparc.hometranet.home
NameVirtualHost 184.108.40.206 <VirtualHost 220.127.116.11> ServerName sun.docs.developer.ch ProxyPass / http://solsparc.hometranet.home/ TransferLog /net/www/logs/sun.docs.access ErrorLog /net/www/logs/sun.docs.errror </VirtualServer>you can also forward to hosts by their ip address
<VirtualHost 18.104.22.168> ServerName sun.docs.developer.ch ProxyPass / http://192.168.1.7/ TransferLog /net/www/logs/sun.docs.access ErrorLog /net/www/logs/sun.docs.errror </VirtualServer>
Since your main web server is making requests to the internal web servers on behalf of your users, you cannot do any sensible logging on the target host, instead you have to log all requests on the source host.
In the above case I log entries on the main host sun.docs.developer.ch instead of solsparc.hometranet.home
Results of logging on sun.docs.developer.ch (dummy result)
22.214.171.124 - - [05/Nov/1999:22:09:04 +0100] "GET /index.html HTTP/1.0" 304 - 126.96.36.199 - - [05/Nov/1999:22:09:04 +0100] "GET /navi.html HTTP/1.0" 304 - 188.8.131.52 - - [05/Nov/1999:22:09:04 +0100] "GET /entrees.html HTTP/1.0" 304 - 184.108.40.206 - - [05/Nov/1999:22:09:15 +0100] "GET /complets.html HTTP/1.0" 304 - 220.127.116.11 - - [05/Nov/1999:22:09:19 +0100] "GET /menu_poisson.html HTTP/1.0" 200 841 18.104.22.168 - - [05/Nov/1999:22:09:25 +0100] "GET /volailles.html HTTP/1.0" 304 - 22.214.171.124 - - [05/Nov/1999:22:09:44 +0100] "GET /agneau.html HTTP/1.0" 304 -Results from logging on solsparc.hometranet.home
192.168.1.1 - - [05/Nov/1999:22:09:04 +0100] "GET /index.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:09:04 +0100] "GET /navi.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:09:04 +0100] "GET /entrees.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:09:15 +0100] "GET /complets.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:09:19 +0100] "GET /menu_poisson.html HTTP/1.0" 200 841 192.168.1.1 - - [05/Nov/1999:22:09:25 +0100] "GET /volailles.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:09:44 +0100] "GET /agneau.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:09:56 +0100] "GET /desserts_ind.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:10:00 +0100] "GET /cocktails.html HTTP/1.0" 304 - 192.168.1.1 - - [05/Nov/1999:22:10:10 +0100] "GET /cgi-bin/commande.cgi HTTP/1.0" 200 2146The same applies also to name based or ip bases ACLs (access control list).
<VirtualHost 126.96.36.199> ServerName sun.docs.developer.ch #this rule only allows users from good.host.com domain <Location /private> order deny,allow deny from all allow from good.host.com </Location> #This rule deny's the uncool Microsoft's monopoly helper browser. BrowserMatch MSIE uncool_browser <Location /coolpages> order allow,deny allow from all deny from env=uncool_browser </Location> #This rule only allows users that are in your passwd.httpd file <Location /coolpages> AuthName "only for registered users" AuthType Basic AuthUserFile "/etc/httpd/passwd.httpd" <Limit GET> require valid-user </Limit> </Location> ProxyPass / http://192.168.1.7/ TransferLog /net/www/logs/sun.docs.access ErrorLog /net/www/logs/sun.docs.errror </VirtualServer>