【问题标题】:Node.js How to create an API endpoint only accessible to SNS topic?Node.js 如何创建一个只有 SNS 主题才能访问的 API 端点?
【发布时间】:2016-12-11 12:43:35
【问题描述】:

我想从 SNS 向托管在 Node.js 服务器上的公共 API 端点发送 HTTP 请求。但是,我想将该 API 配置为仅接受来自该 SNS 主题的 POST 请求,不接受其他请求。我可以在 SNS 消息中插入一个令牌,但我不控制 SNS 消息。它来自 SES,以防退回电子邮件。是否可以查看请求的域,并且仅在来自受信任域(在本例中为 AWS)时才允许?

【问题讨论】:

  • 您可以查看给定 HTTP 请求来自哪个 IP 地址。如果您可以建立一个 IP 地址范围来代表来自 SNS 的请求的可能地址,那么您可以根据该范围进行过滤。
  • 传入请求不会告诉您它来自哪个域。您可以对 IP 地址进行反向查找,以尝试确定谁拥有该 IP 地址。
  • 感谢您的建议,但我想我可能需要比这更具体的东西。因为任何人都可以通过从 AWS EC2 服务器发送 curl 请求来利用这一点。我应该看看如何限制它只能从 SNS 服务访问。因为只有在 HTTP 端点订阅了主题时才能发送 SNS 通知
  • 现在我在想,我可以采取另一种方法,即 SNS 将消息发送到 SQS 队列,然后我可以更改 API 以定期从 SQS 读取。我不需要它是实时的,所以这种方法应该可以工作
  • 实际上,您可以过滤掉来自 EC2 实例的请求。采用 JSON 格式的官方 AWS IP 范围,它包括 EC2 IP 范围:ip-ranges.amazonaws.com/ip-ranges.json

标签: node.js amazon-web-services


【解决方案1】:

您不能将端点的可访问性限制为“仅 SNS”——即使您知道 SNS 的 IP 地址范围,其价值也有限,因为任何人都可能使用 SNS。这将是一种虚假的安全感。

但是,SNS 消息的设计方式是无需通过 IP 地址限制端点的可访问性。无论如何,你应该这样做。

您应该验证 Amazon SNS 发送的通知、订阅确认或取消订阅确认消息的真实性。使用 Amazon SNS 消息中包含的信息,您的终端节点可以重新创建要签名的字符串和签名,以便您可以通过将您从消息内容重新创建的签名与 Amazon SNS 随消息发送的签名相匹配来验证消息的内容.

http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.verify.signature.html

首先,HTTP 请求标头x-amz-sns-topic-arn 标识主题。如果这不是您期望的主题,请不要处理该消息。如果此值与消息本身中的TopicArn 不一致,则不要处理该消息。

接下来,消息正文包含SigningCertURL。这是您的代码获取 SNS 用于签署消息的证书的 URL。如果此 URL 的 scheme 不是 https 且主机名不是 sns.[region].amazonaws.com,则不要下载证书,也不要处理消息。

否则,从提供的 URL 获取证书,并将其缓存在本地内存或磁盘上,这样您就不必在处理每条消息时都获取它(您通常会看到重复使用相同的证书)。确保您的用户代理未配置为不根据信任库和请求主机名验证目标服务器的证书。在此配置中,您可以确保证书本身确实来自 SNS,因为您的用户代理不会与具有不受信任证书的系统协商 SSL,并且您已验证主机名是由 AWS 控制的。

接下来,生成消息的规范哈希,并根据消息随附的Signature 对其进行验证,如上面的链接中所述。

如果消息确实来自 SNS,签名将正确验证,并且应该处理消息。否则不应处理。

【讨论】:

  • 请阅读您的答案。实际上,我最终在查询参数中为我们订阅 SNS 的 HTTP 端点添加了一个令牌。但是你的方法更健壮,我将把我的实现改为这个。感谢您的详尽解释
猜你喜欢
  • 2017-08-14
  • 2013-06-17
  • 2014-02-23
  • 2021-12-31
  • 1970-01-01
  • 2016-12-14
  • 2021-08-16
  • 2021-08-18
  • 2020-08-03
相关资源
最近更新 更多