You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by John Siracusa <si...@mindspring.com> on 2002/11/14 18:45:52 UTC

How can I tell if a request was proxy-passed form an SSL server?

Assume I have a front-end (non-mod_perl) proxy server that supports both
HTTP and HTTPS.  I want to know, from within my Perl code on the back-end
(HTTP-only) mod_perl server, if the current request was ProxyPass-ed to me
based on an original HTTP or HTTPS request from the user.

There doesn't appear to be a way to add headers to the proxy request on a
per-virtual-host basis using mod_proxy, and I don't see any other headers
that I can use to distinguish between an HTTP or HTTPS front-end server.
Any ideas?

-John


Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by Carolyn Hicks <ca...@bannoy.net>.
On Thu, Nov 14, 2002 at 12:45:52PM -0500, John Siracusa wrote:
> Assume I have a front-end (non-mod_perl) proxy server that supports both
> HTTP and HTTPS.  I want to know, from within my Perl code on the back-end
> (HTTP-only) mod_perl server, if the current request was ProxyPass-ed to me
> based on an original HTTP or HTTPS request from the user.
> 
> There doesn't appear to be a way to add headers to the proxy request on a
> per-virtual-host basis using mod_proxy, and I don't see any other headers
> that I can use to distinguish between an HTTP or HTTPS front-end server.
> Any ideas?

If you can proxy-pass HTTP and HTTPS requests to different ports on the
backend server, you just need to check which port the backend is listening
on to tell if the request came through SSL or not.

http://perl.apache.org/docs/1.0/guide/config.html#Knowing_the_proxy_pass_ed_Connection_Type

-carolyn

Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by John Siracusa <si...@mindspring.com>.
On 11/14/02 5:48 PM, Marcin Kasperski wrote:
> What about the simple manual solution: frontend server proxies
> /some/url to /http/some/url on backend for HTTP and to /https/some/url
> on backend for HTTPS. Or something similar...

On 11/14/02 6:56 PM, Carolyn Hicks wrote:
> If you can proxy-pass HTTP and HTTPS requests to different ports on the
> backend server, you just need to check which port the backend is listening
> on to tell if the request came through SSL or not.

Both of those would work, but aren't quite what I'm looking for.  IMO, there
should be some way to do what I ended up doing with my little C apache
module, namely to add X-Whatever header(s) to a proxy-passed request.  I'd
imagine something like:

    Proxy(Add|Set|Unset)Header <header> <value>

Maybe apache 2.0 has something like that, but I'm still using 1.3.x for
now...

-John


Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by Marcin Kasperski <Ma...@acn.waw.pl>.
John Siracusa <si...@mindspring.com> writes:

> Assume I have a front-end (non-mod_perl) proxy server that supports both
> HTTP and HTTPS.  I want to know, from within my Perl code on the back-end
> (HTTP-only) mod_perl server, if the current request was ProxyPass-ed to me
> based on an original HTTP or HTTPS request from the user.
> 
> There doesn't appear to be a way to add headers to the proxy request on a
> per-virtual-host basis using mod_proxy, and I don't see any other headers
> that I can use to distinguish between an HTTP or HTTPS front-end server.
> Any ideas?

What about the simple manual solution: frontend server proxies 
/some/url to /http/some/url on backend for HTTP and to /https/some/url 
on backend for HTTPS. Or something similar...

