Forum: NGINX Incorrect redirect protocol when behind a reverse proxy

E92146e270ae11efac6405927b6439af?d=identicon&s=25 Glenn Maynard (Guest)
on 2013-07-25 00:03
(Received via mailing list)
Our nginx server is running on Heroku, which proxies SSL.  This mostly
works fine, but nginx has one problem with it: since it thinks the
protocol
is http, any redirects (such as trailing-slash redirects) go to http
instead of https.

The usual fix for this is X-Forwarded-Proto, but nginx doesn't support
that
yet, and I haven't found any way to configure it, eg. a configuration
directive to override the protocol.  Nginx seems to decide whether
redirects should go to http or https entirely based on whether the
connection has an SSL context associated (ngx_http_header_filter), so it
doesn't look like there's any way to affect this in configuration.

Is there any workaround?
34011bc56457235a2caa5ed1d4a29f3c?d=identicon&s=25 Jonathan Matthews (Guest)
on 2013-07-25 12:11
(Received via mailing list)
On 24 Jul 2013 23:03, "Glenn Maynard" <glenn@zewt.org> wrote:
>
> Our nginx server is running on Heroku, which proxies SSL.

What does this mean? Do you see SSL traffic, or do you mean heroku
terminates the ssl leaving you with http connections only?

> This mostly works fine, but nginx has one problem with it: since it
thinks the protocol is http, any redirects (such as trailing-slash
redirects) go to http instead of https.

Show us some config that generates these redirects.

> The usual fix for this is X-Forwarded-Proto, but nginx doesn't support
that yet

That doesn't make sense to me. What is there to support? You can just
write
your redirect directives using X-F-P instead of hard coding the scheme.

> and I haven't found any way to configure it, eg. a configuration
directive to override the protocol.
> Nginx seems to decide whether redirects should go to http or https
entirely based on whether the connection has an SSL context associated
(ngx_http_header_filter), so it doesn't look like there's any way to
affect
this in configuration.

You've gone into the code far too early IMHO. There's usually a way to
change nginx's behaviour in config.
>
> Is there any workaround?

Do all requests have x-f-p? 100%? Then just change your redirects to
reference it.

J
E92146e270ae11efac6405927b6439af?d=identicon&s=25 Glenn Maynard (Guest)
on 2013-07-25 16:43
(Received via mailing list)
On Thu, Jul 25, 2013 at 5:11 AM, Jonathan Matthews
<contact@jpluscplusm.com>wrote:

>  What does this mean? Do you see SSL traffic, or do you mean heroku
> terminates the ssl leaving you with http connections only?
>
Heroku handles SSL, and nginx sees only HTTP traffic.

> write your redirect directives using X-F-P instead of hard coding the
> scheme.
>
I'm not hardcoding anything.  Nginx is generating its own redirects.
The
case I'm seeing currently is ngx_http_static_module redirecting to add a
trailing slashes to URLs.


> You've gone into the code far too early IMHO. There's usually a way to
> change nginx's behaviour in config.
>
I've gone into the code precisely to find out how to do that, since the
documentation wasn't helping.  I was surprised to discover that the
protocol seems to be hardcoded.

> Do all requests have x-f-p? 100%? Then just change your redirects to
> reference it.
>
I don't have any redirects.  Nginx is doing this on its own.
34011bc56457235a2caa5ed1d4a29f3c?d=identicon&s=25 Jonathan Matthews (Guest)
on 2013-07-25 17:53
(Received via mailing list)
On 25 Jul 2013 15:43, "Glenn Maynard" <glenn@zewt.org> wrote:
>
> On Thu, Jul 25, 2013 at 5:11 AM, Jonathan Matthews <
contact@jpluscplusm.com> wrote:
>>
>> What does this mean? Do you see SSL traffic, or do you mean heroku
terminates the ssl leaving you with http connections only?
>
> Heroku handles SSL, and nginx sees only HTTP traffic.
>>
>> > This mostly works fine, but nginx has one problem with it: since it
thinks the protocol is http, any redirects (such as trailing-slash
redirects) go to http instead of https.
>>
>> Show us some config that generates these redirects.
>>
>> > The usual fix for this is X-Forwarded-Proto, but nginx doesn't support
that yet
>>
>> That doesn't make sense to me. What is there to support? You can just
write your redirect directives using X-F-P instead of hard coding the
scheme.
>
> I'm not hardcoding anything.  Nginx is generating its own redirects.  The
case I'm seeing currently is ngx_http_static_module redirecting to add a
trailing slashes to URLs

