如何以安全的方式从S3提供HLS流(授权和认证)

时间:2016-10-11 10:29:43

标签: amazon-s3 video-streaming restful-authentication http-live-streaming hls

问题:

我使用给定的文件结构在 S3 中存储 HLS 流的数量:

Video1
  ├──hls3
      ├──hlsv3-master.m3u8
      ├──media-1
      ├──media-2
      ├──media-3
      ├──media-4
      ├──media-5
  ├──hls4
      ├──hlsv4-master.m3u8
      ├──media-1
      ├──media-2
      ├──media-3
      ├──media-4
      ├──media-5

在我的用户 API 中,我知道哪个用户可以访问哪些视频内容 但我还需要确保视频链接不可共享且只能访问 具有正确权限的用户。

解决方案:

1)将signed / temp S3 网址用于私有 S3 内容。每当客户想播放一些特定的视频时 向我的 API 发送请求。如果用户具有正确的权限,则 API 会生成签名的网址 并将其返回给客户端,然后将其传递给播放器。

我在这里看到的问题是,真实的视频内容存储在 media - * 目录中的十几个段文件中 而且我真的不知道如何保护所有这些 - 我是否需要单独签署每个段文件网址?

2) S3 内容是私有的。玩家提出的视频流请求通过我的 API 或单独的反向代理。 因此,每当客户决定播放特定视频时, API / 反向代理即可获取请求,执行身份验证和授权 并传递正确的内容(主播放列表文件和段)。

在这种情况下,我仍然需要将 S3 内容设为私有,并且只能通过我的 API / 反向代理访问。这里推荐的方式应该是什么? S3 rest authentication via tokens

3)使用受保护密钥加密。在这种情况下,所有视频片段都是加密的并且是公开的。密钥也存储在 S3 中 但不公开。玩家提出的每个关键请求都经过身份验证。由我的 API / 反向代理授权。

这些是我现在脑海中的三种解决方案。不相信所有这些。我正在寻找一些简单且防弹安全的东西。有什么建议/建议吗?

二手技术:

  • ffmpeg,用于将视频编码为不同的比特率

  • bento4进行视频分段

1 个答案:

答案 0 :(得分:15)

  

我是否需要单独签署每个段文件网址?

如果玩家直接从S3请求,那么是。所以这可能不是理想的方法。

一个选项是在存储桶前面的CloudFront。 CloudFront可以配置Origin Access Identity,允许它签署请求并将它们发送到S3,以便它可以代表授权用户获取私有S3对象,CloudFront支持两个签名URL(使用与S3不同的算法,我将在下面解释两个重要的差异)或signed cookies。 CloudFront中的签名请求和cookie的工作方式非常相似,重要的区别在于cookie可以设置一次,然后由浏览器自动用于每个后续请求,从而无需签署单个URL。 (AHA)。

对于CloudFront中的签名URL和已签名的Cookie,如果您使用自定义策略,则会获得另外两个无法使用S3执行的功能:

  • 与CloudFront签名关联的策略可以允许wildcard in the path,因此您可以授权访问任何文件,例如/media/Video1/*,直到签名到期为止。 S3签名URL不支持任何形式的通配符 - S3 URL只能对单个对象有效。

  • 只要CloudFront分配仅配置为IPv4,您就可以将签名绑定到特定的客户端IP地址,只允许从单个IP地址访问该签名(CloudFront现在支持IPv6作为可选功能,但它目前不兼容此选项)。这有点激进,可能不适合移动用户群,当他们从提供商网络切换到Wi-Fi并返回时,它将切换源地址。

仍然必须为所有内容链接生成签名URL,但是您只能生成并签署一次URL,然后重复使用签名,只需对每个文件的URL进行字符串重写,从而使该选项的计算成本更低。但仍然很麻烦。另一方面,签名的cookie应该只是工作"对于任何匹配的对象。

当然,添加CloudFront还可以通过缓存和Internet路径缩短来提高性能,因为请求会跳到更接近浏览器的托管AWS网络,而不是通常直接发送到S3的请求。使用CloudFront时,来自浏览器的请求将被发送到60多个全球"边缘位置中的任何一个"假设是最接近发出请求的浏览器。只要sig或cookie有效,CloudFront就可以为具有不同URL或cookie的不同用户提供相同的缓存对象。

要使用CloudFront签名的Cookie,至少应用程序的一部分 - 设置Cookie的部分 - 需要在"背后"指向存储桶的相同CloudFront分配。这是通过将您的应用程序声明为分发的附加Origin,并为特定路径模式创建缓存行为来完成的,该模式在请求时由CloudFront转发到您的应用程序,然后该应用程序可以使用相应的Set-Cookie:进行响应头。

我不隶属于AWS,所以不要将以下内容误认为是""" - 只是期待您的下一个问题:CloudFront + S3的定价使得与单独使用S3相比的成本差异通常可以忽略不计 - 当通过CloudFront和CloudFront'请求对象时,S3不会向您收取带宽费用。在某些情况下,带宽费用略低于直接使用S3的费用。虽然这似乎违反直觉,但有意义的是,AWS会以这样的方式构建定价,以鼓励通过其网络分发请求,而不是将它们全部集中在单个S3区域。

请注意,上述或下面的机制都不会完全免受未经授权的共享,#34;因为认证信息必然可供浏览器使用,因此也可供用户使用,具体取决于用户的专业知识......但这两种方法似乎足以让诚实的用户保持诚实,这是你所希望的全部。做。由于签名URL和cookie上的签名具有到期时间,因此共享能力的持续时间有限,您可以通过CloudFront日志分析识别此类模式,并做出相应的反应。无论您采取何种方法,都不要忘记保持日志的重要性。

反向代理也是一个好主意,可能很容易实现,并且如果运行代理的EC2机器与存储桶位于同一AWS区域,并且应该执行相当可接受,没有额外的数据传输费用或吞吐量问题代理基于像Nginx或HAProxy中那样的可靠,高效的代码。

您不需要在此环境中对任何内容进行签名,因为您可以配置存储桶以允许反向代理访问私有对象,因为它具有固定的IP地址。

在存储桶策略中,您可以通过授予" anonymous"用户s3:getObject权限,仅当其源IPv4地址与其中一个代理的IP地址匹配时。代理服务器代表授权用户匿名请求对象(无需签名)。这要求您不使用S3 VPC端点,而是为代理提供弹性IP地址或将其置于NAT网关或NAT实例之后,让S3信任NAT设备的源IP。如果你使用S3 VPC端点,那么应该可以让S3信任该请求只是因为它遍历了S3 VPC端点,尽管我没有对此进行测试。 (S3 VPC端点是可选的;如果你没有明确配置一个,那么你就没有一个,也可能不需要一个)。

如果我理解正确,你的第三个选项似乎最弱。授权但恶意的用户可以获得可以全天共享密钥的密钥。