Is it possible to configure Nginx to accept requests both with and without proxy protocol to the same URL?

Solution 1:

Without using a different server block, the only way to do this is with different listen directives. This means the server running nginx must have different IP addresses for connecting to the server from the external proxy and from the internal server farm.

For example, you might have an internal network 10.87.239.0/24 for your internal apps, and the server running nginx is on 10.87.239.3. Then you have an external network 10.87.238.0/24 which your external proxy server uses to reach nginx, and the server has address 10.87.238.3. In this case you can configure nginx as:

server {
    # PROXY protocol connections
    listen 10.87.238.3:443 ssl http2 proxy_protocol;
    set_real_ip_from 10.87.238.2;  # The address(es) of the proxies
    real_ip_header proxy_protocol;

    # Direct connections
    listen 10.87.239.3:443 ssl http2;
    listen [::]:443 ssl http2;

    # everything else for this block
}

On a related note, you should have already deployed IPv6 within your organization, even without global IPv6 connectivity. You can use that for your internal communications if you haven't got a separate internal IPv4 network.

Solution 2:

The proxy protocol specification at Proxy protocol explicitly calls out the risk, of running a listener which attempts to guess if Proxy protocol is used on the same address and port.

The receiver MUST be configured to only receive the protocol described in this
specification and MUST not try to guess whether the protocol header is present
or not. This means that the protocol explicitly prevents port sharing between
public and private access. Otherwise it would open a major security breach by
allowing untrusted parties to spoof their connection addresses. The receiver
SHOULD ensure proper access filtering so that only trusted proxies are allowed
to use this protocol.

So attempting to accept requests with both with and without Proxy protocol will be a risk.