1. 问题
部署的ceph对象存储使用了兼容Amazon s3的RGW网关,通过Amazon S3访问对象存储。为了网关的高可用和负载均衡,在RWG网关前面加了一层nginx代理转发。
发现加了nginx之后V4签名会报错The request signature we calculated does not match the signature you provided. Check your key and signing method.
,但是V2签名不会报错。
经过打开工程debug日志、nginx日志、RGW网关日志,最后发现是RGW网关接受到的请求和客户端发出去的请求的头参数Host
不一样。
2. 原因
在nginx中转发http请求有个参数设置proxy_set_header Host xxx;
,当我们使用以下形式的nginx转发时:
upstream backend {
server 127.0.0.1:8080;
}
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:9000;
}
}
server {
listen 80;
location / {
proxy_pass backend;
}
}
nginx默认使用的是基于IP的转发,这样服务端接收到的请求头参数Host
就变成了127.0.0.1:8080
和127.0.0.1:9000
。
3. 解决办法
-
proxy_set_header Host xxx;
xxx就是你需要的host,保持与客户端发出的请求一致。
这样做有个问题,你并不知道客户端用的是域名访问还是ip:port访问。 -
proxy_set_header Host $host;
客户端请求头包含Host参数时为Host字段的值(不含端口),在请求头未携带Host时为虚拟主机的主域名。
但是用$host是不含有端口信息,无论客户端请求头Host中是否含有端口。 -
proxy_set_header Host $http_host;
把客户端请求头转发到服务端;如果客户端请求头中没有携带这个头部,那么传递到服务端的请求也不含这个头参数。
比较特殊的是如果使用的是80端口,这里也不会出现80端口。
以上客户端指的是nginx前一级,服务端指的是nginx后一级,如果有多级代理,都需要设置;也可以不是nginx,是例如Haproxy等等。
网友评论