只是为了让人们知道,我确实按照一些人的建议稍微编辑了帖子,并且该问题已在此处发布在 Azure CDN 论坛上。我也将它发布在 StackOverflow 上的原因是为了尝试接触更多的受众,希望处理过相同/类似问题的人们可以提供有价值的解决方案/反馈。据我所知,目前还没有解决此问题的方法,但它会影响任何使用 CDN 交付其内容的企业。我愿意进一步编辑这个问题,但我要问的是,人们不会简单地否决这个问题,因为这听起来像“咆哮”,事实并非如此,我可以向你保证它会影响成千上万的企业在那里,无论人们是否意识到,每年都要花费数千美元。
所以这里的情况。假设我正在构建一个图片库网站,并且我想使用 Azure CDN 为我提供我的内容。在后端,Azure CDN 将从 Azure 存储帐户中提取内容。CDN 速度快且功能强大,但它似乎有点不安全,因为它会阻止某人能够提取大量内容,从而给用户留下巨额带宽费用。让我证明我的意思。
所以昨晚我决定写一个简单的控制台应用程序,它会从我未来的图片库网站下载一个简单的图像,在一个 for{} 循环中,代码如下:
namespace RefererSpoofer
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest myHttpWebRequest = null;
HttpWebResponse myHttpWebResponse = null;
for (int x = 0; x < 1000; x++)
{
string myUri = "http://myazurecdnendpoint.azureedge.net/mystoragecontainer/DSC00580_1536x1152.jpg";
myHttpWebRequest = (HttpWebRequest) WebRequest.Create(myUri);
myHttpWebRequest.Referer = "www.mywebsite.com";
myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse();
Stream response = myHttpWebResponse.GetResponseStream();
StreamReader streamReader = new StreamReader(response);
Image image = Image.FromStream(streamReader.BaseStream);
image.Save(string.Format("D:\\Downloads\\image{0}.Jpeg", x), ImageFormat.Jpeg);
myHttpWebResponse.Close();
}
Console.ReadKey();
}
}
}
此控制台应用程序对托管在我的 Azure CDN 端点上的图像文件发出 1000 个超快速连续请求,并将它们保存到我 PC 上的“D:\Downloads”文件夹中,每个文件名对应于 for{} 循环迭代,即image1.jpeg、image2.jpeg等。
那么刚刚发生了什么?在大约 1 分钟的时间内,我花费了自己 140MB 的带宽。这是一个高级 CDN,价格为 0.17 美元/GB,让我们一起算一下:0.14GB * 60 分钟 * 24 小时 * 30 天 * 0.17 美分/GB = 1028.16 美元的带宽成本,如果有人(例如竞争对手)想要制作一个在一个月内对单个图像的单个请求会危及我的网站。我想你们可以看到我的目标......我的网站将有数千张高分辨率图像,顺便说一句,我在这个例子中使用的图像大小只有 140KB。这些类型的请求可以来自匿名代理等。
所以我的问题是:如何防止有人滥用公开的 CDN 端点?显然,一个人不能因为恶意请求而为带宽支付 5,000 美元、20,000 美元。
现在 Azure Premium CDN 有一个高级规则引擎,它可以根据 Referer 过滤掉请求,并在 Referer 与您的网站不匹配的情况下响应 403 错误。但是,Referer 可以被伪造,就像我在上面的代码示例中所做的那样,并且 CDN 仍然允许提供请求(我使用 Referer 欺骗进行了测试)。这很糟糕,很多人使用Refer来防止'盗链',但是在这种带宽滥用的情况下,如果Referer可以通过一行代码来伪造又有什么关系呢?
关于防止此类滥用和巨大的带宽成本,我有几个想法:
*这两种解决方案都需要 CDN 采取行动:
当内容请求到达 CDN 时,CDN 可以调用客户端服务器,传入 a) 用户的 IP 地址 b) 请求的 CDN Uri。然后客户端服务器会检查从这个特定 IP 请求 Uri 的次数,如果客户端逻辑看到它在过去一分钟内被请求了 100 次,那么显然这将表明滥用,因为浏览器缓存图像,而恶意请求则不会。所以客户端机器会简单地回复“假”来为这个特定的请求提供内容。这不是一个完美的解决方案,因为对客户端基础设施的额外回调会导致一小段延迟,但这绝对比可能被困在看起来像您在银行储蓄账户中的金额的账单上要好。
更好的解决方案。对每个 ip 在特定时间范围内通过 CDN 提供文件的次数进行了限制。例如,在上面的图像文件示例中,如果可以将 CDN 配置为在 10 分钟的时间范围内服务不超过 50 个图像请求/IP/。如果检测到滥用,则 CDN 可以在客户定义的时间内 a) 为特定的滥用 uri 提供 403。或 b) 如果请求来自滥用者 IP,则所有 uri 的服务器 403。所有时间/选项都应该留给客户配置。这肯定会有所帮助。这里没有回调可以节省时间。缺点是 CDN 必须跟踪 Uri/IP 地址/命中数。
哪些解决方案不起作用:
签名 URL 将不起作用,因为签名查询字符串参数每次都会不同,并且浏览器会不断地请求数据,从而有效地清除浏览器对图像的缓存。
拥有 azure blob 的 SAS 访问签名也不起作用,因为 a) Uri 每次都不同 b) 授予 SAS 后,您可以请求 blob 的次数没有限制。所以滥用场景仍然是可能的。
检查您的日志并简单地通过 IP 禁止。我昨天通过匿名代理测试了这种类型的滥用,它就像一个魅力。在几秒钟内切换 IP 并继续滥用(我自己的内容)以进行测试。所以这也被淘汰了,除非有一个保姆来监控日志。
可行但不可行的解决方案:
在您的 Web 服务器上过滤请求。当然,这将是控制问题和跟踪请求/IP 数量的最佳方式,并且在检测到滥用时根本不提供内容。但是,您失去了不通过超快速、接近客户端优化的 CDN 交付内容的巨大好处。此外,通过提供大字节内容(例如图像)会大大降低您的服务器速度。
只需咬紧牙关,不要担心。嗯...那么您知道可以将您的车轮取出的坑洼就在路上,所以不,使用此选项感觉不舒服。
综上所述,Azure 提供的带有自定义规则引擎的高级 CDN 产品可能会在某处提供解决方案,但文档非常差,并且缺乏示例,人们只能猜测如何正确保护自己,所以这就是为什么我要写这篇文章。有没有人解决过这样的问题?以及如何解决它?
任何建议表示赞赏,我对这个问题持开放态度。
感谢您的阅读。