Nginx中proxy_set_header Host $http_host配置失效问题求助
Nginx代理后主机名显示异常的原因分析与解决
服务器部署了多个虚拟主机,同时配置了“默认测试站点”default.it用于功能测试。目前除proxy_set_header相关配置外其余功能正常,但请求被代理后显示的是被代理主机名default-portals.it,而非请求的主机名default.it。相关Nginx配置如下:
server { # SRV NAME listen 443 ssl; server_name default.it; large_client_header_buffers 4 16k; # TLS ssl_certificate /etc/ssl/websites/wildcard.it/wildcard.it.crt; ssl_certificate_key /etc/ssl/websites/wildcard.it/wildcard.it.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on; access_log /var/log/nginx/default.it.access.log; error_log /var/log/nginx/default.it.error.log; location / { proxy_pass https://default-portals.it/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host:$server_port; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 900; proxy_ssl_verify off; proxy_ssl_trusted_certificate /etc/ssl/websites/default.it/default.it.ca-bundle; proxy_ssl_verify_depth 2; proxy_ssl_session_reuse on; proxy_ssl_name $proxy_host; } }
原因分析
问题的核心在于proxy_ssl_name $proxy_host;这一配置:
$proxy_host变量对应的是proxy_pass中指定的被代理服务器主机名(即default-portals.it),当Nginx与后端HTTPS服务器建立SSL连接时,这个变量会作为SNI(Server Name Indication)字段的值发送给后端。- 即便配置了
proxy_set_header Host $http_host;传递客户端请求的主机名,但如果后端服务器依赖SNI识别站点,或者同时读取SNI和Host头,就会导致显示的是被代理的主机名而非请求的主机名。
解决方案
将proxy_ssl_name的值替换为客户端请求的主机名变量,与proxy_set_header Host保持一致:
修改后的关键配置片段
location / { proxy_pass https://default-portals.it/; # 可根据需求选择$host或$http_host,$host不含端口,$http_host带客户端请求的端口 proxy_set_header Host $host; # 其他原有配置... # 替换$proxy_host为$host或$http_host,确保SNI与Host头一致 proxy_ssl_name $host; }
- 如果需要保留客户端请求的端口,
proxy_set_header Host和proxy_ssl_name都可以使用$http_host; - 如果只需要主机名(不带端口),使用
$host更稳妥,因为$http_host在客户端未指定端口时可能为空。
内容的提问来源于stack exchange,提问作者Roberto D. Maggi
相关产品推荐
相关产品推荐

