Cloudflare 三两事

Posted on June 18, 2024 (Last modified on June 19, 2024) • 9 min read • 4,330 words
Share via
 
 
 
 
 
 

Cloudflare 的一些使用感受

Cloudflare 三两事
Photo by Pero Kalimero on Unsplash

使用 cloudflare 一年多了,突然想记录下自己使用的一些爽点和痛点。为了简化称呼,后续的内容中的 cloudflare 简称为 CF。

一、com 域名  

对比了些常见的国内外域名厂商,发现从 CF 购买长期 5 /10 年以上的 com 域名,便宜又省心。不知道为啥,很少见到有人提及这个部分。大多都是介绍某个域名商的短期域名如何便宜,比如一年才零点几美元/年或者一两美元/年,同时巧妙规避这些低价域名的高昂续费价格的宣传,只有你点进旁边的续费选项才看到,这个时候往往你已经注册了。这种常见的市场营销策略,活跃于各种场合。和国内万网域名供应商相比,他有很多优势,同时还有很多免费自定义的域名服务,就功能性而言简直吊打众多厂商。一旦用网,还是得看 ISP 供应商的脸色和制约。在这点上 CF 也想到了,面向个人用户也免费提供了 CDN 服务,简直菩萨行为,不过还是要警惕,下面会陆续讲到。

二、tunnel  

CF tunnel 是一个比较火的功能点,应对近年来来 IPv4 短缺及 Lab 服务映射问题。个人用户只要注册了 CF 账户,内部环境能联网,有域名绑定了 CF 的 DNS 服务,通过 tunnel 配置就直接能在公网访问你的内网服务。CF 额外提供免费额度的 CDN 加速,直接抢断 NPS/FRP 的市场。tailscale funnel 作为后起之秀,也被打的措手不及。随着防火墙技术的发展,NPS/FRP/Zerotier 已经被很多安全公司列入了严格的监管限制名单,一经启用,安全员立马来找你了。开源 cloudflare-tunnel-ingress-controller 项目,可以直接暴露内网的 k8s 服务给公网访问使用,不过目前比较偏向 deployment 服务,对于 headless statefulset 服务映射目前支持的还比较有限。如果想的话,可以使用 docker-compose 的 CF tunnel 去实现这个部分,CF 官方有介绍的。或者 cloudflare-operator 实现。

docker-compose 版本的 CF 配置,有一个地方要注意。默认 CF tunnel 会用 quic 协议, 但是这个协议的稳定性在实际体验上会比 http2 差些,具体现象就是比如你本地使用 CF tunnel 映射了自己的内网博客到公网的域名映射访问,quic 协议的经常会出现博客的公网域名打不开的情况,http2 方式的相对稳定很多。CF 论坛有很多相关的帖子,有兴趣你可以自己查下。

command: "tunnel --protocol http2 run"

那么问题来了,CF tunnel 这么强,又给免费额度的 CDN,他没有缺点么?

这个东西是后来在一次网络检查中发现的,为了收紧个人使用子域名的数量,降低一些维护精力和成本。在用 nmap 检查自己的 CF tunnel 服务的时候,就发现他会把与 CF tunnel 服务所在的宿主机同台的其他服务直接暴露在公网,如果你想要认真做这部分云 waf 的限制,不好意思,这部分不免费。

同时对于你本地内网的 https 服务的公网映射,你需要 enable TLS/No TLS Verify 的选项,才能使用,默认 No TLS Verify 是 disable 的状态 。

如果是 tunnel 映射本地的内网 http 服务,CF 自动免费提供无痕的 https 的证书服务。但是你的请求内容会全部都在他们的服务器上明文显示,这种非常危险。

三、warp  

还有比较火的 CF warp 功能,不少开发者利用 warp 的机制,弄出了无限免费的代理服务。CF 官方在看到这些现象的反应是默许的。只是心里对这个功能的疑虑很大,但是还是忍不住感慨,这个的确是很硬的功能。目前不太会考虑使用他,没有啥需求。

四、worker  

