通过Apple快捷指令更新Cloudflare Gateway绑定IP

Author Avatar
陽楷锴 6月 02, 2022
  • 在其它设备中阅读本文章

本文共计1.5k字,大约需要5分钟进行阅读。

TL;DR

获取Cloudflare Account ID、包含Account.Zero Trust:Edit权限的Cloudflare API Token、Location的ID后,使用此快捷指令即可更新Cloudflare Gateway绑定IP:

两个链接内容一致,站内链接权当备份。

根本没仔细测试过Apple的Shortcuts Setup能不能用的问题。根据我对Apple的认知,很可能会遇到变量导入的问题,尤其是涉及到有两个字符串需要转换为布尔值。如果遇到相关问题,建议直接把你的内容硬编码到快捷指令里,然后给我留个评论,谢谢~

(我相信都用着Cloudflare Zero Trust而且还能找到这里来的人应该不差这点能力的,吧。);-)

背景&介绍

Cloudflare Gateway是一款运行于DNS层或HTTP层的安全网关。其具有不错的可自定义程度。在基于DNS使用时,其提供IPv4/IPv6 :53 UDP、DoT、DoH几种接入方式。

在通过IPv4 :53 UDP接入其DNS服务时,由于IPv4地址非常稀缺,每个人分配到的接入点都将是一个相同的Anycast IP地址。因此需要在Cloudflare登记客户端IP地址以进行个性化配置。

很不幸,Cloudflare没有提供DDNS支持,而我的路由器又不支持DoT、DoH,更糟糕的是,我的ISP到现在都没有提供IPv6互联网……所以很长一段时间我都只能手动进行IP地址更新。

直到最近我突发奇想,决定通过Cloudflare API对Cloudflare Gateway绑定IP进行定期更新。

前提&准备

Cloudflare API Token

首先,为了使用Cloudflare API,我们需要一个至少包含Account.Zero Trust:Edit权限的Cloudflare API Token。可以在https://dash.cloudflare.com/profile/api-tokens进行生成。

Cloudflare Account ID

打开Cloudflare Zero Trust仪表板,登入账户后,在页面的URL中应该可以非常方便地看到你的Account ID,不做过多赘述。

Gateway Location信息

生成符合条件的API Token之后,我们需要获取Gateway中对应Location的ID。这一步有两种获取方法。

通过网页仪表板获取

打开Cloudflare Zero Trust仪表板,登入账户后,在边栏选择Gateway > Locations,并选择或新建一个想要使用的位置,对其进行至少一次编辑(如名称、ECS支持、是否为默认等)。此时你需要记录该Location的名称。

然后在边栏中转到Logs > Admin,查看对应的Update location事件,在log的json中寻找关键字为id的字符串。注意不是account_id,也不是network关键字下的id

通过API获取

执行

1
2
3
GET https://api.cloudflare.com/client/v4/accounts/:identifier/gateway/locations
Header: Authorization: Bearer :token
Header: Content-Type: application/json

即可获得你所有可用的Gateway Locations。在返回的json中寻找关键字为id以及name的字符串。如果你使用curl,则可以执行:

1
2
3
curl -X GET "https://api.cloudflare.com/client/v4/accounts/:identifier/gateway/locations" \
-H "Authorization: Bearer :token" \
-H "Content-Type: application/json"

这一步中的:identifier是指你的Cloudflare Account ID,:token是指你的API Token,下文同样。注意在替换为你的个人内容时不要保留:,例如,如果你的Account ID是example123456,你应该使用https://api.cloudflare.com/client/v4/accounts/example123456/gateway/locations而非https://api.cloudflare.com/client/v4/accounts/:example123456/gateway/locations

编写快捷指令

这一步建议在macOS中进行,因为iOS上的快捷指令对HTTP请求的配置界面很奇怪。我用着并不是很明白。如果你没有macOS设备,可以使用前文中已编写完毕的快捷指令,或者硬着头皮上

由于作者使用的是英文版操作系统,可能一些翻译不是非常准确,敬请谅解。

主要流程为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
获取当前IP地址:外部,IPv4

获取URL内容:
https://api.cloudflare.com/client/v4/accounts/:identifier/gateway/locations/:uuid
方法为PUT
Header:
Content-Type: application/json
Authorization: Bearer :token
请求正文格式为json,包含:
networks,类型为数组/阵列(Array),包含:
一个字典(Dictionary),包含:
network,类型为字符串/文本(Text),值为:ip/32
name,类型为字符串,值为:name
client_default,类型为布尔(Boolean),值为:client_default
ecs_support,类型为布尔,值为:ecs_support

此处:identifier:token的定义与上文(#通过API获取)一致,不再赘述。:uuid指需要更新的Location ID。:ip指你在快捷指令的第一步中获取的外部IPv4地址。:name指你希望将此Location重命名为的名称。若不欲重命名,填写为原来的名称即可。:client_default指你是否希望此Location成为默认选项(目前我尚不知道此选项的作用)。注意,如果你希望将此项目的值设为False,你需要保证你有一个另外的Location作为默认值,否则其值必须为True:ecs_support指你是否希望此Location的DNS服务启用ECS,建议设为True来提高性能。

Cloudflare API Documentation给出的样例请求正文格式为:

1
{"name":"Austin Office Location","networks":["192.0.2.1"],"client_default":"false"}

这是不对的。如果按照此方式进行请求,我们将得到一个错误,消息为json: cannot unmarshal string into Go struct field LocationRequest.networks of type api.NetworkRecordJSON以及json: cannot unmarshal string into Go struct field LocationRequest.client_default of type bool。我不知道Cloudflare为什么会在一个示例里出现两处错误。正确的样例请求正文格式应为:

1
{"name":"Austin Office Location","networks":[{"network": "192.0.2.1/24"}],"client_default":false}

此处我也遇到了问题。搜索后参考了Cloudflare Community里的一篇文章解决了问题。十分感谢。

至此,可以直接通过Apple平台上的快捷指令完成对Cloudflare Gateway绑定IP的更新了。后话就是建议添加自动化获得更加体验了。

本文以KYPL授权转载。
本文链接:https://kaiy.moe/2022/update-Cloudflare-Gateway-IP-shortcuts/