proxy_pass redirect for address without trailing slash disregards Host port

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

proxy_pass redirect for address without trailing slash disregards Host port

Nuno Gonçalves
I am using proxy_pass and I'm facing a issue which I'm not sure it's a bug.

It is in regard to the behaviour specified by the documentation [1]:

If a location is defined by a prefix string that ends with the slash
character, and requests are processed by one of proxy_pass,
fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass,
then the special processing is performed. In response to a request
with URI equal to this string, but without the trailing slash, a
permanent redirect with the code 301 will be returned to the requested
URI with the slash appended. If this is not desired, an exact match of
the URI and location could be defined like this:

Consider that there is a proxy pass for location /abcd/ { proxy_pass
... } for a server listening on port 80.

If I make a request for /abcd with Host header "example.com:8080",
then I receive a 301 for example.com/abcd/ and not for the expected
example.com:8080/abcd/.

In fact NGINX is considering the Host header domain part, but
disregarding the port part.

I believe this is a bug.

Thanks,
Nuno

[1] http://nginx.org/en/docs/http/ngx_http_core_module.html
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: proxy_pass redirect for address without trailing slash disregards Host port

Jeffrey 'jf' Lim
The host is defined by the server, surely, and not by what the client tells the server it is? And you tell the server what host it is by the server_name directive (https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name).

-jf

On Sat, 24 Aug 2019, 01:39 Nuno Gonçalves, <[hidden email]> wrote:
I am using proxy_pass and I'm facing a issue which I'm not sure it's a bug.

It is in regard to the behaviour specified by the documentation [1]:

If a location is defined by a prefix string that ends with the slash
character, and requests are processed by one of proxy_pass,
fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass,
then the special processing is performed. In response to a request
with URI equal to this string, but without the trailing slash, a
permanent redirect with the code 301 will be returned to the requested
URI with the slash appended. If this is not desired, an exact match of
the URI and location could be defined like this:

Consider that there is a proxy pass for location /abcd/ { proxy_pass
... } for a server listening on port 80.

If I make a request for /abcd with Host header "example.com:8080",
then I receive a 301 for example.com/abcd/ and not for the expected
example.com:8080/abcd/.

In fact NGINX is considering the Host header domain part, but
disregarding the port part.

I believe this is a bug.

Thanks,
Nuno

[1] http://nginx.org/en/docs/http/ngx_http_core_module.html
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: proxy_pass redirect for address without trailing slash disregards Host port

Nuno Gonçalves
On Sat, Aug 24, 2019 at 8:24 AM Jeffrey 'jf' Lim <[hidden email]> wrote:
>
> The host is defined by the server, surely, and not by what the client tells the server it is? And you tell the server what host it is by the server_name directive (https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name).

That's not correct, the server is taking the Host domain part from the
client Host header. It's just not taking the port part.

This inconsistency is why I believe it's a bug.

For my exact case it was enough to set "absolute_redirect off;", since
only the absolute redirect is affected by this issue.

Thanks,
Nuno

>
> -jf
>
> On Sat, 24 Aug 2019, 01:39 Nuno Gonçalves, <[hidden email]> wrote:
>>
>> I am using proxy_pass and I'm facing a issue which I'm not sure it's a bug.
>>
>> It is in regard to the behaviour specified by the documentation [1]:
>>
>> If a location is defined by a prefix string that ends with the slash
>> character, and requests are processed by one of proxy_pass,
>> fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass,
>> then the special processing is performed. In response to a request
>> with URI equal to this string, but without the trailing slash, a
>> permanent redirect with the code 301 will be returned to the requested
>> URI with the slash appended. If this is not desired, an exact match of
>> the URI and location could be defined like this:
>>
>> Consider that there is a proxy pass for location /abcd/ { proxy_pass
>> ... } for a server listening on port 80.
>>
>> If I make a request for /abcd with Host header "example.com:8080",
>> then I receive a 301 for example.com/abcd/ and not for the expected
>> example.com:8080/abcd/.
>>
>> In fact NGINX is considering the Host header domain part, but
>> disregarding the port part.
>>
>> I believe this is a bug.
>>
>> Thanks,
>> Nuno
>>
>> [1] http://nginx.org/en/docs/http/ngx_http_core_module.html
>> _______________________________________________
>> nginx mailing list
>> [hidden email]
>> http://mailman.nginx.org/mailman/listinfo/nginx
>
> _______________________________________________
> nginx mailing list
> [hidden email]
> http://mailman.nginx.org/mailman/listinfo/nginx
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: proxy_pass redirect for address without trailing slash disregards Host port

