Opened 4 years ago

Closed 4 years ago

#1936 closed defect (invalid)

'set_real_ip_from' in location section is not processed before REWRITE_PHASE

Reported by: p01arbear@… Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.17.x
Keywords: realip_module Cc:
uname -a:
nginx -V: 1.17.8

Description (last modified by p01arbear@…)

For the confuguration

    server {
        listen 1024 proxy_protocol;
        location / {
            real_ip_header proxy_protocol;
            set_real_ip_from 0.0.0.0/0;
            return 200 remote_addr=$remote_addr;
        }       
    } 

response on request

echo -en "PROXY TCP4 4.4.4.4 5.5.5.5 1234 80\r\nGET / \n\n" | nc -q-1 0 1024

is

remote_addr=127.0.0.1

It is wrong address. The same in the access log.

Moving real_ip* directives into the server section or removing 'return' provide the correct result.

    server {
        listen 1024 proxy_protocol;
        real_ip_header proxy_protocol;
        set_real_ip_from 0.0.0.0/0;
        location / {
            return 200 remote_addr=$remote_addr;
        }       
    } 
remote_addr=4.4.4.4

This happens due to missing call of ngx_http_realip_handler() with config of a location on PREACCESS_PHASE.
Because 'return' works off on REWRITE_PHASE.

Change History (5)

comment:1 by p01arbear@…, 4 years ago

Description: modified (diff)

comment:2 by Maxim Dounin, 4 years ago

Resolution: invalid
Status: newclosed

The realip module, if specified in a particular location, starts working only if a particular location is chosen. The rewrite module (and the return directive as a part of it) is designed to conditionally select configurations, and therefore a configuration is only considered to be chosen after processing by the rewrite module. In your particular example request processing is stopped by the return directive of the rewrite module before this happens.

If you want the realip module to apply to all requests, including ones where a configuration wasn't yet chosen, and to all phases of request processing after reading the request, including processing by the rewrite module, configure the realip module at the server level.

comment:3 by p01arbear@…, 4 years ago

If something satisfies the way is was supposed to be written, it doesn't get right because of this.
NGINX has an extremely controversial behavior here.
It is a modules conflict or a flaw of architecture/documentation (inconsistency of phase handlers planning).

The realip module, if specified in a particular location, starts working only if a particular location is chosen

Particular location is chosen, because 'return' directive inside it does execute.
And this is always last chosen location, because there are no redirection is specified for it.

configuration is only considered to be chosen after processing by the rewrite module

The presented case above have simple unambiguous location config.
But it is processed incorrectly due to flaw of consistent execution of rewrite module's directives with directives from other modules placed in the same location.
And there is no right place for a correct processing it now: nor on the same phase (there are no such phase), nor on the different phases (there are no appropriate phases).

Obviously, it is incorrect to declare an ability to use 'realip' directives in the location if they have conflicts with location handling directives.

In your particular example request processing is stopped by the return directive of the rewrite module before this happens.

Exactly. And this ticket insists that it is bug of nginx, which is possible to fix by changing the way it treats with locations.

Last edited 4 years ago by p01arbear@… (previous) (diff)

comment:4 by p01arbear@…, 4 years ago

Resolution: invalid
Status: closedreopened

It would be right to change the Summary of the ticket to

Wrong processing of rewrite-module's directives inside location leads to incorrect processing of 'set_real_ip_from' there

Last edited 4 years ago by p01arbear@… (previous) (diff)

comment:5 by Maxim Dounin, 4 years ago

Resolution: invalid
Status: reopenedclosed

As already explained above, the behaviour you observe is in line with the current design. While it may be counter-intuitive, it is not a bug.

The realip module, if used only in a particular location, changes the IP address once the location is finally chosen, and this happens after the rewrite module instructions are executed, because these instructions is a logical part of the process of choosing a location. As such, rewrite module instructions will see the original IP address, not yet changed by the realip module.

If you think you can came up with a better design, which will result in more intuitive processing, don't hesitate to submit a patch.

Note: See TracTickets for help on using tickets.