Skip to content

[第三期] determine the user ip from the request #23

@panjizhi

Description

@panjizhi

需求描述

这里定义为获取终端 "用户" ip, 考虑到实际场景需要 bypass proxy / LB

基本要求

  • 以 fastify 的plugin 形式产出组件
  • 编写 unit test,实现代码 100% 全覆盖

单元测试的编写参考:@fe/byted-consul

思路

  1. 直连或透明代理由 TCP 协议获取

  2. proxy / LB 从 http 协议(header)获取

  3. 一些标准化的云服务 / LB 服务, 从 header 中标准定义获取

策略梳理

  1. 优先 header 关键字判定, 命中则为 proxy / LB

    1. 检查最标准无歧义的 header: X-Client-IP

      一般国外云服务商(Amazon / Heroku)遵循的业界标准

    2. 检查记录代理信息的 header: x-forwarded-forx-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;

    3. 检查一些常见云服务商约定的 header:

      1. cf-connecting-ip(Cloudflare)
      2. true-client-ip(Akamai)
      3. x-cluster-client-ip(一些 LB 服务商标准)
    4. 检查 x-forwarded-for 的常见变体:

      1. x-forwarded
      2. forwarded-for
      3. forwarded
  2. 取 TCP 协议中的 remoteAddress (只有两种情况下可以获取 client ip, 与 client 直连或是经过透明代理)

    透明代理的 nginx 配置: proxy_bind $remote_addr transparent;

    按 node net 模块 实现, 依次检查:

    1. req.connection.remoteAddress
    2. req.socket.remoteAddress
    3. req.connection.socket.remoteAddress
    4. req.info.remoteAddress
  3. 兼容一些 serverless 服务商, 从 req 附加 context 获取

    1. req.requestContext.identity.sourceIp (AWS Lambda)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions