You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by André Warnier <aw...@ice-sa.com> on 2012/11/23 18:39:58 UTC
custom proxy setup with mod_perl
Hi.
I am trying to solve an unconventional (I think) issue with mod_perl (or even without it).
Environment : Apache 2.2/mod_perl 2 under Linux.
The issue :
A number of workstations are in a LAN, using a local DNS server under my control.
In the same LAN (192.168.45.0), I have a Linux host running Apache 2.2/mod_perl 2, also
under my full control (IP 192.168.45.100).
Currently, the LAN workstations access external websites such as (for the sake of example) :
1) http://www.site-1.com (IP 1.2.3.4)
2) http://www.site-2.biz (IP 2.3.4.5)
3) http://www.site-3.org (IP 3.4.5.6)
4) http://www.site-4.co.uk (IP 4.5.6.7)
(all these IP's being supposedly real public Internet IP addresses)
In the future, I would like that when the workstations try to access websites (2) and (4)
above, they access them through my Apache/mod_perl host.
The reason for this is that
a) I need to authenticate the users
b) I need to allow some users to access these external servers, and deny other users (and
for those, I need to return a nice page explaining why)
I already do the authentication/authorization using custom PerlAuth* handlers.
I also know how to write PerlFixupHandler and PerlTransHandler modules, and how to "push"
other Perl "HTTP cycle" handlers when needed.
My basic scheme is as follows :
- the DNS server configuration is modified so that when resolving the hostnames (2) and
(4) above, it returns the IP address of the internal Apache host (192.168.45.100).
When a workstation thus wants to connect to webserver (2) above, in reality it connects to
the internal Apache host, where I want to perform my mod_perl magic.
- on the Apache host, there is a virtual host configured with
ServerAlias www.site-2.biz
ServerAlias www.site-4.co.uk
so it responds to these requests.
The Apache host has access to the "real" IP addresses of the above external webservers.
(For example, in its own "hosts" file; or it has itself an "uncorrupted" DNS server which
delivers the original IP addresses).
In the Apache host, I have the following configuration section :
<Location />
AuthType MyOwn
AuthName CheckProxy
PerlAuthenHandler my:AuthHandler->get_id
PerlAuthzHandler my:AuthHandler->allow_or_not
Require valid-user
PerlFixupHandler ????
PerlTransHandler ????
ProxyPass http://(corresponding hostname)/(path and query as received)
</Location>
Now my questions are : if I do something at the level of the PerlFixupHandler or
PerlTransHandler,
1) is that "early enough" to be before the Apache ProxyPass step ?
2) can I set the "(corresponding hostname)" above in such a Perl handler, or otherwise
manipulate the URI before it gets proxy-ed ?
3) do I need this ProxyPass directive in my configuration, or can I just set the Apache
response handler to be mod_proxy_http, in one of the Perl handlers ? and if yes, how ?
I'd be thankful for any answer or tip, even about a solution which does not involve
mod_perl at all. (But in reality, I do need to do a bit more in my handlers than I allude
to above).
Re: custom proxy setup with mod_perl
Posted by Fred Moyer <fr...@redhotpenguin.com>.
On Fri, Nov 23, 2012 at 3:06 PM, André Warnier <aw...@ice-sa.com> wrote:
> Ok, get it, thanks.
> All-in-one, as a substitute for mod_proxy.
> I will have a second look now.
Feel free to write me off list with any questions you have specific to
this module, but if you can do what you need with mod_proxy I would
recommend that approach.
Re: custom proxy setup with mod_perl
Posted by André Warnier <aw...@ice-sa.com>.
Fred Moyer wrote:
> On Fri, Nov 23, 2012 at 2:18 PM, André Warnier <aw...@ice-sa.com> wrote:
>> Fred Moyer wrote:
>>> You might want to take a look at a mod_perl based proxy module I wrote
>>> - https://metacpan.org/module/Apache2::Proxy
>>>
>>> It was used in conjunction with Perlbal and a couple other tricks, but
>>> was pretty speedy given the crude nature of how I implemented it.
>>
>> No offense intended, Fred, but without much of a documentation, this is bit
>> above my level. I have trouble even understanding where it fits in.
>
> None taken, you're quite right, this needs (more) documentation. It
> was open sourced when still in rough form. I'll send a ping when I get
> it cleaned up and 0.05 released. Anyway, here's the basic way I used
> it. Torsten's solution is probably technically more adept, but I
> couldn't do what I needed to using filtering, so I had to write this.
>
> <Location />
> SetHandler modperl
> PerlHeaderParserHandler Apache2::Const::OK
> PerlAccessHandler Apache2::Const::OK
> PerlAuthenHandler Apache2::Const::OK
> PerlAuthzHandler Apache2::Const::OK
> PerlTypeHandler Apache2::Const::OK
> PerlFixupHandler Apache2::Const::OK
> PerlResponseHandler My::Proxy->handler
> </Location>
>
> package My::Proxy;
> use base 'Apache2::Proxy';
>
> sub handler {
> my ($r, $class) = @_;
>
> # examine request to see if it needs to be modified
>
> # if not, pass to Apache2::Proxy
> return $class->SUPER::handler($r);
>
> # else fixup the request as needed.
> }
>
Ok, get it, thanks.
All-in-one, as a substitute for mod_proxy.
I will have a second look now.
Re: custom proxy setup with mod_perl
Posted by Fred Moyer <fr...@redhotpenguin.com>.
On Fri, Nov 23, 2012 at 2:18 PM, André Warnier <aw...@ice-sa.com> wrote:
> Fred Moyer wrote:
>>
>> You might want to take a look at a mod_perl based proxy module I wrote
>> - https://metacpan.org/module/Apache2::Proxy
>>
>> It was used in conjunction with Perlbal and a couple other tricks, but
>> was pretty speedy given the crude nature of how I implemented it.
>
>
> No offense intended, Fred, but without much of a documentation, this is bit
> above my level. I have trouble even understanding where it fits in.
None taken, you're quite right, this needs (more) documentation. It
was open sourced when still in rough form. I'll send a ping when I get
it cleaned up and 0.05 released. Anyway, here's the basic way I used
it. Torsten's solution is probably technically more adept, but I
couldn't do what I needed to using filtering, so I had to write this.
<Location />
SetHandler modperl
PerlHeaderParserHandler Apache2::Const::OK
PerlAccessHandler Apache2::Const::OK
PerlAuthenHandler Apache2::Const::OK
PerlAuthzHandler Apache2::Const::OK
PerlTypeHandler Apache2::Const::OK
PerlFixupHandler Apache2::Const::OK
PerlResponseHandler My::Proxy->handler
</Location>
package My::Proxy;
use base 'Apache2::Proxy';
sub handler {
my ($r, $class) = @_;
# examine request to see if it needs to be modified
# if not, pass to Apache2::Proxy
return $class->SUPER::handler($r);
# else fixup the request as needed.
}
Re: custom proxy setup with mod_perl
Posted by André Warnier <aw...@ice-sa.com>.
Fred Moyer wrote:
> You might want to take a look at a mod_perl based proxy module I wrote
> - https://metacpan.org/module/Apache2::Proxy
>
> It was used in conjunction with Perlbal and a couple other tricks, but
> was pretty speedy given the crude nature of how I implemented it.
No offense intended, Fred, but without much of a documentation, this is bit above my
level. I have trouble even understanding where it fits in.
Re: custom proxy setup with mod_perl
Posted by Fred Moyer <fr...@redhotpenguin.com>.
You might want to take a look at a mod_perl based proxy module I wrote
- https://metacpan.org/module/Apache2::Proxy
It was used in conjunction with Perlbal and a couple other tricks, but
was pretty speedy given the crude nature of how I implemented it.
On Fri, Nov 23, 2012 at 9:39 AM, André Warnier <aw...@ice-sa.com> wrote:
> Hi.
>
> I am trying to solve an unconventional (I think) issue with mod_perl (or
> even without it).
> Environment : Apache 2.2/mod_perl 2 under Linux.
>
> The issue :
> A number of workstations are in a LAN, using a local DNS server under my
> control.
> In the same LAN (192.168.45.0), I have a Linux host running Apache
> 2.2/mod_perl 2, also under my full control (IP 192.168.45.100).
>
> Currently, the LAN workstations access external websites such as (for the
> sake of example) :
> 1) http://www.site-1.com (IP 1.2.3.4)
> 2) http://www.site-2.biz (IP 2.3.4.5)
> 3) http://www.site-3.org (IP 3.4.5.6)
> 4) http://www.site-4.co.uk (IP 4.5.6.7)
> (all these IP's being supposedly real public Internet IP addresses)
>
> In the future, I would like that when the workstations try to access
> websites (2) and (4) above, they access them through my Apache/mod_perl
> host.
> The reason for this is that
> a) I need to authenticate the users
> b) I need to allow some users to access these external servers, and deny
> other users (and for those, I need to return a nice page explaining why)
>
> I already do the authentication/authorization using custom PerlAuth*
> handlers.
> I also know how to write PerlFixupHandler and PerlTransHandler modules, and
> how to "push" other Perl "HTTP cycle" handlers when needed.
>
> My basic scheme is as follows :
> - the DNS server configuration is modified so that when resolving the
> hostnames (2) and (4) above, it returns the IP address of the internal
> Apache host (192.168.45.100).
> When a workstation thus wants to connect to webserver (2) above, in reality
> it connects to the internal Apache host, where I want to perform my mod_perl
> magic.
> - on the Apache host, there is a virtual host configured with
> ServerAlias www.site-2.biz
> ServerAlias www.site-4.co.uk
> so it responds to these requests.
>
> The Apache host has access to the "real" IP addresses of the above external
> webservers.
> (For example, in its own "hosts" file; or it has itself an "uncorrupted" DNS
> server which delivers the original IP addresses).
>
> In the Apache host, I have the following configuration section :
> <Location />
> AuthType MyOwn
> AuthName CheckProxy
> PerlAuthenHandler my:AuthHandler->get_id
> PerlAuthzHandler my:AuthHandler->allow_or_not
> Require valid-user
> PerlFixupHandler ????
> PerlTransHandler ????
> ProxyPass http://(corresponding hostname)/(path and query as received)
> </Location>
>
> Now my questions are : if I do something at the level of the
> PerlFixupHandler or PerlTransHandler,
> 1) is that "early enough" to be before the Apache ProxyPass step ?
> 2) can I set the "(corresponding hostname)" above in such a Perl handler, or
> otherwise manipulate the URI before it gets proxy-ed ?
> 3) do I need this ProxyPass directive in my configuration, or can I just set
> the Apache response handler to be mod_proxy_http, in one of the Perl
> handlers ? and if yes, how ?
>
> I'd be thankful for any answer or tip, even about a solution which does not
> involve mod_perl at all. (But in reality, I do need to do a bit more in my
> handlers than I allude to above).
>
>
>
>
>
>
>
>
>
>
Re: custom proxy setup with mod_perl
Posted by André Warnier <aw...@ice-sa.com>.
Torsten Förtsch wrote:
> On 11/23/2012 06:39 PM, André Warnier wrote:
>> 1) is that "early enough" to be before the Apache ProxyPass step ?
>
> yes, the proxy works as usual in the response phase.
>
>> 2) can I set the "(corresponding hostname)" above in such a Perl
>> handler, or otherwise manipulate the URI before it gets proxy-ed ?
>
> yes
>
>> 3) do I need this ProxyPass directive in my configuration, or can I just
>> set the Apache response handler to be mod_proxy_http, in one of the Perl
>> handlers ? and if yes, how ?
>
> no, the fixup handler can configure the request to be handled by mod_proxy.
>
> # Perhaps 2 is better here, since your server actually acts as
> # reverse proxy. The differences are subtle. Have a look at the code
> # for better understanding.
> $r->proxyreq(1);
> $r->filename("proxy:".$url);
> $r->handler('proxy_server');
>
> That's what I would begin with. $url is then 'http://www.site-...'.
Many thanks. I would not have found this by myself. Of course, now that I know ..
http://perl.apache.org/docs/2.0/api/Apache2/RequestRec.html#C_proxyreq_
but I would not have looked there.
>
> A problem here is perhaps if the user wants to use https.
Yes, that's the next issue :
5) https://www.site-5.edu
You can of
> course fake up a certificate. You perhaps can even have the browser
> accept it without warning. But nevertheless, a user with sufficient
> knowledge can identify the man in the middle.
That last is not really an issue here. The users are (supposed to be) cooperative .
The real context is that the client/company has subscriptions with certain sites, limited
in number of users and nominative. If the user is not registered yet, the message they
receive is to get in touch with the appropriate department, to obtain a subscription.
If they are registered, then they can be passed through to the target transparently.
The reason for being able to manipulate the URI's, is that on some of these sites the
subscriptions are only valid for a part of the site.
Also, I don't necessarily want to do all this heavy-duty stuff for all calls to the
external sites (e.g. not for css, images etc..). That's why I wanted to achieve this with
mod_perl, to retain a maximum of flexibility. Once you start combining a bunch of
criteria on multiple target sites, things get pretty messy with standard Rewrite* and
Proxy* and SetEnvIf..
The browser warning may be an issue because it's ugly from a user point of view, and we
would have to warn them to disregard it. It may even be that they are not allowed to
disregard it, if their corporate IE + policies allow to set this.
In this case, there are 10 sites in total, and one of them is a https:// one. But there
may be more in future.
I'll cross that bridge when I get to it.
>
> See also
>
> http://foertsch.name/ModPerl-Tricks/using-modproxy-as-useragent.shtml
>
> for a different but also unusual usage of mod_proxy.
Now that I read this, I remember seeing that before. But I forgot about it.
Thanks for reminding me.
Re: custom proxy setup with mod_perl
Posted by Torsten Förtsch <to...@gmx.net>.
On 11/23/2012 06:39 PM, André Warnier wrote:
> 1) is that "early enough" to be before the Apache ProxyPass step ?
yes, the proxy works as usual in the response phase.
> 2) can I set the "(corresponding hostname)" above in such a Perl
> handler, or otherwise manipulate the URI before it gets proxy-ed ?
yes
> 3) do I need this ProxyPass directive in my configuration, or can I just
> set the Apache response handler to be mod_proxy_http, in one of the Perl
> handlers ? and if yes, how ?
no, the fixup handler can configure the request to be handled by mod_proxy.
# Perhaps 2 is better here, since your server actually acts as
# reverse proxy. The differences are subtle. Have a look at the code
# for better understanding.
$r->proxyreq(1);
$r->filename("proxy:".$url);
$r->handler('proxy_server');
That's what I would begin with. $url is then 'http://www.site-...'.
A problem here is perhaps if the user wants to use https. You can of
course fake up a certificate. You perhaps can even have the browser
accept it without warning. But nevertheless, a user with sufficient
knowledge can identify the man in the middle.
See also
http://foertsch.name/ModPerl-Tricks/using-modproxy-as-useragent.shtml
for a different but also unusual usage of mod_proxy.
Torsten