Cloudflare+Backblaze搭建免费图床
song

准备

创建托管图片的存储桶

登录 Backblaze,然后单击B2 Cloud Storage下左侧的Buckets,然后单击Create a Bucket。将存储桶设为公开(public),将其他设置默认即可。
Backblaze B2 的桶名不能重复 全球唯一

image

上传的图片,查看属性值,将Friendly URL里面的主机名记下来,这里是f005.backblazeb2.com https://f005.backblazeb2.com/file/bucket-name/123456.jpg

为图床域名添加CNAME解析

登录cloudflare,新增域名解析指向上面获取的主机名f005.backblazeb2.com
image
保存完毕后,再在左侧列表点击SSL/TLS,将加密模式从“flexible(灵活)”更改为“full(完全)”

重写 URL,隐藏bucket名称

单击Cloudflare仪表板左侧的规则,然后单击转换规则,在重写URLtab下的创建规则。

  • 规则名称Backblaze存储地址重写
  • 添加匹配规则(http.host eq "自定义主机名称" and not starts_with(http.request.uri.path, "/file/自定义的桶名称" )
    -)
  • 添加Dynamic重写规则 concat("/file/自定义的桶名称",http.request.uri.path)

完成后如图所示

点击部署,现在可以用你自定义的域名测试下了,举个例子:

  • 原始地址为:https://f005.backblazeb2.com/file/自定义的桶名称/test.png
  • 重写之后地址为:https://files.example.com/test.png

这里的配置实现了 {your_domain}/xxx.jpg -> Friendly domain/file/{bucketName}/xxx.jpg 的转换,既不会暴露自己的桶名称,还缩短了 URL。

其他调整

删除HTTP标头

图片在响应时有一些X-Bz开头的字段,这些都是和Backblaze云存储相关的,要把它们都隐藏掉。

Cloudflare仪表板–>规则–>转换规则–>修改响应头–>创建规则
移除下面这些header请求头。

1
2
3
4
5
X-Bz-Content-Sha1
X-Bz-File-Id
X-Bz-File-Name
X-Bz-Info-Src_last_modified_millis
X-Bz-Upload-Timestamp

backblaze缓存设置

进入backblaze后台,点击Buckets中Bucket Settings设置,设置Bucket Info{"cache-control":"public,max-age=5184000"},5184000秒(也就是60天),最后点Update Bucket保存设置。
设置之后Cloudflare会缓存数据到自己cdn服务器上,减少请求backblaze的流量,节省用量。

cloudflare配置缓存规则

进入cloudflare控制台,缓存–>Cache Rules,创建新缓存规则

  1. 匹配规则(http.host eq "图床域名")
  2. 缓存资格:选择符合缓存条件
  3. 边缘TTL:选择忽略缓存控制标头,使用此 TTL,缓存时间设置为一个月
  4. 浏览器TTL:选择替代源服务器,使用此 TTL,缓存时间设置为一个月
  5. 缓存密钥:开启缓存欺骗盔甲

b2私人桶通过Cloudflare Worker实现外围访问

我们使用CloudFlare Worker定时更新重写URL规则,所以需要先为这个Worker创建一个API令牌。进入我的个人资料 API令牌,然后点击创建令牌,在接下来的页面中中选择创建自定义令牌,然后如图创建一个令牌。

image

添加成功后,妥善保存这个令牌。CfAuthKey

接下来我们需要知道要修改的规则,规则集等ID。

  • CfRulesetID: 在重写URL规则那里修改一下规则,内容随意,之后在 管理帐户 –> 审核日志 如下图找到我们需要的规则集ID。

image

通过cf提供的api获取规则集id

1
2
GET https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets
Authorization: Bearer YOUR_CLOUDFLARE_API_TOKEN

YOUR_ZONE_ID 换为你的域名的区域 ID。YOUR_CLOUDFLARE_API_TOKEN 换成你的 API 令牌,这里我创建使用了读取所有资源 模板API令牌。

这个请求会返回一系列规则集,有 CloudFlare 内部的,也有我们自己的。理论上,名字是 default 并且 phase 是 http_request_transform 的那个就是我们要的。

  • CfRuleID: 打开上面定义的 重写url 规则,在规则的编辑页面里面,url地址的最后一段就是规则的D。

通过cf提供的api获取规则id

1
2
GET https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/rulesets/RULE_SET_ID
Authorization: Bearer YOUR_CLOUDFLARE_API_TOKEN

RULE_SET_ID 替换为上面找到的规则集的 id。

前往 CloudFlare Workers,创建一个新的 Worker。然后到设置 –>变量,添加如下环境变量:

量名
B2KeyID Backblaze 的 keyID
B2AppKey Backblaze 的 applicationKey
B2BucketName Backblaze 的存储桶名
CfAuthKey 上面创建的 CloudFlare API 令牌
CfHostname CloudFlare CNAME好的二级域名
CfZoneID 你的域名的区域 ID
CfRulesetID 上面拿到的规则集 ID
CfRuleID 上面拿到的规则 ID

设置–>域和路由 点击禁用,因为我们不会用 HTTP 请求来触发这个 Worker。
设置 –>触发事件 中添加一个 Cron触发器,BackBlaze的文档说一个 Token 的有效期最大不超过 24 小时,这里每1个小时触发一次woker,更新token ,0 */1 * * *

至此前置任务完成,点击右上角的快速编辑,然后将如下脚本粘贴进去,然后点击保存并部署。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
addEventListener("scheduled", (event) => {
event.waitUntil(updateRule());
});

const getB2Token = async () => {
const res = await fetch(
"https://api.backblazeb2.com/b2api/v2/b2_authorize_account",
{
headers: {
Authorization: "Basic " + btoa(B2KeyID + ":" + B2AppKey),
},
}
);
const data = await res.json();
return data.authorizationToken;
};

const updateRule = async () => {
const b2Token = await getB2Token();

const res = await fetch(
`https://api.cloudflare.com/client/v4/zones/${CfZoneID}/rulesets/${CfRulesetID}/rules/${CfRuleID}`,
{
method: "PATCH",
headers: {
"Authorization": `Bearer ${CfAuthKey}`
},
body:
`{
"description": "Replace path for static files for blog",
"action": "rewrite",
"expression": "(http.host eq \\\"${CfHostname}\\\" and not starts_with(http.request.uri.path, \\\"/file/${B2BucketName}\\\"))",
"action_parameters": {
"uri": {
"path": {
"expression": "concat(\\\"/file/${B2BucketName}\\\", http.request.uri.path)"
},
"query": {
"value": "Authorization=${b2Token}"
}
}
}
}`,
}
);

const data = await res.text();
console.log(data);
return data;
};

async function handleRequest(request) {
const data = await updateRule();
return new Response(data);
}

等 Worker 被触发之后,就可以在浏览器中访问上面配置的域名,来测试到存储桶的连接是否正常。如果测试没问题,就可以把博客中的图片链接换到新地址了。

由 Hexo 驱动 & 主题 Keep