1346 字
7 分钟
通过Apple快捷指令更新Cloudflare Gateway绑定IP
2022-06-02
无标签

TL;DR#

获取Cloudflare Account ID、包含Account.Zero Trust权限的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权限的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获取#

执行

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,则可以执行:

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设备,可以使用前文中已编写完毕的快捷指令~~,或者硬着头皮上~~。

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

主要流程为:

获取当前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给出的样例请求正文格式为:

{"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为什么会在一个示例里出现两处错误。正确的样例请求正文格式应为:

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

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

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