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

时间:2018-03-23 21:37:12

标签: node.js security networking request localhost

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

所以说我运行了两个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 个答案:

答案 0 :(得分:1)

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

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

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

案例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中自行构建。

希望尽管有所帮助。