simplistic gatekeeper limiting access to apache2-based proxy

i had to expose some web-based application hosted on a windows server to the internet. i don’t put too much trust in the developers of that particular application so i did not want to make it reachable from the public internet. while i could not use ip address based whitelist i could count on the end-user of the application to do a simple routine at the beginning of her/his work: visit another page and only then try to access the actual web-app. security through obscurity? perhaps, but for me it that’s one more layer of protection.

i’ve found out that i don’t need to dynamically rewrite apache2 config and add/remove ip addresses that are allowed to access the protected resource. this stackoverflow answer suggested that mod rewrite’s RewriteMap can be a solution. so here’s my solution:

apache2 vhost:

<VirtualHost *:443>
 DocumentRoot /var/www/
 ProxyPass /ProtectedResource
 ProxyPassReverse /ProtectedResource
 RewriteEngine On
 RewriteMap ipslist txt:/var/www/gatekeeper/list.txt
 <Location /ProtectedResource>
  AddOutputFilterByType INFLATE;SUBSTITUTE;DEFLATE text/html text/plain text/xml
  Substitute "s|||i"
  RewriteCond %{REMOTE_ADDR} ^(.*)$
  RewriteCond ${ipslist:%1|black} ^black$ [NC]
  RewriteRule ^ - [F]
 # ssl related stuff + logging  

did you see what i did there? not just allowed reverse-proxying of request arriving to /ProtectedResource to an internal Windows-based but also protecting access to it via https and re-writing on the fly references in html/xml to into ; access to the /ProtectedResource is only possible for hosts that are listed in the text file /var/www/gatekeeper/list.txt

that file is updated by two scripts:

/var/www/gatekeeper/index.php – invoked by the user at the beginning of the working day by visiting

 file_put_contents('list.txt',$x."\n".$ip.' '.time());
 echo "hi $ip";

and /var/www/gatekeeper/cron.php – invoked from cron by visiting – it’s responsible for clean-up of the stale entries older than few hours:

 $res = "";
 foreach(explode("\n",file_get_contents('list.txt')) as $row){
  $row = explode(' ',$row);
   if (sizeof($row)!=2)continue;
   if ($row[1]<time()-3600*8)continue;
   $res.=$row[0]." ".$row[1]."\n";

there’s a risk of race conditions when during the execution of cron someone visits the gatekeeper page. in my case – where number of users is very small, i’m comfortable with it.

Leave a Reply

Your email address will not be published. Required fields are marked *