On Fri 11 Apr 2008, John Zhang wrote:
> We have a situation that we would like to restrict the
> access to certain folders only to requests from the
> "local machine".  Here is why:
> When a page is processed by our filter, the filter
> (based on page logic) may request pages (just like a
> regular web page request) that should never go to the
> browser.  We put these pages in a folder.  And would
> like to use apache config to restrict the access to
> only the "local machine".  Here is the config
> <LocationMatch "/secrete-stuff/">
>     Order Deny,Allow
>     Deny from all
>     Allow from 127.0.0.1
>     #Allow from localhost
> </LocationMatch>
>
> The issue we face:
>     When our filter issues the request, we use the
> hostname from the original request. eg, original
> request
> http://1.2.3.4/index.html
> our filter might issue
> http://1.2.3.4/something/secrete-stuff/server.js
>
> In order to make the above directive work, we will
> have to put the ip (1.2.3.4) in the Allow section.
> However, we are planning to deply many servers, it
> would be very hard for us to edit each config file.
> So we are wondering if there are anyway we can achieve
> the same result without make ip-specific changes.

I see several ways to solve your problem each depending on your setup. I 
assume you are using modperl 2 with apache 2.2.x.

1) You can fetch the IP address in a <Perl> block and add the appropriate 
Allow statement. I use something similar on my notebook. Normally I am at 
home connected to my LAN. Then the apache should listen on 192.168.0.4. When 
I am not connected to my LAN the apache should nevertheless be able to start. 
So, I check if there is an interface with my IP address and add the Listen 
directive only if so:

<Perl>
use IO::Interface::Simple;
my ($opi, $vm);
foreach my $if (IO::Interface::Simple->interfaces) {
  if( $if->address eq '192.168.0.4' ) {
    push @PerlConfig, 'Listen opi.home:80', 'Listen opi.home:443';
    $opi++;
  } elsif( $if->address eq '192.168.9.1' ) {
    push @PerlConfig, 'Listen opi-vm.home:80', 'Listen opi-vm.home:443';
    $vm++;
  }
}

warn "WARNING: could not find opi.home. Not listening on this address"
  unless( $opi );
warn "WARNING: could not find opi-vm.home. Not listening on this address"
  unless( $vm );
</Perl>

I don't know how well this works inside a <Location>. Maybe you'll have to 
configure the whole Location block in Perl.

2) It's not well documented but apache can evaluate environment variables 
during configuration. So you can set one containing your local IP address and 
then write

  Allow from "${LOCAL_IP}"

3) use a fake hostname set in your /etc/hosts that points to the local IP on 
each host.

4) If your setup is identical on all servers you must be listening on 
127.0.0.1 as well. So why not issue the request to this address?

5) This is the best solution in my opinion. Why do you bother yourself and 
your server with issuing a full featured request? Why not a subrequest, 
$r->lookup_uri or even better $r->lookup_file? In the latter case your secure 
resources can be even outside your DocumentRoot. You only have to make it 
accessible via a <Directory> block.

6) a .htaccess file in your secured directory with the following content:

PerlAccessHandler "sub { \
  use Apache2::RequestRec (); \
  use Apache2::Connection (); \
  use Apache2::Const -compile=>qw(OK FORBIDDEN); \
  return Apache2::Const::FORBIDDEN \
    unless $_[0]->connection->local_ip eq $_[0]->connection->remote_ip; \
  return Apache2::Const::OK; \
}"

Alternatively this statement may also be in a Location or Directory block. It 
may also be a PerlInitHandler (within Location, Directory or .htaccess) or 
PerlHeaderParserHandler.

Torsten

--
Need professional mod_perl support?
Just ask me: [EMAIL PROTECTED]

Reply via email to