CF 还有很强大的 worker 功能,这个真的挺好用的。偶尔在转写一些 AI 代理服务的时候,表现得很出色,除此当然还有其他的。比如区域限制, docker hub 的访问被收紧,很多得 CF worker docker hub 项目起死回生。不少内容都是雷同的,为了验证这些新出方法是否好用。自己做了些测试,发现弊端很多。准确来说是 CF worker 自建 docker 镜像源的镜像加速服务,想要实现的目的是 pull 镜像网络不受阻隔,且速度不慢。这个部分会简称涵盖为 docker 代理。

4.1 worker 转发  

4.1.1 第一种  

GitHub - ciiiii/cloudflare-docker-proxy: A docker registry proxy run on cloudflare worker.
GitHub - ImSingee/hammal: docker-registry proxy run in cloudflare workers

4.1.2 补充  

GitHub - dqzboy/Docker-Proxy-镜像加速\管理服务.支持部署到Render

第一种是通过 CF worker 去转发重写原始镜像的仓库名字去实现的。假如你有一个域名 test123.com

const routes = {
  ***
   "docker.test123.com": "https://registry-1.docker.io",
  "quay.test123.com": "https://quay.io",
  "gcr.test123.com": "https://gcr.io",
  "k8s-gcr.test123.com": "https://k8s.gcr.io",
  "k8s.test123.com": "https://registry.k8s.io",
  "ghcr.test123.com": "https://ghcr.io",
  ***
};

fork 项目,然后根据教程去配置相关的 CF worker 的 api token 及 account id, 过程挺简单的。

然后配置 CF 的私有的 dns 解析,修改 GitHub 上 fork 过来的 const routes 的域名映射信息,一切都很流畅。

CF 私有 dns 解析
CF 自定义域名

除此外,还要修改宿主机本地的 /etc/docker/daemon.json,添加替换 registry-mirrors 的配置,最后重载相关服务。现网可不允许随便重启 docker。

继续往下测试,为了测试的有效性,把全部三方的公网源干掉了。

没改 docker 代理前

## 没改前源配置:"registry-mirrors": ["https://dockerhub.azk8s.cn", "https://docker.mirrors.ustc.edu.cn"], 

root@test123:~# docker pull grafana/grafana:8.3.1
Pulling from grafana/grafana
error pulling image configuration: download failed after attempts=6: dial tcp 162.125.7.1:443: i/o timeout

删除三方源,只用 CF Worker 转发的自定义域名源

为了节省篇幅展现重点,一些日志打印删除了,比如更多重复 pull 的过程和 pull 的详细打印过程。不影响当前的实测结果。

想先测试下grafana
发现 grafana 无论是否使用原始 repo 还是自定义域名 repo 都可以正常拉起,

root@test123:~# docker pull  docker.test123.com/grafana/grafana:8.3.1
Pulling from grafana/grafana
Digest: sha256:259b847ed7e3f58e6056438fd3bc353f48fbe9b77ed3b204ae619ba80e10aed9
Status: Downloaded newer image for docker.test123.com/grafana/grafana:8.3.1
docker.test123.com/grafana/grafana:8.3.1
  

root@test123:~# docker pull  grafana/grafana:8.3.1
Pulling from grafana/grafana
Digest: sha256:259b847ed7e3f58e6056438fd3bc353f48fbe9b77ed3b204ae619ba80e10aed9
Status: Downloaded newer image for grafana/grafana:8.3.1

root@test123:~# docker images|grep grafana
grafana/grafana                                                      latest                  f9095e2f0444   4 weeks ago     443MB
grafana/grafana                                                      <none>                  0aa9adb9f6ef   12 months ago   309MB
grafana/grafana                                                      8.3.1                   3b1fc05e7c9a   2 years ago     275MB
root@test123:~#

root@test123:~# docker rmi 3b1fc05e7c9a   0aa9adb9f6ef    f9095e2f0444  
root@test123:~# docker pull  grafana/grafana:8.3.1
Pulling from grafana/grafana
error pulling image configuration: download failed after attempts=6: dial tcp 80.87.199.46:443: i/o timeout