On my phone's browser, searching for that module name doesn't bring me
anything useful I'm afraid. Are you just serving local files off disk?

I bet you have redirects configured somewhere, or a backend is
generating
them ;-)

Please post your entire config.

>> You've gone into the code far too early IMHO. There's usually a way to
change nginx's behaviour in config.
>
> I've gone into the code precisely to find out how to do that, since the
documentation wasn't helping.  I was surprised to discover that the
protocol seems to be hardcoded.
>>
>> Do all requests have x-f-p? 100%? Then just change your redirects to
reference it.
>
> I don't have any redirects.  Nginx is doing this on its own.

In response to what class of request? What's common across them?

J
E92146e270ae11efac6405927b6439af?d=identicon&s=25 Glenn Maynard (Guest)
on 2013-07-25 18:15
(Received via mailing list)
On Thu, Jul 25, 2013 at 10:53 AM, Jonathan Matthews
<contact@jpluscplusm.com
> wrote:

> On my phone's browser, searching for that module name doesn't bring me
> anything useful I'm afraid. Are you just serving local files off disk?
>
src/http/modules/ngx_http_static_module.c.  This is where the
trailing-slash redirects originate.

>  I bet you have redirects configured somewhere, or a backend is
> generating them ;-)
>
> Please post your entire config.
>
I don't.  It happens with a minimal configuration.

events { }
http {
        server {
                listen 10000;
                root "data";
        }
}

mkdir -p data/test/, and then accessing "http://localhost:10000/test"
redirects to "http://localhost:10000/test/".
34011bc56457235a2caa5ed1d4a29f3c?d=identicon&s=25 Jonathan Matthews (Guest)
on 2013-07-25 20:42
(Received via mailing list)
On 25 July 2013 17:14, Glenn Maynard <glenn@zewt.org> wrote:
>> them ;-)
>         }
> }
>
> mkdir -p data/test/, and then accessing "http://localhost:10000/test"
> redirects to "http://localhost:10000/test/".

I've just got to a box and can ACK that. I can make that stop with a
correctly configured try_files, which I would always choose to have
set up, myself. That may not be a solution for you however.

Here's a way I've just tested (on 1.4.2) that forces the
trailing-slash redirects to incorporate a random HTTP header ("foo",
here) as their scheme:

# include your boilerplate as per previous email
location / {
  location ~ "^(.*)[^/]$" {
    rewrite ^ $http_foo://$http_host$uri/ permanent;
  }
}

Or, supposing you have certain URIs which *can* end in
not-a-trailing-slash: (also tested on 1.4.2)

location / {
  if (-d $document_root$uri) {
    rewrite ^ $http_foo://$http_host$uri/ permanent;
  }
}

I suppose the question is then: what *other* classes of automatic
redirects do you find yourself hitting, and can you deterministically
isolate their URIs using either a location{} or if{}, so that you can
pre-empt the auto redirect in order to incorporate the
X-forwarded-proto header?

HTH,
J
--
Jonathan Matthews
Oxford, London, UK
http://www.jpluscplusm.com/contact.html
E92146e270ae11efac6405927b6439af?d=identicon&s=25 Glenn Maynard (Guest)
on 2013-07-30 23:26
(Received via mailing list)
On Thu, Jul 25, 2013 at 1:41 PM, Jonathan Matthews
<contact@jpluscplusm.com>wrote:

>   location ~ "^(.*)[^/]$" {
>   }
> }
>
>

> I suppose the question is then: what *other* classes of automatic
> redirects do you find yourself hitting, and can you deterministically
> isolate their URIs using either a location{} or if{}, so that you can
> pre-empt the auto redirect in order to incorporate the
> X-forwarded-proto header?
>

Thanks, I'll give these approaches a try.  I don't know where else this
might happen, though.  Hopefully at some point I'll be able to say
something like "override_protocol $http_x_forwarded_proto;" to tell
nginx
which protocol it's really receiving a request on, since SSL
"offloading"
is fairly common these days
(http://aws.amazon.com/elasticloadbalancing/,
etc).
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.