如何在Nginx的stream块中条件式启用proxy_protocol功能?
Nginx stream块条件启用proxy_protocol的实现方案
核心原因
proxy_protocol 属于Nginx stream代理模块的静态配置指令,不支持传入动态变量作为参数,因此你尝试通过map赋值变量的写法无法生效,这是官方预设的功能限制。
可行实现方案
我们可以通过两层内部转发的方式规避这个限制:外层server监听业务端口做域名匹配,将需要开启/关闭proxy_protocol的流量分别转发到两个内部回环server,两个内部server分别静态配置proxy_protocol的开关即可。
修正后的完整配置
error_log logs/error.log; events { } stream { # 保留原有域名与真实后端的映射规则 map $ssl_preread_server_name $server { default unix:/var/run/nginx.sock; include /home/user/allow_url_list; } # 新增map:根据域名匹配对应的内部中转server map $ssl_preread_server_name $internal_proxy { # 特定域名走关闭proxy_protocol的内部server facebook.com 127.0.0.1:18001; # 其余域名走开启proxy_protocol的内部server default 127.0.0.1:18000; } # 外层业务server:仅负责端口监听+域名匹配转发 server { listen 8443 ; ssl_preread on; # 转发到内部中转server proxy_pass $internal_proxy; } # 内部中转server1:开启proxy_protocol server { listen 127.0.0.1:18000; resolver 8.8.8.8 ipv6=off; proxy_pass $server; proxy_protocol on; } # 内部中转server2:关闭proxy_protocol server { listen 127.0.0.1:18001; resolver 8.8.8.8 ipv6=off; proxy_pass $server; proxy_protocol off; } } 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; } } }
配置说明
- 内部中转server仅监听回环地址,不会对外暴露,性能损耗极低
- 所有域名与真实后端的映射规则无需修改,仅新增流量分发逻辑即可
- 如果需要扩展更多域名的proxy_protocol开关规则,仅需要修改
$internal_proxy对应的map规则即可 - 如果你使用的是Nginx Plus商业版,原生支持
proxy_protocol传入变量,无需中转配置,直接使用你原来的写法即可生效
内容的提问来源于stack exchange,提问作者Jarvis
相关产品推荐
相关产品推荐