root@test123:~# docker pull  grafana/grafana:8.3.1
Pulling from grafana/grafana
Digest: sha256:259b847ed7e3f58e6056438fd3bc353f48fbe9b77ed3b204ae619ba80e10aed9
Status: Downloaded newer image for grafana/grafana:8.3.1
root@test123:~#

想看看能不能下载 k8s 镜像,毕竟用的最多的就是 k8s,发现不能。k8s 镜像大多是不会被默认自定义源域名代理的,直接 pull 原始的镜像 repos: tags 是不行的。

root@test123:~# docker pull k8s.gcr.io/pause:3.2
root@test123:~# docker pull k8s.gcr.io/pause:3.2
Error response from daemon: Get "https://k8s.gcr.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
root@test123:~#
root@test123:~# docker pull registry.k8s.io/ingress-nginx/controller:v1.3.0
Error response from daemon: Head "https://us-west2-docker.pkg.dev/v2/k8s-artifacts-prod/images/ingress-nginx/controller/manifests/v1.3.0": dial tcp 142.250.141.82:443: i/o timeout
root@test123:~#
root@test123:~# docker pull registry.k8s.io/ingress-nginx/controller:v1.3.0
Error response from daemon: Head "https://us-west2-docker.pkg.dev/v2/k8s-artifacts-prod/images/ingress-nginx/controller/manifests/v1.3.0": dial tcp 74.125.137.82:443: i/o timeout
root@test123:~#
root@test123:~#

源镜像 k8s.gcr.io/prometheus-adapter/prometheus-adapter:v0.9.1, 反复执行的测试过程中,多数会失败,存在成功率,可用性已经成问题了。

root@test123:~#
root@test123:~# docker pull k8s.gcr.io/prometheus-adapter/prometheus-adapter:v0.9.1
Error response from daemon: Get "https://k8s.gcr.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/prometheus-adapter/prometheus-adapter:v0.9.1
Error response from daemon: error parsing HTTP 404 response body: no error details found in HTTP response body: "{\"routes\":{\"docker.test123.com\":\"https://registry-1.docker.io\",\"quay.test123.com/*\":\"https://quay.io\",\"gcr.test123.com/*\":\"https://gcr.io\",\"k8s-gcr.test123.com/*\":\"https://k8s.gcr.io\",\"k8s.test123.com/*\":\"https://registry.k8s.io\",\"ghcr.test123.com/*\":\"https://ghcr.io\",\"cloudsmith.test123.com/*\":\"https://docker.cloudsmith.io\"}}"

root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/prometheus-adapter/prometheus-adapter:v0.9.1
Pulling from prometheus-adapter/prometheus-adapter
error pulling image configuration: download failed after attempts=1: unauthorized: authentication required
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/prometheus-adapter/prometheus-adapter:v0.9.1
Error response from daemon: Head "https://k8s-gcr.test123.com/v2/prometheus-adapter/prometheus-adapter/manifests/v0.9.1": unable to decode token response: invalid character '<' looking for beginning of value
root@test123:~#

root@test123:~# docker pull k8s-gcr.test123.com/library/prometheus-adapter/prometheus-adapter:v0.9.1
Error response from daemon: Head "https://k8s-gcr.test123.com/v2/library/prometheus-adapter/prometheus-adapter/manifests/v0.9.1": unable to decode token response: EOF
root@test123:~# docker pull k8s-gcr.test123.com/prometheus-adapter/prometheus-adapter:v0.9.1
Pulling from prometheus-adapter/prometheus-adapter
Digest: sha256:d025d1a109234c28b4a97f5d35d759943124be8885a5bce22a91363025304e9d
Status: Downloaded newer image for k8s-gcr.test123.com/prometheus-adapter/prometheus-adapter:v0.9.1
k8s-gcr.test123.com/prometheus-adapter/prometheus-adapter:v0.9.1
root@test123:~#

  

