阻止对CDN上的内部资源的请求?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (53)

在这种情况下,防火墙存在的原因是:阻止外部请求访问内部资源。

所以说我运行了两个HTTP服务器:一个在端口8080上,另一个在端口8081上。

端口8080上的服务器是一个可公开访问的基于节点的网站(express在此示例中提供支持),并在每个请求上运行以下代码,这基本上是一种简单的CDN,它从用户定义的URL请求数据(在X-Cool-URL标题)并将该请求的正文返回给我网站域下的用户。requestrequest模块,reqexpress请求对象,resexpress响应对象。(显然这个特殊的代码不实用或者没有错误,但它是一个不错的例子。)

const url = req.get("X-Cool-URL"); // some example user input value
request(url, (error, response, body) => { // request said arbitrary resource
    res.send(body); // send response back to user
});

端口8081上的服务器是通过内部请求执行操作的HTTP服务器; 通过端口8081的外部网络被防火墙阻止,这是有充分理由的。绝不应将任意用户定义的数据发送给它。假设我不是此Web服务器的程序员,并且无法控制或访问其代码。这个服务器对任何给定请求输入的确切作用是无关紧要的。重要的是允许向其发送任意数据将是一种安全风险。

...但我可以从任何外部命令行运行此命令。

curl -H "X-Cool-URL: http://localhost:8081/something/malicious" http://example.com:8080

这就产生了一个问题:用户可以使用我的公共Web服务器通过localhost:8081内部网络请求私有Web服务器。我仍然希望人们能够通过我的Web服务器在端口8080上请求其他公共域,我仍然希望能够在内部请求8081作为开发人员,但我不希望任何其他人能够利用我的服务器任意访问8081,免于防火墙。我怎样才能使用户无法使用我的公共Web服务器请求任何内部资源?

我想要保护的端口可能并不总是明确且已知,因此仅通过我的Web服务器阻止8081是不切实际的。仅阻止所有请求也是不切实际的localhost,因为还有其他方式来请求内部资源(例如使用127.0.0.1)。甚至可以将DNS记录设置为指向本地资源的点,因此将一组URL列入黑名单也不起作用。白名单也不是一种选择,因为它会破坏CDN的要点,因为客户端能够请求任何外部资源。我感兴趣的是一种在每种情况下都能检测URL是否是内部的方法。

提问于
用户回答回答于

案例1:您在端口8080上控制代理服务器

因此,如果您控制代理服务器而不是其后面的Web服务器,那么实际上很容易阻止这样的事情:您只需要从请求中过滤某些HTTP头而不处理这些请求。

最安全的方法是使用允许在X-Cool-URL标题中使用的主机名白名单。然后只需检查URL是否与白名单匹配。或者你可以使用黑名单进行过滤,但这样做有点麻烦,因为你不仅要考虑localhost,还要考虑各种IP范围。你不想X-Cool-URL指向127.0.0.1,192.168.xx等任何东西。

案例2:您可以在端口8081上控制后端服务器

如果您无法控制代理服务器筛选的请求以及HTTP请求转发给您的请求,则必须检查请求的来源。您可以使用以下代码获取有关原始请求者的详细信息:

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

如果ip地址不在您允许的范围内,请不要回答该请求。这样,您可以从防火墙后面运行的其他服务器授予访问权限,同时阻止从代理访问。

开发者访问

一旦实现了这两种机制中的任何一种,您仍然希望允许对后端的开发访问。最简单的方法是使用只有您知道且无法轻易猜到的密钥。然后将此密钥作为附加HTTP请求标头(X-Cool-Secret)或作为X-Cool-URL查询参数作为其自身的一部分提供。

额外的冥想

像这样的场景本质上是不安全的。只要您通过公共Internet访问后端,就需要为攻击做好准备。即使您的代理可以过滤很多,但仍有可能找到通过它的方法。让代理和后端在同一台物理计算机(或VM)上运行会增加额外的安全风险。一般经验法则:不要这样做。

允许从开发机器访问也存在风险。密钥可能泄漏,密码可能被盗,IP地址可能被欺骗。没有简单的方法可以防止复杂的攻击。这种公共访问有许多权衡,你通常应该避免。尝试使用SSH作为安全隧道进入非军事区(防火墙和代理后面的所有内容)。这提供了一个更安全的环境,您可以在Node / Express中自行构建。

希望尽管有所帮助。

扫码关注云+社区

领取腾讯云代金券