nginx反向代理,丢失了部分请求头里面的信息,没有把客户端请求的信息全部传回到服务器,服务器读取header里面信息缺失,应该怎么配置?
在 Nginx 反向代理配置中丢失请求头信息通常是由于未正确传递头字段导致的。以下是完整的解决方案和配置指南:
核心配置项(必须添加)
在 location
块中添加以下指令:
location / {
proxy_pass http://backend_server;
# 基础头信息传递
proxy_set_header Host $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-Proto $scheme;
# 关键配置:传递所有原始请求头
proxy_pass_request_headers on;
# 传递自定义头(如 Authorization)
proxy_set_header Authorization $http_authorization;
proxy_pass_request_headers on;
}
完整解决方案
1. 基础头信息配置
server {
listen 80;
server_name proxy.example.com;
location / {
proxy_pass http://backend-server;
# 必须传递的核心头
proxy_set_header Host $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-Proto $scheme;
# 确保传递所有头字段
proxy_pass_request_headers on;
}
}
2. 处理自定义请求头
location / {
# 传递特定自定义头
proxy_set_header Your-Custom-Header $http_your_custom_header;
# 处理带下划线的头(Nginx 默认会丢弃)
underscores_in_headers on; # 在 http 或 server 块添加
}
3. 完整配置示例
http {
# 允许带下划线的请求头
underscores_in_headers on;
server {
listen 80;
server_name proxy.example.com;
location /api/ {
proxy_pass http://backend-server;
# 标准头
proxy_set_header Host $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-Proto $scheme;
# 自定义头
proxy_set_header API-Key $http_api_key;
proxy_set_header Authorization $http_authorization;
# 重要:确保请求体也被传递
proxy_pass_request_headers on;
proxy_pass_request_body on;
# 超时设置(可选)
proxy_connect_timeout 60s;
proxy_read_timeout 90s;
}
}
}
常见问题解决
1. 下划线头丢失问题
# 在 http 块添加(影响全局)
http {
underscores_in_headers on;
}
# 或在 server 块添加(局部生效)
server {
underscores_in_headers on;
}
2. 特殊头处理(如 Authorization)
location / {
# 显式传递 Authorization 头
proxy_set_header Authorization $http_authorization;
}
3. 验证头传递
使用 curl 测试:
curl -H "Custom-Header: test-value" http://proxy-server
在后端查看日志确认头是否收到
调试技巧
检查 Nginx 日志
log_format headers '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" "$http_x_custom_header"'; access_log /var/log/nginx/access.log headers;
检查后端收到的头
- Node.js:
console.log(req.headers)
- PHP:
print_r($_SERVER)
- Python:
print(request.headers)
- Node.js:
使用 tcpdump 抓包
tcpdump -i eth0 -A -s 0 'port 80 and host backend-server'
高级配置
传递所有头(不推荐)
location / {
# 谨慎使用:可能传递敏感信息
proxy_pass_request_headers on;
# 或者显式设置每个头
proxy_set_header "$header" "$http_header";
}
删除特定头
location / {
# 删除不需要的头
proxy_set_header Some-Header "";
}
重要提示:
- 修改配置后执行
nginx -t
测试配置- 重载配置
nginx -s reload
- 清除浏览器缓存和CDN缓存再测试
- 检查防火墙是否过滤了特定头字段
通过以上配置,99% 的请求头丢失问题都能解决。如仍有问题,建议使用 tcpdump 抓包分析请求头是否真正到达 Nginx 服务器。
完整配置文件示例:
# user nobody;
# worker_processes 4;
# error_log logs/error.log;
# error_log logs/error.log notice;
# error_log logs/error.log info;
# pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
underscores_in_headers on;
gzip on;
server {
listen 80;
server_name localhost;
location / {
proxy_set_header Host $host:$server_port;
proxy_pass_header Server;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_pass_request_headers on;
proxy_pass http://127.0.0.1:8080;
}
#error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 443 ssl;
server_name localhost;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl on;
ssl_certificate ./ssl_key/server.crt;
ssl_certificate_key ./ssl_key/server.key;
add_header Content-Security-Policy "upgrade-insecure-requests";
# 接口代理
location / {
proxy_set_header Host $host:$server_port;
proxy_pass_header Server;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-Port $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_pass_request_headers on;
proxy_pass http://127.0.0.1:8080;
}
}
}