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 20:28:06 UTC

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

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 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