源镜像 quay.io/external_storage/nfs-client-provisioner:v3.1.0-k8s1.11 该镜像实测在正常的国内 docker 源还是可以访问的,不具备代表性。

root@test123:~# docker pull quay.io/external_storage/nfs-client-provisioner:v3.1.0-k8s1.11
v3.1.0-k8s1.11: Pulling from external_storage/nfs-client-provisioner
Digest: sha256:cdbccbf53d100b36eae744c1cb07be3d0d22a8e64bb038b7a3808dd29c174661
Status: Downloaded newer image for quay.io/external_storage/nfs-client-provisioner:v3.1.0-k8s1.11
quay.io/external_storage/nfs-client-provisioner:v3.1.0-k8s1.11
root@test123:~#

源镜像 k8s.gcr.io/kube-scheduler:v1.19.13 , 这个是没法下载成功的。

root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
Error response from daemon: Head "https://k8s-gcr.test123.com/v2/kube-scheduler/manifests/v1.19.13": unable to decode token response: EOF
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
v1.19.13: Pulling from kube-scheduler
error pulling image configuration: download failed after attempts=1: unauthorized: authentication required
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
Error response from daemon: unauthorized: No valid credential was supplied.
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
Error response from daemon: Head "https://k8s-gcr.test123.com/v2/kube-scheduler/manifests/v1.19.13": unable to decode token response: invalid character '<' looking for beginning of value
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
v1.19.13: Pulling from kube-scheduler
unauthorized: No valid credential was supplied.
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
v1.19.13: Pulling from kube-scheduler
error pulling image configuration: download failed after attempts=1: unauthorized: authentication required
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/kube-scheduler:v1.19.13
v1.19.13: Pulling from kube-scheduler
error pulling image configuration: download failed after attempts=1: unauthorized: authentication required
root@test123:~#

源镜像 k8s.gcr.io/pause:3.4.1, 经过CF转发,成功率还是很低,可用性已经成问题了。

root@test123:~# docker pull k8s.gcr.io/pause:3.4.1
Error response from daemon: Get "https://k8s.gcr.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/pause:3.4.1
Error response from daemon: Head "https://k8s-gcr.test123.com/v2/pause/manifests/3.4.1": unable to decode token response: EOF
root@test123:~#
root@test123:~# docker pull k8s-gcr.test123.com/pause:3.4.1
3.4.1: Pulling from pause
Digest: sha256:6c3835cab3980f11b83277305d0d736051c32b17606f5ec59f1dda67c9ba3810
Status: Downloaded newer image for k8s-gcr.test123.com/pause:3.4.1
k8s-gcr.test123.com/pause:3.4.1
root@test123:~#
root@test123:~#

4.2 总结  

第一类的 docker 代理的原理都很相似,通过 CF 的 worker 转发,差异化就在 CF 的配置处理上。其实经过一些测试,发现部分域名代理的镜像名,是没法使用的。
k8s 的不少开源业务镜像有自己的域名镜像仓库,导致 CF 的域名代理需要针对不同大类的 repos: tags 额外新增域名映射关系,真到用的时候,这个就很麻烦了。
你需要辨别这个源镜像的 repos 问题。