-- 
( Marcin Kasperski   | Communication takes place between people, documents   )
( http://www.mk.w.pl |                are secondary. (Booch)                 )
(----------------------------------------------------------------------------)
( Moje prywatne strony: http://www.kasperski.prv.pl                          )

Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by Rob Nagler <na...@bivio.biz>.
John Siracusa writes:
> and that does the trick.  The full code for the module is at the end of this
> message.  But I still think this is an ugly hack, and I'd like to be able to
> do this using "standard" apache modules or config parameters...

Our hack is to forward 443 to port 81 on the middle tier:

    <VirtualHost 1.2.3.4:443>
        ...
        ProxyVia on
	...
        RewriteRule ^(.*) http://middle.tier.host:81$1 [proxy]

We set a value (is_secure => 1) on our internal request object when it
is initialized if the incoming port is 81.  We also set remote_ip with:

    $r->connection->remote_ip($1)
	if ($r->header_in('x-forwarded-for') || '') =~ /((?:\d+\.){3}\d+)/;

This makes the log entries useful.  There might be an easier way to do
this.

Rob



Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by John Siracusa <si...@mindspring.com>.
On 11/14/02 2:39 PM, Randy Kobes wrote:
> On Thu, 14 Nov 2002, John Siracusa wrote:
>> I tried turning on ProxyVia, but all I got was the HTTP
>> protocol version ("1.1") and the host ("www.foo.com"), but no
>> scheme string (e.g. "http://" or "https://")
> 
> Were these from requests you know were made using https?

Yep, but I still just get the version number.

> My reading of the Via header was that the protocol name is optional
> only if it is HTTP, implying that if it's not given, you can
> assume it's HTTP.

That doesn't appear to be the case with mod_proxy in apache 1.3.27.

I ended up having to make a trivial C apache module (using the old
mod_proxy_add_forward.c as a basis) to set my own header.  Of course, first
I had to find out if the request is SSL.  I figured I'd look for the env var
that mod_ssl sets:

    https = getenv("HTTPS");
    
    if(https)
      ap_table_set(r->headers_in, "X-Forwarded-For-SSL", "yes");

But that didn't work. (I also tried many of the SSL_* env vars.)  So then I
tried looking where mod_ssl actually puts its HTTPS env var, in the
subprocess_env structure:

    table *e = r->subprocess_env;

    if(ap_table_get(e, "HTTPS"))
      ap_table_set(r->headers_in, "X-Forwarded-For-SSL", "yes");

But that didn't work either.  I forced my trivial module to the end of the
module chain just to make sure mod_ssl got a chance to set its var(s) first,
but that didn't help.

Finally, I found something that did work:

    method = ap_ctx_get(r->ctx, "ap::http::method");

    if(method)
      ap_table_set(r->headers_in, "X-Forwarded-For-Method", method);

Apparently, this is only set by mod_ssl if method is "https".  If it is
HTTP, this is not set at all.  Anyway, I just check for this on the mod_perl
side with:

    if($r->header_in('X-Forwarded-For-Method') eq 'https') { ... }

and that does the trick.  The full code for the module is at the end of this
message.  But I still think this is an ugly hack, and I'd like to be able to
do this using "standard" apache modules or config parameters...

-John

---

#include "httpd.h"
#include "http_config.h"
#include "http_core.h"

module MODULE_VAR_EXPORT proxy_add_ssl_module;

static int add_ssl_header(request_rec *r)
{
  const char *method;

  if(r->proxyreq == PROXY_PASS)
  {
    method = ap_ctx_get(r->ctx, "ap::http::method");

    if(method)
      ap_table_set(r->headers_in, "X-Forwarded-For-Method", method);

    return OK;
  }

  return DECLINED;
}

module MODULE_VAR_EXPORT proxy_add_ssl_module = {
    STANDARD_MODULE_STUFF,
    NULL,                       /* initializer */
    NULL,                       /* dir config creater */
    NULL,                       /* dir merger --- default is to override */
    NULL,                       /* server config */
    NULL,                       /* merge server configs */
    NULL,                       /* command table */
    NULL,                       /* handlers */
    NULL,                       /* filename translation */
    NULL,                       /* check_user_id */
    NULL,                       /* check auth */
    NULL,                       /* check access */
    NULL,                       /* type_checker */
    add_ssl_header,             /* fixups */
    NULL,                       /* logger */
    NULL,                       /* header parser */
    NULL,                       /* child_init */
    NULL,                       /* child_exit */
    NULL                        /* post read-request */
};


Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by Randy Kobes <ra...@theoryx5.uwinnipeg.ca>.
On Thu, 14 Nov 2002, John Siracusa wrote:

> On 11/14/02 2:12 PM, Randy Kobes wrote:
> > 
> > If your front-end proxy server has 'ProxyVia on' enabled, a Via
> > header would get sent.  According to rfc2068, the protocol name
> > should, and port may, be supplied in this header if these aren't
> > the defaults - would this be enough to enable your mod_perl
> > server to distinguish between an HTTP or HTTPS request?
> 
> I tried turning on ProxyVia, but all I got was the HTTP
> protocol version ("1.1") and the host ("www.foo.com"), but no
> scheme string (e.g. "http://" or "https://")

Were these from requests you know were made using https? My
reading of the Via header was that the protocol name is optional
only if it is HTTP, implying that if it's not given, you can
assume it's HTTP. Perhaps less useful, if the port is not given,
it may be assumed that the default port is used.

-- 
best regards,
randy



Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by John Siracusa <si...@mindspring.com>.
On 11/14/02 2:12 PM, Randy Kobes wrote:
> On Thu, 14 Nov 2002, John Siracusa wrote:
>> Assume I have a front-end (non-mod_perl) proxy server that
>> supports both HTTP and HTTPS.  I want to know, from within my
>> Perl code on the back-end (HTTP-only) mod_perl server, if the
>> current request was ProxyPass-ed to me based on an original
>> HTTP or HTTPS request from the user.
>> 
>> There doesn't appear to be a way to add headers to the proxy
>> request on a per-virtual-host basis using mod_proxy, and I
>> don't see any other headers that I can use to distinguish
>> between an HTTP or HTTPS front-end server. Any ideas?
> 
> If your front-end proxy server has 'ProxyVia on' enabled, a Via
> header would get sent.  According to rfc2068, the protocol name
> should, and port may, be supplied in this header if these aren't
> the defaults - would this be enough to enable your mod_perl
> server to distinguish between an HTTP or HTTPS request?

I tried turning on ProxyVia, but all I got was the HTTP protocol version
("1.1") and the host ("www.foo.com"), but no scheme string (e.g. "http://"
or "https://")

-John


Re: How can I tell if a request was proxy-passed form an SSL server?

Posted by Randy Kobes <ra...@theoryx5.uwinnipeg.ca>.
On Thu, 14 Nov 2002, John Siracusa wrote:

> Assume I have a front-end (non-mod_perl) proxy server that
> supports both HTTP and HTTPS.  I want to know, from within my
> Perl code on the back-end (HTTP-only) mod_perl server, if the
> current request was ProxyPass-ed to me based on an original
> HTTP or HTTPS request from the user.
> 
> There doesn't appear to be a way to add headers to the proxy
> request on a per-virtual-host basis using mod_proxy, and I
> don't see any other headers that I can use to distinguish
> between an HTTP or HTTPS front-end server. Any ideas?

If your front-end proxy server has 'ProxyVia on' enabled, a Via
header would get sent.  According to rfc2068, the protocol name
should, and port may, be supplied in this header if these aren't
the defaults - would this be enough to enable your mod_perl
server to distinguish between an HTTP or HTTPS request?

-- 
best regards,
randy kobes