1

I have a NGINX instance (nginx/1.17.7) that acts as a tls passthrough reverse-proxy (not terminating TLS but forwarding raw-tcp connection according to SNI headers).

The main drawback of this configuration is that the upstream servers are unable to get the real client IP address, but they only see the reverse proxy IP as source of any connection.

I am trying to implement PROXY Protocol to overcome this problem with upstream servers capable of understanding it (for example another NGINX server).

It's very easy to implement it if we assume the all the upstream servers will be configured to start accepting inbound PROXY Protocol at the same time.

This configuration works pretty well in that case:

stream {
    map $ssl_preread_server_name $name {
         www.site1.com site1_https;
         www.site2.com site2_https;
         # ...
    }

    upstream site1_https {
        server <site1 internal ip1>:443;
        # ...
    }
    upstream site2_https {
        server <site2 internal ip1>:443;
        # ...
    }
    # ...

    server {
        listen <public ip address>:443
        ssl_preread on;
        proxy_pass $name;

        # This line enable outbound PROXY Protocol to EVERY upstream server!
        proxy_protocol on;
    }
}

However if you want to implement inbound proxy protocol gradually, or you have some upstream servers that are unable to decode PROXY Protocol header, it would be nice to be able to add outbound PROXY Headers only to a subset of the upstream servers.

What I tried so far to achieve this goal is to add another mapped variable for whether proxy_protocol should be set on or not:

stream {
    map $ssl_preread_server_name $name {
        www.site1.com site1_https;
        # ...
    }
    map $name $proxy_protocol_onoff {
        site1_https on;
    }
    # ...
    server {
        # ...
        proxy_pass $name;
        proxy_protocol $proxy_protocol_onoff;
# ...

But I got the following error:

invalid value "$proxy_protocol_onoff" in "proxy_protocol" directive, it must be "on" or "off" in /etc/nginx/nginx.conf:147

Using if directives is not an option because they are not allowed inside server directives. Also defining proxy_protocol on; inside upstream directives is not allowed.

There is any possibility at all to achieve this behavior with NGINX? Or the only way is to switch towards HAProxy or something similar?

2
  • As you have discovered it already, proxy_protocol does not support variable values. Provided that you are using a configuration tool like Ansible to template out your configs, you can simply emit as many server blocks as needed, in other words, for each upstream server, then specify a different value for proxy_protocol, where needed. – Danila Vershinin Apr 24 '20 at 22:29
  • @DanilaVershinin, thank you for your answer. Unfortunately it seems that is not possible to have multiple server blocks listening to the same address within a stream block. (Probably it's feasible inside an http block, but since NGINX is not terminating TLS traffic i can't use it)/ I got the error: duplicate "10.0.2.15:443" address and port pair in /etc/nginx/nginx.conf:152 Also, without terminating TLS traffic, I think I can't use the server_name directive to match the right server instance for each site. – lore20 Apr 25 '20 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.