Egg.js+nginx多层反向代理问题

Posted by Run-dream Blog on November 20, 2020

背景

公司安全要求对外开放的站点必须为Cookies设置Secure属性,而

标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,因此可以预防 man-in-the-middle 攻击者的攻击。

同时,业务的https请求路径如下:

User-Agent —[https]—> haproxy(公司级接入) —[http]—> nginx(业务级接入) —[http]—> nodejs(后端服务接入)

解决方案

egg config.proxy属性

根据Issues,修改项目配置

config.proxy = true;
config.cookies = {
  secure: true
};

本地nginx测试通过。发上测试服后,发现所有请求返回500错误

Cannot send secure cookie over unencrypted connection

查看egg-cookie的实现,发现ctx.secure 仍然是 false, 服务拿到的protocol仍然是http. 查看业务的nginx配置,发现关于转发的部分如下:

location  ^~ /api/ {
  proxy_set_header X-Forwarded-Proto $scheme;
}

而查看nginx日志发现,业务拿到的scheme是http, 导致服务最后拿到的也是http。 发现测试服比本地多了一层nginx代理, 修改配置

location  ^~ /api/ {
  proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}

后一切正常

注意事项

之所以需要这么改是因为实际的网络路径会存在多层代理,比如我们的https层其实只建立在用户到公司网关上。在最外层的nginx上已经设置

 proxy_set_header X-Forwarded-Proto $scheme;

而nginx每一层获取到的scheme是指到这一层到底是用的http还是https协议。