【问题标题】:How can I retrieve a user's public IP address via Amazon API Gateway + Lambda (node)如何通过 Amazon API Gateway + Lambda(节点)检索用户的公共 IP 地址
【发布时间】:2016-01-08 19:25:03
【问题描述】:

我目前正在编写一个 Node.js lambda 函数,我想在其中记录传入请求者的公共 IP 地址。我整天都在查看 API Gateway 和 Lambda 文档,但没有找到解决方案。

lambda event 对象是否包含可用于提取用户 IP 的请求元数据?

【问题讨论】:

    标签: node.js amazon-web-services aws-lambda aws-api-gateway


    【解决方案1】:

    在 API 网关中,就是价值

    $context.identity.sourceIp
    

    http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference

    您可以通过映射模板将其传递给您的 Lambda。

    【讨论】:

    • 酷。但是,如何在我的 Lambda 函数中引用传递的值?
    • 我尝试过通过映射模板来做,几乎什么都做了,但是还是不行,有没有明确的分步参考或者可以讲讲的例子?
    • 显然,只有在 API 网关中使用“授权方”时,这才是正确的。
    • 在我的例子中,我使用的是 ALB,所以你必须使用 $context.multiValueHeaders.x-forwarded-for 而不是 $context.identity.sourceIP - 你也可以在接受的答案上考虑 Roman 的评论。
    【解决方案2】:

    这是在 Lambda 函数中使用 API Gateway 的 $context.identity.sourceIp 的简单演示。

    API 映射模板:

    {
        "sourceIP" : "$context.identity.sourceIp"
    }
    

    Lambda 函数:

    'use strict';
    console.log('Loading function');
    exports.handler = (event, context, callback) => {
        console.log('SourceIP =', event.identity.sourceIP);
        callback(null, event.identity.sourceIP);
    };
    

    【讨论】:

    • 这太棒了。感谢您提供映射信息 =)
    • 仅供参考:对于代理集成,API 网关将整个请求传递到后端,您无法修改传递行为。 docs.aws.amazon.com/apigateway/latest/developerguide/…
    • 对于 Lambda 代理集成,源 IP 包含在传递给函数的事件中。例如。 event.requestContext.identity.sourceIp
    • 另一个问题是是否也可以获得用户代理?
    • 请注意,如果请求通过代理(在我的例子中是 CloudFront),实际的客户端 ID 将在 X-Forwarded-For 标头中给出。
    【解决方案3】:

    HTTP API 更新

    添加@Elijah 的评论。 HTTP API 的格式为

    event['requestContext']['http']['sourceIp']
    

    编辑

    更好的方法实际上是检查

    event['requestContext']['identity']['sourceIp']
    

    你也可以从同一个对象中获取 User-Agent

    event['requestContext']['identity']['userAgent']
    

    请参阅下面的 Cesar 评论。标头很容易被欺骗,用户可以将X-Forwarded-For 设置为任何内容。 AFAIK 上面的sourceIp 是从 TCP 连接中检索到的。

    原答案

    自 2017 年 9 月起,您可以在 API 网关中创建一个与 Lambda 代理集成的方法,这将使您能够访问

    events['headers']['X-Forwarded-For']
    

    看起来像1.1.1.1,214.25.52.1

    第一个 ip 1.1.1.1 是您用户的公共 ip 地址。

    【讨论】:

    • 如果您使用的是 Lambda 代理集成,这才是真正的答案。比为每个方法添加映射要容易得多。
    • 您的原始答案应该被完全删除! X-Forwarded-For 标头可以被用户欺骗并更改为他们想要的任何内容。
    • @Cesar 的建议是不完整的:X-Forwarded-For 确实可以由客户端根据请求设置,这使得仅在您拥有受信任的代理并且您的代码只信任最右边的值。见developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…
    • 必须信任代理才能在客户端传入的任何值的右侧插入额外的 IP,甚至覆盖该值。
    • 如果您使用的是新的 HTTP API 而不是 REST API,它将是 event['requestContext']['http']['sourceIp'] 而不是 event['requestContext']['身份']['sourceIp']
    【解决方案4】:
    exports.handler = (event, context) => {
        console.log('ip:', event.headers["x-forwarded-for"].split(",")[0].trim());
    };
    

    【讨论】:

      【解决方案5】:

      API 网关应该已经在 http 标头 X-Forwarded-For 中包含远程 IP,因此您可以:

      // Lambda handler function
      module.exports.handlerFunc = async (event, context) => {
          // `X-Forwarded-For` should return a comma-delimited list of IPs, first one being remote IP:
          // X-Forwarded-For: '<remote IP>, <cloudfront/API gateway IP>, ...'
          const remoteIp = event.headers['X-Forwarded-For'].split(', ')[0]
          // If you want to see more info available in event and context, add following, deploy and check CloudWatch log:
          // console.log(event, context)
      }
      

      【讨论】:

      • 请注意,这适用于大多数用例,但不要将其用于允许/拒绝对机密内容的访问,因为如果恶意用户获取了 X-Forwarded-For 标头,则可能会被欺骗处理您的 API Gateway URL 并直接在那里发出请求,跳过 CloudFront 或您在其路径上放置的任何内容。见:sjoerdlangkemper.nl/2017/03/01/…
      猜你喜欢
      • 2021-08-11
      • 2019-07-09
      • 2018-07-15
      • 2014-04-25
      • 2019-12-04
      • 1970-01-01
      • 2021-08-18
      • 2011-10-11
      • 2019-10-20
      相关资源
      最近更新 更多