需求描述
这里定义为获取终端 "用户" ip, 考虑到实际场景需要 bypass proxy / LB
基本要求
- 以 fastify 的
plugin 形式产出组件
- 编写 unit test,实现代码 100% 全覆盖
单元测试的编写参考:@fe/byted-consul
思路
-
直连或透明代理由 TCP 协议获取
-
proxy / LB 从 http 协议(header)获取
-
一些标准化的云服务 / LB 服务, 从 header 中标准定义获取
策略梳理
-
优先 header 关键字判定, 命中则为 proxy / LB
-
检查最标准无歧义的 header: X-Client-IP
一般国外云服务商(Amazon / Heroku)遵循的业界标准
-
检查记录代理信息的 header: x-forwarded-for 和 x-real-ip
都为约定速成的 header, x-forwarded-for 目前应用最广泛, x-real-ip 是早期 fastcgi 等默认的 header
node 服务最常见的 proxy 和 LB 默认配置, 属性值为 [client_IP, proxy1_IP, proxy2_IP, ...]
如果是可控的 proxy 配置, 例如公司 TLB(nginx), 确保: location 配置包含 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 或 proxy_set_header X-Real-IP $remote_addr;
-
检查一些常见云服务商约定的 header:
cf-connecting-ip(Cloudflare)
true-client-ip(Akamai)
x-cluster-client-ip(一些 LB 服务商标准)
-
检查 x-forwarded-for 的常见变体:
x-forwarded
forwarded-for
forwarded
-
取 TCP 协议中的 remoteAddress (只有两种情况下可以获取 client ip, 与 client 直连或是经过透明代理)
透明代理的 nginx 配置: proxy_bind $remote_addr transparent;
按 node net 模块 实现, 依次检查:
req.connection.remoteAddress
req.socket.remoteAddress
req.connection.socket.remoteAddress
req.info.remoteAddress
-
兼容一些 serverless 服务商, 从 req 附加 context 获取
req.requestContext.identity.sourceIp (AWS Lambda)
需求描述
这里定义为获取终端 "用户" ip, 考虑到实际场景需要 bypass proxy / LB
基本要求
plugin形式产出组件思路
直连或透明代理由 TCP 协议获取
proxy / LB 从 http 协议(header)获取
一些标准化的云服务 / LB 服务, 从 header 中标准定义获取
策略梳理
优先 header 关键字判定, 命中则为 proxy / LB
检查最标准无歧义的 header:
X-Client-IP检查记录代理信息的 header:
x-forwarded-for和x-real-ip检查一些常见云服务商约定的 header:
cf-connecting-ip(Cloudflare)true-client-ip(Akamai)x-cluster-client-ip(一些 LB 服务商标准)检查
x-forwarded-for的常见变体:x-forwardedforwarded-forforwarded取 TCP 协议中的
remoteAddress(只有两种情况下可以获取 client ip, 与 client 直连或是经过透明代理)req.connection.remoteAddressreq.socket.remoteAddressreq.connection.socket.remoteAddressreq.info.remoteAddress兼容一些 serverless 服务商, 从
req附加 context 获取req.requestContext.identity.sourceIp(AWS Lambda)