How to set the proxy_protocol to 'on' in a conditional manner in nginx?
Asked Answered
C

2

6

Any one familiar with nginx? I am trying to enable proxy_protocol in a conditional manner in a stream block ie for certain endpoints I want the proxy protocol header to be added. For others I dont want to add it. Looking at the documentation there is no way for proxy_protocol to take a variable (Tried the map directive) Any suggestions on how to achieve this? Added my nginx conf here. http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_protocol

This is the problematic piece proxy_protocol $proxy_state;

   map $ssl_preread_server_name $proxy_state{
        default on;
        facebook.com off;
    }
    server {
        listen 8443 ;
        resolver 8.8.8.8 ipv6=off;        
        proxy_pass $server;
        proxy_protocol $proxy_state;
        ssl_preread on;

    }

The following is the complete config

error_log logs/error.log;

events {
}


stream {

    map $ssl_preread_server_name $server { 
        # default 127.0.0.1:8080;
        default unix:/var/run/nginx.sock;
        include /home/user/allow_url_list;

    } 
    map $ssl_preread_server_name $proxy_state{
        default on;
        facebook.com off;
    }
    server {
        listen 8443 ;
        resolver 8.8.8.8 ipv6=off;        
        proxy_pass $server;
        proxy_protocol $proxy_state;
        ssl_preread on;
        
    }
}

http {
    server {
        listen 8080 ssl;
        listen 80;
        listen unix:/var/run/nginx.sock ssl proxy_protocol;
        set_real_ip_from unix:;
        real_ip_header proxy_protocol;
        ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
        ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
        include /home/conf/ssl-params.conf;
        location / {
            resolver 8.8.8.8;
            proxy_pass https://$host$request_uri;
        }
       
    }
    
}
Celestinecelestite answered 7/9, 2021 at 0:10 Comment(0)
E
0

I have a similar question to yours. In my situation, I need to proxy both frps service and a website on the same port, 443. The former uses a custom first byte in the TLS handshake, which makes it difficult to proxy via the HTTP block. Additionally, I need to identify the source IP of connections to my website to implement per-IP rate limiting.

To meet these requirements, I use the following configuration in the stream block:

map $ssl_preread_server_name $name_https {
    frps.example.com frps_https;
    default nginx_https;
}

upstream frps_https {
    server 127.0.0.1:3211;
}

# A wrapper to the FRPS connection to absorb pp packet after handshake (I guess)
server {
    listen 3211 proxy_protocol; 
    proxy_pass 127.0.0.1:7000;
}

upstream nginx_https {
    server 127.0.0.1:8443;
}

server {
    listen 443 reuseport;
    listen [::]:443 reuseport;
    proxy_pass $name_https;
    proxy_protocol on;
    ssl_preread on;
}

To be honest, I'm not an expert in nginx, but this configuration works magically. What it does is enable the proxy_protocol by default and then "disable" it for upstreams that don't require it.

In your situation, you may try the following configuration (untested):

# events ...

stream {
    map $ssl_preread_server_name $proxy_server {
        facebook.com 127.0.0.1:9443;
        default 127.0.0.1:10443;
    }

    map $ssl_preread_server_name $server {
        default unix:/var/run/nginx.sock;
        include /home/user/allow_url_list;
    }

    server {
        listen 9443 proxy_protocol;
        proxy_pass $server;
        ssl_preread on;
    }

    server {
        listen 10443 proxy_protocol;
        proxy_pass $server;
        proxy_protocol on;
        ssl_preread on;
    }

    server {
        listen 8443;
        proxy_pass $proxy_server;
        resolver 8.8.8.8 ipv6=off;
        proxy_protocol on;
        ssl_preread on;
    }
}

# http ...
Edgeways answered 20/8, 2024 at 1:22 Comment(0)
B
-1

You can split it into 2 servers. you can try if it works. Proxy protocol might cause problems.

map $ssl_preread_server_name $internalport {
     facebook.com 10443;
     default 8443;
  }

server {
       listen 8443 ;
       resolver 8.8.8.8 ipv6=off;        
       proxy_pass $server;
       proxy_protocol on;
       ssl_preread on;
   }

server {
       listen 10443 ;
       resolver 8.8.8.8 ipv6=off;        
       proxy_pass $server;
       proxy_protocol off;
       ssl_preread on;

   }
Bobker answered 21/9, 2021 at 16:0 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.