一般来说,我们的服务都不会直接接受外部的请求,而会将服务部署在接入层之后。这样做可以实现多台机器的负载均衡和服务的平滑发布,保证高可用。
在这个场景下,我们无法直接获取到真实用户请求的连接,从而无法确认用户的真实 IP、请求协议,甚至请求的域名。为了解决这个问题,框架默认提供了一系列配置项,以便开发者基于与接入层的约定(事实标准)来使应用层获取真实的用户请求信息。
开启前置代理模式
通过设置 config.proxy = true
可以开启前置代理模式:
// config/config.default.js
exports.proxy = true;
注意,开启此模式后,应用就默认处于反向代理之后。它会支持通过解析约定的请求头来获取用户真实的 IP、协议和域名。如果你的服务未部署在反向代理之后,请不要开启此配置,以防被恶意用户伪造请求 IP 等信息。
config.ipHeaders
开启 proxy 配置后,应用会解析 X-Forwarded-For 请求头来获取客户端的真实 IP。如果你的前置代理通过其他请求头传递该信息,可以通过 config.ipHeaders
来配置。此配置项支持配置多个头(逗号分开)。
// config/config.default.js
exports.ipHeaders = 'X-Real-Ip, X-Forwarded-For';
config.maxIpsCount
X-Forwarded-For
等传递 IP 的头,通常格式是:
X-Forwarded-For: client, proxy1, proxy2
通常我们可以取第一个作为请求的真实 IP。但是,如果有恶意用户在请求中传递了 X-Forwarded-For
参数,以伪造其位置在反向代理之后,将会导致获取的 X-Forwarded-For
值变得不准确。这可能被用来伪造请求 IP 地址,绕过应用层的某些 IP 限制。
X-Forwarded-For: fake, client, proxy1, proxy2
为避免此问题,我们可以通过 config.maxIpsCount
来限制前置代理的数量。这样在获取请求真实 IP 地址时,会忽略掉用户所传递的伪造 IP 地址。例如,如果我们将应用部署在一个统一的接入层后(如阿里云 SLB),可以将此参数配置为 1
。这样用户就无法通过 X-Forwarded-For
请求头伪造 IP 地址了。
// config/config.default.js
exports.maxIpsCount = 1;
此配置项与 koa 提供的 options.maxIpsCount
作用一致。
config.protocolHeaders
开启 proxy 配置后,应用会解析 X-Forwarded-Proto 请求头来获取客户端的真实访问协议。如果你的前置代理通过其他请求头传递该信息,可以通过 config.protocolHeaders
来配置。此配置项支持配置多个头(逗号分开)。
// config/config.default.js
exports.protocolHeaders = 'X-Real-Proto, X-Forwarded-Proto';
config.hostHeaders
开启 proxy 配置后,应用通常会直接读取 host
来获取请求的域名,因为大多数反向代理不会修改这个值。但有时,一些反向代理会通过 X-Forwarded-Host 传递客户端的真实访问域名。你可以在 config.hostHeaders
中配置此信息,配置项支持多个头(逗号分开)。
// config/config.default.js
exports.hostHeaders = 'X-Forwarded-Host';