Jeffrey 'jf' Lim
On Sat, Aug 24, 2019 at 5:18 PM Nuno Gonçalves <[hidden email]> wrote:

>
> On Sat, Aug 24, 2019 at 8:24 AM Jeffrey 'jf' Lim <[hidden email]> wrote:
> >
> > The host is defined by the server, surely, and not by what the client tells the server it is? And you tell the server what host it is by the server_name directive (https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name).
>
> That's not correct, the server is taking the Host domain part from the
> client Host header. It's just not taking the port part.
>
> This inconsistency is why I believe it's a bug.
>
> For my exact case it was enough to set "absolute_redirect off;", since
> only the absolute redirect is affected by this issue.
>

ok this is interesting. I see "port_in_redirect" as well
(https://nginx.org/en/docs/http/ngx_http_core_module.html#port_in_redirect)
as well, but from my testing (you can also verify this in the source)
the port here would refer to the port *as specified by the server*
(specifically the listen directive), and NOT as specified by the
client in the Host header. The exception to 'port_in_redirect on'
would be if the server is listening at the standard 80; you will not
see ':80' in your redirect (i.e. no "Location:
http://example.com:80/abcd/")

When you say that "only the absolute redirect is affected by this
issue", I assume you mean that absolute redirects are affected
*because* they specify the hostname (and indirectly, the port), vs
relative redirects don't?

-jf


> Thanks,
> Nuno
>
> >
> > -jf
> >
> > On Sat, 24 Aug 2019, 01:39 Nuno Gonçalves, <[hidden email]> wrote:
> >>
> >> I am using proxy_pass and I'm facing a issue which I'm not sure it's a bug.
> >>
> >> It is in regard to the behaviour specified by the documentation [1]:
> >>
> >> If a location is defined by a prefix string that ends with the slash
> >> character, and requests are processed by one of proxy_pass,
> >> fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass,
> >> then the special processing is performed. In response to a request
> >> with URI equal to this string, but without the trailing slash, a
> >> permanent redirect with the code 301 will be returned to the requested
> >> URI with the slash appended. If this is not desired, an exact match of
> >> the URI and location could be defined like this:
> >>
> >> Consider that there is a proxy pass for location /abcd/ { proxy_pass
> >> ... } for a server listening on port 80.
> >>
> >> If I make a request for /abcd with Host header "example.com:8080",
> >> then I receive a 301 for example.com/abcd/ and not for the expected
> >> example.com:8080/abcd/.
> >>
> >> In fact NGINX is considering the Host header domain part, but
> >> disregarding the port part.
> >>
> >> I believe this is a bug.
> >>
> >> Thanks,
> >> Nuno
> >>
> >> [1] http://nginx.org/en/docs/http/ngx_http_core_module.html
> >> _______________________________________________
> >> nginx mailing list
> >> [hidden email]
> >> http://mailman.nginx.org/mailman/listinfo/nginx
> >
> > _______________________________________________
> > nginx mailing list
> > [hidden email]
> > http://mailman.nginx.org/mailman/listinfo/nginx
> _______________________________________________
> nginx mailing list
> [hidden email]
> http://mailman.nginx.org/mailman/listinfo/nginx
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: proxy_pass redirect for address without trailing slash disregards Host port

Nuno Gonçalves
On Sat, Aug 24, 2019 at 3:33 PM Jeffrey 'jf' Lim <[hidden email]> wrote:
> When you say that "only the absolute redirect is affected by this
> issue", I assume you mean that absolute redirects are affected
> *because* they specify the hostname (and indirectly, the port), vs
> relative redirects don't?

Yes.
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: proxy_pass redirect for address without trailing slash disregards Host port

Jeffrey 'jf' Lim
In reply to this post by Jeffrey 'jf' Lim
On Sat, Aug 24, 2019 at 9:32 PM Jeffrey 'jf' Lim <[hidden email]> wrote:

>
> On Sat, Aug 24, 2019 at 5:18 PM Nuno Gonçalves <[hidden email]> wrote:
> >
> > On Sat, Aug 24, 2019 at 8:24 AM Jeffrey 'jf' Lim <[hidden email]> wrote:
> > >
> > > The host is defined by the server, surely, and not by what the client tells the server it is? And you tell the server what host it is by the server_name directive (https://nginx.org/en/docs/http/ngx_http_core_module.html#server_name).
> >
> > That's not correct, the server is taking the Host domain part from the
> > client Host header. It's just not taking the port part.
> >
> > This inconsistency is why I believe it's a bug.
> >
> > For my exact case it was enough to set "absolute_redirect off;", since
> > only the absolute redirect is affected by this issue.
> >
>
> ok this is interesting. I see "port_in_redirect" as well
> (https://nginx.org/en/docs/http/ngx_http_core_module.html#port_in_redirect)
> as well, but from my testing (you can also verify this in the source)
> the port here would refer to the port *as specified by the server*
> (specifically the listen directive), and NOT as specified by the
> client in the Host header. The exception to 'port_in_redirect on'
> would be if the server is listening at the standard 80; you will not
> see ':80' in your redirect (i.e. no "Location:
> http://example.com:80/abcd/")
>

Sorry; actually browsing the source, and to be more specific: if SSL
*and* port 443, ':443' is not specified as well (makes sense!). If
http *and* port 80, ':80' is similarly not specified in the Location
(https://trac.nginx.org/nginx/browser/nginx/src/http/ngx_http_header_filter_module.c#L354).

You can also see from the code just above that that the port in the
Location (if any, as mentioned) is taken from the actual connection of
the server (which would be the actual port that the server took this
request at, as opposed to the port that the client is reporting).

Is this a bug? well I would say that this will only have an effect
when you have nginx behind a proxy (in your example, listening at
:8080), as opposed to hitting nginx directly with your client. I
imagine that the code was written from the perspective that you should
be hitting nginx directly (I'll leave Igor or somebody from the nginx
team to have the final word on this). While I see no security risks
redirecting based on the port that a client gives, I'm not so sure I
welcome this. But feel free to propose a directive if you want, I
guess.

-jf


> When you say that "only the absolute redirect is affected by this
> issue", I assume you mean that absolute redirects are affected
> *because* they specify the hostname (and indirectly, the port), vs
> relative redirects don't?
>
> -jf
>
>
> > Thanks,
> > Nuno
> >
> > >
> > > -jf
> > >
> > > On Sat, 24 Aug 2019, 01:39 Nuno Gonçalves, <[hidden email]> wrote:
> > >>
> > >> I am using proxy_pass and I'm facing a issue which I'm not sure it's a bug.
> > >>
> > >> It is in regard to the behaviour specified by the documentation [1]:
> > >>
> > >> If a location is defined by a prefix string that ends with the slash
> > >> character, and requests are processed by one of proxy_pass,
> > >> fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass,
> > >> then the special processing is performed. In response to a request
> > >> with URI equal to this string, but without the trailing slash, a
> > >> permanent redirect with the code 301 will be returned to the requested
> > >> URI with the slash appended. If this is not desired, an exact match of
> > >> the URI and location could be defined like this:
> > >>
> > >> Consider that there is a proxy pass for location /abcd/ { proxy_pass
> > >> ... } for a server listening on port 80.
> > >>
> > >> If I make a request for /abcd with Host header "example.com:8080",
> > >> then I receive a 301 for example.com/abcd/ and not for the expected
> > >> example.com:8080/abcd/.
> > >>
> > >> In fact NGINX is considering the Host header domain part, but
> > >> disregarding the port part.
> > >>
> > >> I believe this is a bug.
> > >>
> > >> Thanks,
> > >> Nuno
> > >>
> > >> [1] http://nginx.org/en/docs/http/ngx_http_core_module.html
> > >> _______________________________________________
> > >> nginx mailing list
> > >> [hidden email]
> > >> http://mailman.nginx.org/mailman/listinfo/nginx
> > >
> > > _______________________________________________
> > > nginx mailing list
> > > [hidden email]
> > > http://mailman.nginx.org/mailman/listinfo/nginx
> > _______________________________________________
> > nginx mailing list
> > [hidden email]
> > http://mailman.nginx.org/mailman/listinfo/nginx
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

Re: proxy_pass redirect for address without trailing slash disregards Host port

Francis Daly
In reply to this post by Nuno Gonçalves
On Sat, Aug 24, 2019 at 11:17:34AM +0200, Nuno Gonçalves wrote:

Hi there,

> That's not correct, the server is taking the Host domain part from the
> client Host header. It's just not taking the port part.
>
> This inconsistency is why I believe it's a bug.

Before "absolute_redirect", I would have called it a bug too.

Now I just consider it "a feature".

I think that nginx has never used the port from the Host header (or from
the request line, if present) in its redirects.

I think that it might be useful for nginx to be able to use that -- as in
"a redirect could optionally use exactly the host:port provided in the
string from the request that nginx used to choose the server{}" -- but
I guess that no-one who cared enough about it provided a justification
and a patch.

And now, "absolute_redirect off;" probably makes it unnecessary.


If you know that you want to use exactly one "unusual" port in the url,
I think that it is possible to fake it using server_name and the various
*_in_redirect directives. But that is not a general solution.

Cheers,

        f
--
Francis Daly        [hidden email]
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx