我已经开发了一个 NodeJs + express 应用程序,该应用程序部署为IBM Cloud中的 Cloud Foundry应用程序。 我想执行相互认证(客户端和服务器证书),以控制传入流量和对我的应用程序的请求。我的证书由安全网关生成,如here所述,并将我的应用程序配置为云目标(可从本地客户端访问)。
安全网关已生成以下pem文件:服务器的主证书,中间证书和根证书以及目标证书和密钥。 在文档中,使用tls.createServer非常清晰Nodejs example。
在我的情况下,存在一些差异: 首先,我处于相反的情况(本地客户端通过Secure Gateway创建隧道连接到云应用程序)。 其次,这是本文的主要原因,我的应用程序已部署为CF应用程序。
阅读有关HTTP routing的CF文档,我发现IBM Cloud仅使用端口80和443,然后通过HTTP将请求转发到应用程序正在侦听的端口(例如,如果我的NodeJ在6001端口上运行)并且我将云端点称为端口443,GoRouter将通过HTTP将请求转发到正确的端口,并添加X-Forwarded-Proto
标头,以将用于请求的原始协议信息传递给应用程序。
请牢记这一点(假设这是正确的),在我的NodeJs代码中,我不能使用类似https.createServer(opts, app)
之类的东西,因为所有传入App容器的请求都将通过HTTP。
阅读CF文档here我知道可以告诉CF将证书转发到我的应用程序,但这是我无法真正理解的。
首先,在Load Balancer或GoRouter处终止TLS有什么区别?这种选择背后的原因是什么?
我的第二个问题是,一旦将证书作为HTTP标头转发到我的应用程序,则处理证书的正确方法是什么?这是因为我的NodeJs服务器将是http服务器,它是使用标准http.createServer(app)
的express创建的。
感谢所有将帮助我解决此问题的人。显然,如果您有任何示例或建议,那将非常有帮助。
答案 0 :(得分:0)
阅读有关HTTP路由的CF文档我发现IBM云仅使用端口80和443,然后通过HTTP将请求转发到应用程序正在侦听的端口(例如,如果我的NodeJ在6001端口上运行,并且我调用了在端口443上的云终结点上,GoRouter将通过HTTP将请求转发到正确的端口,并添加X-Forwarded-Proto标头,以向应用程序传递用于请求的原始协议的信息。
请记住这一点(假设这是正确的),在我的NodeJs代码中,我不能使用https.createServer(opts,app)之类的东西,因为所有传入App容器的请求都将通过HTTP。
是的。
首先,在Load Balancer或GoRouter处终止TLS有什么区别?这种选择背后的原因是什么?
这仅在您运行自己的Cloud Foundry平台时适用。如果您要将应用程序部署到由其他人运营的Cloud Foundry平台上,他们将做出此决定,并且不会以用户身份影响您。
作为操作员,这是您需要做出的选择。有一些取舍取决于您选择做什么。
您可以在LB处终止。通常这是最快的,因为LB在处理TLS / SSL方面非常有效。然后,LB可以将流量未经加密地转发到Gorouter上,这减少了Gorouter的工作量,但代价是不对两者之间的流量进行加密(根据安全要求,可能不行)。在这种情况下,LB有责任添加x-forwarded-*
标头。
浏览器-> HTTPS-> LB-> HTTP-> Gorouters-> HTTP->您的应用
您可以使用4层LB,并使Gorouters之间的连接平衡。这使Gorouters可以终止TLS / SSL。他们在执行此操作方面非常有效,但比大多数LB效率要低。这也可以使您在请求路径中加密直至Gorouter。在这种情况下,Gorouters的责任是添加x-forwarded-*
标头。
浏览器-> HTTPS-> LB-> HTTPS-> Gorouters-> HTTP->您的应用
您可以在LB处终止,但可以在LB和Gorouters之间打开新的TLS / SSL会话。这是效率最低的选项,因为它需要终止两个TLS / SSL会话,但是它提供了到Gorouter的请求路径中的加密。在非第4层LB上,它也往往是最灵活的,它可以让您的LB检查HTTP流量,因为您要终止LB上的会话。在这种情况下,LB有责任添加x-forwarded-*
标头。
浏览器-> HTTPS(会话A)-> LB-> HTTPS(会话B)-> Gorouters-> HTTP->您的应用
同样,如果您没有运行Cloud Foundry平台,那么您可以忽略它。
我的第二个问题是,一旦将证书作为HTTP标头转发到我的应用程序,则处理证书的正确方法是什么?这是因为我的NodeJs服务器将是http服务器,它是用express以标准方式http.createServer(app)创建的。
您无需在创建服务器的方式上做任何花哨的事情。您所需要做的就是查看x-forwarded-*
标头,然后使用这些标头做出决定。
请求是否通过HTTPS传入?查看x-forwarded-proto
(对于HTTPS请求,应将其设置为https
)还是查看{{1} },对于HTTPS请求,应将其设置为x-forwarded-port
。
请求中是否提供了客户证书?请查看443
。如果包含证书,则客户端提供了证书。
客户端的证书有效吗?如果您的应用收到请求,则客户端的证书有效。您知道这一点是因为平台可以为您处理该部分。由于平台(LB或Gorouter)正在终止TLS / SSL连接,因此有责任验证证书。如果您的应用收到请求并且设置了X-Forwarded-Client-Cert
,则该证书有效。
如何根据客户证书做出授权决定?这有点棘手,但是通常您会从x-forwarded-client-cert
中提取证书,进行读取/解析并根据证书内容做出决定(由于平台,我们知道这是有效的)。您很可能会查看主题名称,并将其视为用户名。然后查找该用户的角色或权限。但是,如何解决问题取决于开发人员。
希望有帮助!