【问题标题】:Secure connection between 2 servers两台服务器之间的安全连接
【发布时间】:2020-09-08 14:56:48
【问题描述】:

我想要一些面向用户的服务器,比如服务器 A。对于某些任务,服务器 A 应该在服务器 B 上提交一个作业请求。当服务器 B 完成后,它应该将结果写入数据库或者进行调用在服务器 A 上,让服务器 A 处理结果(现在不太确定这部分)。

问题是: 如何安全地连接服务器 A 和服务器 B?

  • 在服务器 B 的端点上,我只想允许来自服务器 A 的调用。
  • 在服务器 A 上,我希望某些端点仅可用于服务器 B(可能在某些时候其他工作机器服务器 C、D.. 等)。

我只是找不到合适的词来谷歌搜索。我想这有一些非常明显的流行语,但是谷歌搜索“两台服务器之间的安全连接”并没有产生我想要的。

我对它的一般名称感兴趣,但为了完整起见:

  • 面向用户的服务器将使用 php
  • 作业机器将是一些节点应用程序

我自己的想法(但我不知道如何准确实现它)类似于我通过 ssh 连接到某个服务器时,我只是将我的 pub-key 添加到服务器。所以它应该是这样的:将服务器 A 的公钥存储在服务器 B 上,反之亦然。然后确保只能对服务器 B 进行经过身份验证的调用。

一个完整的答案会很好,但实际上我已经很高兴得到一个指向正确方向的指针,关于我应该在谷歌上搜索什么,或者可能是关于 SO 的另一个问题。

【问题讨论】:

    标签: php node.js security server microservices


    【解决方案1】:

    您正在寻找的技术词是“身份验证”,这是确定一方就是他们所说的那个人的过程。与之密切相关的是“授权”,即确定是否允许一方做某事的过程。

    对于这个问题,标准的身份验证技术适用,与他们对用户的方式非常相似。生成一个长的、随机的身份验证令牌并将其存储在服务器 B 上。使用 HTTPS 从服务器 B 连接到服务器 A,并传递身份验证令牌。一种流行的方法是使用承载身份验证。添加标题:

    Authorization: Bearer {access_token}
    

    在服务器 A 上,验证令牌并在授权时执行请求。

    这只是实现 API 密钥的一种特定方式。您也可以将访问令牌(API 密钥)直接放入请求中。应该是一样的。

    如果您有容器化或虚拟化设置,这些密钥通常存储在环境变量中。我不建议将它们直接存储在代码中(有太多的小错误可能导致代码可见)。

    有更复杂的方法来做同样的事情,如果你已经有一个好的系统来验证用户,你也可以为服务器 B 创建一个“服务帐户”并使用你的正常身份验证方案。但是不记名令牌是一种很好、简单的方法来处理机器-机器身份验证,而无需创建虚假帐户。

    请注意,所有方法都要求您能够保护服务器 B。任何可以访问服务器 B 的人都可以窃取令牌并冒充服务器。缓解这种情况通常需要专门的硬件(例如 HSM),并且超出了大多数系统的需求。

    虽然有点复杂,但另一种常见的技术是签署您的请求。签名的优点是您永远不必通过网络发送您的身份验证令牌(即使使用 HTTPS),您只需将私钥存储在一个地方(服务器 B)。这意味着即使是服务器 A 也不能像承载身份验证那样伪装成服务器 B。我经常为此使用 JWS(JSON Web 签名),但如果您没有一个很好的库来为您处理它,那么它会相当复杂。在没有 JWS 的情况下签名很难做到正确,因为您必须非常小心地签署所有重要的内容,并且很容易忽略部分请求(例如标头)。如果您走这条路,您可能需要安全专家来检查一下。

    正如 Mikah 所指出的,从 OAuth2 升级而来的是 OAuth2,但我通常不建议将其用于您控制一切且实体不多的点对点身份验证。这只是很多复杂性而没有什么好处。 OAuth2 的重点是允许对复杂的身份验证环境进行集中管理。如果您没有这些问题,复杂性往往会降低而不是提高安全性。

    【讨论】:

    • 嘿!感谢您的回答:+1。您能否向我指出一些资源,我可以在其中阅读更多有关如何“正确”执行此操作的信息,或者讨论一些替代方案?使用 Auth-Server 怎么样?矫枉过正? P.s.:我会再等一会儿,看看是否有其他答案出现。如果没有,我可能会接受这个。
    • 这是一篇关于 Open ID Connect (OIDC) 的不错的文章 - 您可能正在寻找经常被过度使用的客户端凭证流。 medium.com/@robert.broeckelmann/…
    • 更新了更多信息。我不知道有什么好的文件可以涵盖所有这些。我主要是从多年在 InfoSec 工作和审查基础架构设计中学到的。
    • 其实我在考虑 OAuth2,但正如你已经提到的,我认为它是矫枉过正的。这就是为什么我首先想到了问题中提到的一些简单的公钥。但实际上我喜欢不记名令牌的想法,因为它非常简单直接。是的,我控制所有机器。希望没有其他人能够访问它。此外,它不是一项关键服务。我只是想避免让 API 公开可用...
    • 不记名令牌只是头部实现的一种特定的标准格式。在这个设计中,API 密钥是完全一样的东西,其他的头部也是一样的。这就是为什么我说“这只是实现 API 密钥的一种特定方式。您也可以将访问令牌(API 密钥)直接放入请求中。它会是相同的。”