const routes = {
  ***
  "docker.test123.com": dockerHub,
  "quay.test123.com": "https://quay.io",
  "gcr.test123.com": "https://gcr.io",
  "k8s-gcr.test123.com": "https://k8s.gcr.io",
  ****

还有一个麻烦,各大厂商会对源站的安全做各种限制,类似 nginx 头部注入漏洞,就像上述的问题,我用了别的 hosts 去请求你的 api,直接就 unauthorized 报错了。 pull 对方原始的源 repos: tags 就没有任何问题。

第三个弊端,在本地 pull 自测了 20-30 次左右,界面的请求数已经到了2.4k左右,CF 免费的策略限制是每天 10 万次。 如果你用了 CF Pages 挂博客,还有别的一些项目挂在了 CF。那免费额度一个人用起来就是比较紧张的。关键目前使用 CF worker 镜像加速 docker,抛开稳定性,可用性还有待完善,。

docker 考虑透明代理不是更好的方案么,比如类似 bash remote_pull_docker_img.sh pull.txt 这种,

只需要编辑好 pull.txt 文件中的目标下载的镜像,在执行一条 bash 命令就好了。维护移植性和经济成本是最低的,稳定性也很强。其他的方法还有很多。

内网其他机器想要 pull ,只要连接这个 remote 执行操作,完全没任何侵入性,这个真的非常重要。

docker 透明代理

第二类补充的部分和 CF worker 无关,主要提供对照,已经有 aws 或者 azure 机器了,这个方案选择,就比较灵活了。个人使用的话,比较在乎对方的这个资源消耗负载的问题,1核1G内存20G磁盘 的机器都远远不能承受你的服务,再往上要就要在考虑一下了。如果公司出服务器的钱,那另说。

worker 还有很多其他的功能,比如 AI/LLM 的接口使用,这些也很强大。各种收费限制,目前自用的比较少。

正是这些社区开源博主,才有很多不同的点子刺激到大脑突触,对生活和工作的帮助都很大,集思广益还是很必要。

五、pages  

这个内容,可谈的很多。CF Pages 真的很好用。主要优势是有免费额度且够用的 CDN 加速服务,算是很强了。Github Pages 被诟病的 DNS 污染和网页打开卡慢的问题,CF Pages 算是给了很多免费的优化。除了博客,还有很多其他静态页面配合他的免费 R2/s3 bucket 接口组合待你探索。那他有啥不好的地方? 比如你的博客想长期运营,考虑数据托管和商业化的问题,还是自建 wordpress 会好点。还有爬虫应该会很喜欢 CF Pages,爬取异常的简单方便。甚至面临恶意请求,被刷新访问次数,免费额度直接生成个人的天价账单,这部分云 waf 的限制功能,很多是不免费的。如果只是写写静态博客,没有太多的折腾, CF Pages 算是当下最好的选择了。不得不说对于大多数个人玩家,wordpress 还是太重了。维护他本身,已经不止是要写博客了,打安全补丁,修改自定义多个客户端的展示面板,选择适配业务插件,考虑后续的迁移备份各种各样的,就单单多客户端的页面展示优化能折腾你很久。顺着发展规律,哪天 CF 要收费或者学习 Google 开始关停不盈利的项目时候,也不得不考虑迁移的问题,所以要提前准备好迁移计划。不过只要域名在,家总是还找的到的。以后的事情,以后在处理把。

六、Email Routing  

这个就很迷惑了。你可以使用 CF 的这个服务去自定义你的邮箱域名。比如你有一个邮箱且已经有一个域名 test123.com,可以自定义你喜欢的域名 [email protected]。 但问题是 CF 明确说他自己只是转发邮件,并不提供 pop/imap 的发件服务。想想也是,涉及很多的法律风险,这块的业务比较敏感。如果你使用配置了他的 routing 功能,原则上是半残废的状态。外部可以随意发邮件给 [email protected], 但是 [email protected] 在回复的时候,对方收到的邮件上会提示该邮件由 xx 代发,这样就很丑了。目前的解决办法是选取一些三方的发件服务商去配置发送。整体的配置过程还是比较繁琐的。

自定义域名邮件转发

自定义域名邮件转发

七、后记  

CF 毕竟是一家商业公司,很多哇塞的免费服务,背后可能会用你的内容数据作为商业分析。至少简单的使用,他还是很强的,已经很良心了。不少服务有免费额度,如果不添加信用卡支付信息是不能用的,免费额度用完才会扣费。同时使用他的域名服务,你的域名控制台必须要提前配置他的 DNS 服务器。不少功能对于工作和生活,都有很多的便利性,有点像是一个工具箱。他的网站也在持续跟新 beta 功能吸引用户,不过对于一些服务的使用,还是要保持谨慎,一旦超用费用很惊人。


Comments

Follow me

I'm involved in Kubernetes coding and share developer memes.