亚马逊AWS官方博客
盗链行为与 AWS 防盗链技术
“盗链”是互联网用语。通常指未经源网站允许的情况下,通过超链接引用源网站内容,如图片,视频等。盗链行为会造成受害网站数据泄露以及经济损失。
在现代互联网公司业务中防盗链技术扮演者越来越重要的角色,例如:网站通常会对内容进行防盗链处理,仅仅对特定用户开放,而没有权限的用户即使获得链接地址,也无法访问该链接所指向的内容。
本文根据常见盗链方法及其特点,介绍盗链对受害网站与用户造成的危害,以及如何利用AWS服务阻止盗链访问,从而确保网站数据访问安全。
盗链的形式与危害
图1:盗链过程
由上图中可以看出,盗链过程中,盗链网站自身不提供全部网页所需内容。部分网页内容来自受害网站。在以上过程中,受害网站实际承载盗链网站的部分业务流量和压力,而盗链网站则盗取该部分数据流量和计算资源甚至客户流量用以支撑自己的业务。受害网站则需要承担被盗取流量和计算资源所带来的运营成本,从而造成受害网站的经济损失。
同时,由于盗链的过程具有隐秘性,最终用户往往难以及时察觉盗链行为,在一些场景下盗链甚至会造成最终用户经济损失。
基于Referer的防盗链解决方案
根据HTTP标头决定是否允许访问
HTTP协议规范在HTTP标头中定义了referer字段(见RFC 1945, RFC 7231),用于表示HTTP请求来源。该字段值由浏览器在发起HTTP请求时指定。该字段值代表当前HTTP请求的来源,例如在点击网页链接时,浏览器会向服务器提交一个HTTP请求,请求中HTTP标头的referer字段值为引用该资源的网页地址,即用户点击的网页地址。
以下即为从https://thinkwithwp.com/cn/点击链接跳转到其他页面时,HTTP标头内容。注意其中referer字段:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN
Host: a0.awsstatic.com
If-Modified-Since: Wed, 02 Sep 2020 15:58:15 GMT
If-None-Match: “b9ec147e4cfd12659b26c5df5a97f68c”
Referer: https://thinkwithwp.com/cn/
表1:HTTP请求标头referer字段示例
通过对HTTP标头中referer字段内容跟进行判断,可以判定请求是正常用户发起的请求还是来自盗链网站。
利用AWS服务实现referer检查
- 方案一:通过WAF实现referer检查
WAF是由AWS提供的应用防火墙功能。WAF配合CloudFront,ALB或API Gateway使用,支持通过访问控制列表对Web请求进行过滤,从而实现拒绝盗链请求的功能。
WAF相当于在CloudFront,ALB或API Gateway前部署一套防火墙,其架构如下图所示:
图2:WAF部署架构
部署WAF时,首先创建一个ACL用于检查referer字段。在服务中搜索WAF,并选择“WAF & Shield”。
图3:创建ACL
在打开的页面中输入ACL名称,本例中使用“testACL”,并选择ACL所属区域,单击Add AWS resources添加关联的资源。此处可以关联CloudFront分发,ALB或API Gateway。之后单击“Next”继续。
图4:设置ACL名称
本示例中,Web服务器默认拒绝所有不符合referer匹配规则的连接。因此,在新打开的页面中需要将“Default web ACL action for requests that don’t match any rules”设置成“Block”。设置完成后单击“Add rules”,并选择“Add my own rules and rule groups”添加请求匹配规则。
图5:设置阻止没有匹配到任何规则的请求
本示例中,Web服务器默认拒绝所有不符合referer匹配规则的连接。因此,在新打开的页面中需要将“Default web ACL action for requests that don’t match any rules”设置成“Block”。设置完成后单击“Add rules”,并选择“Add my own rules and rule groups”添加请求匹配规则。
在弹出的页面上选择“Rule Builder”创建一条规则。
图6:选择Rule Builder创建规则
填写规则名称,规则类型选择“Regular rule”,匹配方式选择“matches the statement”,在Statement处选择Inspect “Header”,在Header field name字段中填写“referer”,Match Type选择“Contains string”,在String to match中输入允许访问的域名。本示例使用example.com。在Text transformation中选择“Lowercase”,以确保大小写不影响判断结果。之后在Action中选择“Allow”以允许访问。完成后单击“Add Rule”添加规则。
图7:配置规则
规则配置完毕后,检查“Web ACL rule capacity units used”,确保总WCU不超过1500。同时检查“Default web ACL action for requests that don’t match any rules”为“Block”。检查无误后,单击“Next”继续。
图8:检查规则
“Set rule priority”和“Configure metrics”配置页面均使用默认配置即可,可以直接点击“Next”跳过。
图9:设置规则优先级
图10:配置CloudWatch指标监控
在“Review and create web ACL”页面,检查各项配置,配置无误则单击“Create Web ACL”创建Web ACL。
图11:检查并创建ACL
在完成了配置工作之后,即可对WAF ACL进行测试。当使用了正确的referer字段时(本例中使用example.com),则返回HTTP 200 OK。
curl -H “Referer: https://example.com/” -I http://example.com/
HTTP/1.1 200 OK
Date: Sun, 06 Sep 2020 12:00:16 GMT
Content-Type: text/html
Content-Length: 703
Connection: keep-alive
Last-Modified: Sun, 06 Sep 2020 11:21:32 GMT
Accept-Ranges: bytes
表2:WAF验证通过允许访问测试效果
当使用的referer字段与预期值不匹配时,则返回HTTP 403禁止访问。
curl -H “Referer: https://example.net/” -I http://example.com/
HTTP/1.1 403 Forbidden
Server: awselb/2.0
Date: Sun, 06 Sep 2020 12:01:21 GMT
Content-Type: text/html
Content-Length: 134
Connection: keep-alive
表3:WAF验证未通过拒绝访问测试效果
- 方案二:使用Lambda@Edge实现复杂条件下
某些应用场景下,用户需要配置复杂的访问控制规则。而图形界面往往难以适应复杂访问控制规则的需要。此时Lamba@Edge与CloudFront配合使用,可以有效应对复杂访问策略带来的挑战。
Lambda@Edge是AWS利用Lambda无服务器计算服务结合CloudFront内容分发网络,在边缘站点运行Lambda代码,从而在边缘站点实现动态Web应用程序的技术。
由于Lambda@Edge通过编写代码实现对Web请求的精确过滤,因此可以为用户提供更加灵活的过滤条件和数据处理方式。
Lambda@Edge功能支持使用Lambda在CloudFront边缘节点对HTTP请求和响应进行按需调整。当CloudFront收到用户请求,CloudFront从源端请求资源,CloudFront接收到源端反馈资源和CloudFront即将向用户返回资源时,均支持调用Lambda对HTTP请求或响应进行按需处理。
图12:利用Lambda@Edge调整HTTP请求和响应
Lambda@Edge只需要在CloudFront创建分发时,在Lambda函数关联中指定查看请求所对应的Lambda函数即可。
图13:在CloudFront创建分发时指定Lambda函数
Lambda函数内容则如下图所示,用户可以在“handler”函数中编写自定义处理流程,在必要时,可以创建response对象,并将response对象的状态设置为403,从而达到禁止访问的效果。
图14:Lambda函数内容
由于采用了编程的方式,Lambda@Edge为网站访问控制提供了极大的灵活性。同时,由于Lambda函数运行于CloudFront边缘节点,因此不会占用核心节点计算资源,同时其无服务器架构支持自动扩展也有利于承载海量用户请求。
利用URL验证提升数据访问安全性
使用HTTP标头字段实现防盗链可以应对常见的盗链情形。但盗链者仍然可以通过更加复杂的手段如客户端脚本去生成一个具有合法HTTP标头的请求,从而获取访问文件的能力。
为了进一步提升文件访问的安全性,可以通过对请求的URL添加一个具有时效性的随机验证码作为签名。用户通过签名的地址访问相关资源。系统在后台对签名信息进行比对,确认签名正确性和时效性,从而识别当前请求是否有权访问对应文件。
AWS CloudFront Signed URL提供一整套签名管理方案,包括签名URL生成API,与CloudFront集成的签名验证机制,从而简化资源访问控制。
图15:Lambda函数内容
如上图所示,客户端在访问CloudFront资源前,需要通过签名URL生成器获取经签名的URL地址。AWS签名URL生成器支持包括Java,C#,PHP,Perl等多种开发语言。开发人员可以根据需要选择自己熟悉的语言完成签名URL生成工作。
当CloudFront收到资源请求时,会自动识别URL中签名部分是否正确,是否仍在有效期内,从而确定是否返回对应资源。
在对CloudFront进行配置前,建议首先完成签名URL生成器。一下为URL生成器的示例代码片段。
图16:生成签名URL代码示例
从以上代码示例中可以看出,签名URL主要包含几个要素:被签名的文件访问路径,签名URL生效和失效时间,请求客户端IP地址范围,以及签名URL使用的密钥信息。
生成的签名URL格式如下,高亮部分为签名URL内容,未高亮URL参数为原始请求所需参数:
http://d111111abcdef8.cloudfront.net/image.jpg?color=red&size=medium&Expires=1357034400&Signature=nitfHRCrtziwO2HwPfWw~yYDhUF5EwRunQA-j19DzZrvDh6hQ73lDx~-ar3UocvvRQVw6EkC~GdpGQyyOSKQim-TxAnW7d8F5Kkai9HVx0FIu-5jcQb0UEmatEXAMPLE3ReXySpLSMj0yCd3ZAB4UcBCAqEijkytL6f3fVYNGQI6
&Key-Pair-Id=APKA9ONS7QCOWEXAMPLE
表4:WAF验证未通过拒绝访问测试效果
签名URL生成器就绪后,就可以配置CloudFront使用签名URL了。配置过程也很简单,只需要在创建或者编辑CloudFront分发时,将Restrict Viewer Access选项设置为“Yes”即可。
图17:配置CloudFront分发启用签名URL访问
上图配置中Trusted Signer配置项用于指定可以生成签名URL的AWS账户。只有被授权的AWS账户才能为指定的CloudFront分发生成签名URL,从而确保数据访问安全性。
配置完成后,用户直接访问CloudFront分发时会提示禁止访问。效果如下:
curl -I http://d2znl5ds23rvha.cloudfront.net/Picture1.png
HTTP/1.1 403 Forbidden
Server: CloudFront
Date: Mon, 07 Sep 2020 02:45:18 GMT
Content-Type: text/xml
Content-Length: 146
Connection: keep-alive
X-Cache: Error from cloudfront
表5:在CloudFront启用签名URL后,未签名的URL无法访问
至此,访问CloudFront上的资源均需要使用临时生成的签名URL进行访问。由于签名URL具有时效性,因此难以被盗链者使用。从而改善了访问安全性。
开发人员还可以选择使用签名Cookie用于简化指定用户访问CloudFront资源的过程。相比签名URL,签名Cookie可以授予制定用户访问多个资源的能力,而无需为每个独立的资源生成签名URL。
部分场景下,由于实际业务需要,使得资源访问URL难以修改时,也可以是使用签名Cookie实现资源访问授权。
开发人员可以通过在生产签名URL或签名Cookie时增加资源请求客户端身份验证功能进一步提升资源访问的安全性。例如当收到生成签名URL请求时,检查资源请求客户端是否有登陆操作并对Cookie进行验证,从而使得资源访问过程更加安全。
适用于媒体资源的防盗链技术
媒体资源可以通过DRM数字版权管理技术实现更安全的资源访问管理。
DRM数字版权管理技术通过对媒体资源进行加密,并将媒体节目授权中心URL和密钥ID保存在媒体资源文件头部,从而实现更加安全的媒体资源访问控制。用户在播放媒体资源时,还需要从媒体节目授权中心获得对应密钥才能解密媒体内容。未经授权的用户即使获得媒体文件,也无法播放媒体内容。
AWS Elemental MediaPackage服务支持将DRM数字版权管理信息打包到媒体文件中,从而提供更加安全的媒体内容访问管控。