OPPO 设备空间绑定 NAS 授权失败排查记录
背景
OPPO 设备空间可以绑定 NAS,直接备份相册和浏览文件。我试了几次都提示"密码错误",但 NAS 官方 App 登录没问题。
网络结构:光猫 → 路由器拨号,下面两台机器。.100 是 DMZ 网关跑 Nginx,.43 是 NAS。域名解析到 .100,外网流量经过网关转发到 NAS。
第一次折腾
抓包看了下,设备空间发的是:
POST https://xxx:5667/og.oauth2.v1.Oauth2Service/Authorize
走的 5667 端口,路径是 gRPC 格式。NAS App 走的是 8888 端口,普通 HTTP。
我 Nginx 只配了 8888,5667 没管。于是加了个 server block,SSL 终止后代理到 NAS 的 5666:
server {
listen 5667 ssl;
location / {
proxy_pass http://192.168.x.43:5666;
proxy_http_version 1.1;
}
}
结果还是不行,依然"密码错误"。超时、buffer、header 都试了一遍,没用。
当时忙,干脆路由器直接把 5667 映射到 .43 的 5667,设备空间立马能用了。这事就搁下了。
隔了段时间再搞
路由器直通虽然能用,但 SSL 证书得 NAS 自己管,不统一。于是重新排查。
先看了下后端协议:
$ curl -I http://192.168.x.43:5666
→ HTTP/1.1 200 OK
$ curl -I https://192.168.x.43:5667
→ HTTP/2 200
5666 只有 HTTP/1.1,5667 才有 HTTP/2。设备空间走 gRPC,gRPC 依赖 HTTP/2。之前用 proxy_pass 到 5666 相当于把 gRPC 降级成 HTTP/1.1 了,gRPC 的状态码(trailers)在 HTTP/1.1 里没地方放,直接丢了。后端返回的认证失败信息传不回客户端,界面上就显示"密码错误"。
最终方案
Nginx 有 grpc_pass 指令,专门代理 gRPC,保持 HTTP/2 协议。
server {
listen 5667 ssl;
http2 on;
server_name nas.mydomain.xxx;
include snippets/ssl_cert.conf;
location ~ ^/(og|grpc)\. {
grpc_pass grpcs://192.168.x.43:5667;
grpc_ssl_verify off;
grpc_ssl_name nas.mydomain.xxx;
grpc_read_timeout 3600s;
grpc_send_timeout 3600s;
}
location / {
proxy_pass http://192.168.x.43:5666;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_request_buffering off;
}
}
gRPC 路径走 grpc_pass 到 NAS 的 5667(HTTPS+HTTP/2),其他走普通 proxy_pass 到 5666(HTTP)。部署后设备空间绑定、备份、浏览都正常。
总结
问题的链条很简单:设备空间用 gRPC → gRPC 需要 HTTP/2 → Nginx 代理到 5666 变成 HTTP/1.1 → gRPC 状态码丢失 → 客户端收到不了认证结果 → 显示"密码错误"。
如果 NAS 的 5666 端口也支持 HTTP/2,就不会有这个坑。或者早期排查时能注意到两个端口的协议差异,也能少走弯路。