WebP Cloud Services Blog

WebP Cloud 目前已支持在图片 CDN 上设置回源 UA, CORS Header 并支持限制 Referer

· Nova Kwok

在之前的文章中,我们对比了一些和我们有类似功能的图片 CDN,发现除了直接将 NS 记录给转移到 CDN 服务商的(以 Cloudflare 为典型)以外,基本都会根据源站的图片地址给你一个新的地址,这一点上 WebP Cloud 也不例外。

具体来说,假设你的图片地址在:

https://blog.example.com/some/cat.jpg

那么一般来说你会获得类似如下的新地址:

# WebP Cloud
https://e52565b.webp.ee/some/cat.jpg

# Vercel
https://cdn-image.example.com/_next/image?url=https://blog.example.com/some/cat.jpg?w=640&q=75

# Other CDN
https://cdn.example.com/some/cat.jpg

要「接入」CDN 的话只需要将对应的图片地址换成新的地址即可。

这样做本身其实没有什么问题,使用一个新的地址可以在保证源地址可用的情况下减少接入成本,但是这里就有被盗链和 CDN 穿透(绕过)的风险,我们考虑以下两个场景:

  1. CDN 上可能会配置一些规则,比如生成水印(WebP Cloud 支持)防止原图被直接下载
  2. 源站可能是直接放在 AWS S3 这种流量费比较贵的服务上,使用 CDN 的目的主要是为了缓存减少 Egress 流量费用
  3. 其他网站,例如 https://some-content-farm.com 可以直接使用 img 标签来使用你的 CDN 地址的图片,产生额外的 CDN 请求数量/流量费用

我们对于上面的场景一个个来看:

  • 假设我们的图片 https://e52565b.webp.ee/some/cat.jpg 是放在 https://blog.example.com 页面上的,一个访客想下载对应的原图(因为博客上的图片可能加入了水印之类的不希望原图被直接拿走),可以很自然的猜到原图地址就是 https://blog.example.com/some/cat.jpg ,这个时候没有水印的原图就被盗走了,我们认为 CDN 被穿透(绕过)了
  • 对于后面两个情况其实也是如此,Vercel 甚至直接把原图地址就放在 URL 的 Params 上,访客可以很容易拿到原图

对于一般情况而言,可能 CDN 被穿透无非是多点源站流量费用的问题,但是如果你使用 CDN,并设置了水印就是为了防止图片被恶意盗用的话,那这里就有潜在的风险点了。

对于以上问题,我们最近发布的新功能打算从三个维度来尝试解决。

回源 UA

对于一般的 CDN 而言,访客使用的 User Agent 在 CDN 回源的时候会被直接发送给源站,WebP Cloud 和传统 CDN 在这个地方有一些差异。

WebP Cloud 目前回源用的 UA 是固定的字符串: WebP Cloud Services/1.0 ,用户请求的流程如下:

  • 访客对

    https://e52565b.webp.ee/some/cat.jpg
    

    发起请求,请求的 Header 如下:

    • User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
  • 假设对应图片并没有在 WebP Cloud 上缓存,需要回源,WebP Cloud 接受到请求之后向源站

    https://blog.example.com/some/cat.jpg
    

    发起 GET 请求,请求的 Header 如下:

    • User-Agent:WebP Cloud Services/1.0
  • WebP Cloud 拿到了原始图片之后进行对应的处理,并返回给访客

这里,我们的新功能允许用户设置回源时的 User-Agent ,即现在默认为 WebP Cloud Services/1.0 的字段,例如用户可以设置为: User-557f51ce-Custom ,这样这里 User Agent 可以作为一个 Pre-shared Key 的形式用于保证源站地址只能被 WebP Cloud 访问,杜绝了源站地址被猜到而导致 CDN 穿透(绕过)的问题。

设置了自定义的 User Agent 之后,源站可以用如下类似的配置来保证图片请求仅允许 WebP Cloud 回源:

Nginx

server {
    listen 80;
    server_name blog.example.com;

    location ~ \\.(jpg|jpeg|png|gif)$ {
        if ($http_user_agent !~ "User-557f51ce-Custom") {
            return 403;
        }
    }
    location / {
        # 其他配置
    }
}

Cloudflare

(http.user_agent ne "User-557f51ce-Custom") and ((http.request.uri.path contains "jpg") or (http.request.uri.path contains "png") or (http.request.uri.path contains "jpeg") or (http.request.uri.path contains "gif"))

AWS S3

可以通过编写 Bucket Policy 的方式来限定访问 UserAgent,例如:

{
    "Version": "2012-10-17",
    "Id": "OnlyAllowWebPCloud",
    "Statement": [
        {
            "Sid": "AllowSpecificUserAgent",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::blog-webp-se/*",
            "Condition": {
                "StringEquals": {
                    "aws:UserAgent": "User-557f51ce-Custom"
                }
            }
        },
        {
            "Sid": "DenyOthers",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::blog-webp-se/*"
        }
    ]
}

CORS Header

为了减少图片在站外被其他网站直接引用,我们允许用户设置自己的 CORS Header,可以在 Dashboard 上设置,这个默认值是 *,表示允许所有网站使用,在上面的例子中,如果你希望 https://e52565b.webp.ee/some/cat.jpg 只被博客域名 https://blog.webp.se 使用的话,可以设置为 blog.webp.se ,这样设置之后所有的请求返回的 Header 中的 Access-Control-Allow-Origin 字段会被设置为 blog.webp.se,对于其他网站的引用来说,图片会无法直接正常显示(提示 CORS 错误),进一步减少被盗链的风险。

Allowed Referer

  • 需要注意的是 referer 实际上是 “referrer” 误拼写。参见 HTTP referer on Wikipedia(HTTP referer 在维基百科上的条目)来获取更详细的信息。

上文中设置 CORS Header 的方式可以有效防止其他网站的前端框架引用你的图片,但是如果其他网站直接使用 img 标签使用图片的话,也就没有办法了。

所以这里我们提供一层额外的限制,通过限制网站的 referer 字段来进一步减少图片被盗用的概率。

  • Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

例如用户在访问: https://wordpress.webp.se/ 的时候,浏览器在加载页面上的图片时会带上:

Referer: https://wordpress.webp.se/

这个请求头,用来向服务端告知目前是哪个页面引用了这个图片,WebP Cloud 最近的新功能让用户可以在后台设置允许的 referer ,默认是 * 表示允许任意 referer,如果你希望对此加以限制的话,可以用逗号分割的域名的形式,比如 wordpress.webp.se,nova.moe,dmesg.app,tuki.moe ,假设这个时候有其他域名尝试直接用 img 标签的方式嵌入图片的话,WebP Cloud 会返回 403 阻止图片显示:

当然,防止图片被盗链有很多需要做的事情,以上只是 WebP Cloud 在保护源站安全和图片防盗链上做的一些微小的贡献。

和往常我们添加的新功能一样,WebP Cloud 一直坚信所有用户应该获得同等的使用权利。因此无论你是付费用户还是免费用户,以上三个功能均可随意使用。


WebP Cloud Services 团队是一个来自上海和赫尔辛堡的三人小团队,由于我们不融资,且没有盈利压力 ,所以我们会坚持做我们认为正确的事情,力求在我们的资源和能力允许范围内尽量把事情做到最好, 同时也会在不影响对外提供的服务的情况下整更多的活,并在我们产品上实践各种新奇的东西。

如果你觉得我们的这个服务有意思或者对我们服务感兴趣,欢迎登录 WebP Cloud Dashboard 来体验,如果你好奇它还有哪些神奇的功能,可以来看看我们的文档 WebP Cloud Services Docs,希望大家玩的开心~


Discuss on Hacker News