使用 Cloudflare 增强公网服务安全性的实践

random-pic-api

简介

前几天在 Cloudflare 上买了一个 dev 域名, 想着使用 Cloudflare 强大的 proxy 功能增加暴露到公网服务的安全性, 今天尝试了一下, 感觉基本满足要求, 下面说说折腾过程.

现状

20250213003153_vrv0wkOy.webp

上图是现在的流量路径:

  1. 路由器将 1000 端口的流量全部转发到雷池 WAF 所在的服务器上(192.168.1.2:1000);
  2. 雷池 WAF 的 1000 端口配置了 HTTPS 证书, 然后在反向代理到局域网内真实的服务器上;

现在的问题是可以通过暴露出去的域名得到我真实的公网 IP 地址, 虽然公网 IP 会不定期变更, 但是感觉还不是特别安全, 所以打算使用 Cloudflare 来增加安全防护.

使用 Cloudflare

我这里以在外网访问家中的 NAS 为例, 方便理解.

20250213004537_s0Ig2NR4.webp

我预期的效果为 通过 https://nas.dong4j.dev 访问家中的 NAS.

我们都知道家用宽带的 80 和 443 端口是被运营商封了的, 为了实现上面的效果, 我们需要对 CloudFlare 有个基础的了解.


CloudFlare CDN 支持的端口

在我们使用 CloudFlare CDN 的时候,对其 CDN 支持的一些端口不太熟悉。以为 CloudFlare 是只允许 80/443 端口走 CDN 的。其实不然,CloudFlare 有一些端口是允许 HTTP/HTTPS 流量走 CDN 的。默认情况下,Cloudflare 会代理发往下面列出的 HTTP/HTTPS 端口的流量:

HTTP 端口HTTPS 端口禁用缓存的端口
804432052
808020532053
888020832082
205220872083
208220962086
208684432087
20952095
2096
8880
8443

意思是假设 nas.dong4j.dev 对应的 IP 为 11.11.11.11, 当我们访问 https://nas.dong4j.dev:2053 时, 会被代理到 https://11.11.11.11:2053, 但是不再上述列表的端口则无法代理, 比如 https://nas.dong4j.dev:12053

所以我们可以利用这点来代理我们内网的服务:

20250213112400_2psIANxI.webp

路由器端口转发配置:

20250213112522_V7f18YZR.webp

雷池代理配置

20250213112754_qL4jNqd7.webp

完成后我们即可通过 https://nas.dong4j.dev:8443 访问内网的 NAS.

20250213113556_3IB6zEr0.webp

但我们最终的目的是使用 https://nas.dong4j.dev, 即在不加端口的情况下访问, 这里就要使用 Cloudflare 的 Origin Rules.

Cloudflare 的 Rules

Cloudflare 包含了众多的 Rules, 相当于过滤器能对进入的流量按照规则一步一步处理:

20250213114150_xF30VFzi.webp

为了实现上述需求, 我们有多种方式:

Page Rules

20250213115101_NT2lFPKB.webp

https://tonas.dong4j.dev 重定向到 https://nas.dong4j.dev:8443

Origin Rules

因为 Page Rules 免费用户最多添加 3 条, 数量比较宝贵, 所以我选择 Origin Rules 来实现我上面的需求.

20250213115516_L2P6Piwy.webp

这样我们访问 https://nas.dong4j.dev 时会自动重定向到 https://nas.dong4j.dev:8443

Cloudflare Workers

最后一种方法是利用功能强大的 Cloudflare Workers,但是需要写代码。一个简单的转发所有请求到新网址的 worker 代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
export default {
async fetch(request) {
const base = "https://nas.dong4j.dev:8443"; // 定义目标域名和端口
const statusCode = 301; // 设置 HTTP 状态码为 301,表示永久重定向

const url = new URL(request.url); // 获取当前请求的 URL 对象
const { pathname, search } = url; // 从 URL 中提取路径(pathname)和查询字符串(search)

const destinationURL = `${base}${pathname}${search}`; // 构建目标 URL,将 base 与请求的路径和查询参数拼接在一起
return Response.redirect(destinationURL, statusCode); // 返回一个 HTTP 重定向响应,指向构建的目标 URL,并使用 301 状态码
},
};

通过 Cloudflare worker,实际上已经能实现我们所有的需求了,但是部署和调试更麻烦,适合高级玩家。Cloudflare worker 另外一个缺点是免费账户每天请求限制 10 万次,当然对于个人用途也足够了。

Cloudflare SSL

在 Cloudflare 购买的 dev 域名可以免费获取 SSL 证书, 有效期为 3 个月, 不过不用担心, Cloudflare 会自动续期并部署, 这一切都不需要我们做任何操作.

这里我们需要了解一下 Cloudflare SSL 相关的基础知识:

20250213120432_XXRyhrfY.webp

Cloudflare 作为中间代理, 流量需要经过 Cloudflare 服务器, 然后再转发到源服务器, 所以这中间需要 2 个 SSL 证书:

  • 浏览器到 Cloudflare 的流量, 通过 边缘证书 来保证数据安全, 这个 边缘证书 由 Cloudflare 管理, 当然你也可以使用自己的证书, 不过需要升级到 Business 计划;
  • Cloudflare 到源服务器的流量, 通过 源服务器证书 来保证数据安全, 这个证书就是我们平时使用 Let’s Encrypt 申请的证书, 这个需要配置到源服务器上, 比如 Nginx;

Cloudflare 真的配得上 『赛博佛祖』 的称号, 免费的服务基本上能够满足绝大多数个人需求, 这里我还从 Cloudflare 白嫖了一个 15 年的免费 TLS 证书:

20250213121227_57gxNRu6.webp

上面一番配置后, 我们的真实 IP 被 Cloudflare 隐藏了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ dig nas.dong4j.dev

; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> nas.dong4j.dev
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48841
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;nas.dong4j.dev. IN A

;; ANSWER SECTION:
nas.dong4j.dev. 1 IN A 104.21.22.178
nas.dong4j.dev. 1 IN A 172.67.206.92

;; Query time: 6 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Thu Feb 13 12:16:14 CST 2025
;; MSG SIZE rcvd: 75

且还具备完善的 SSL 加密, 所以下一步的计划是将暴露到外网的 API 全部使用 Cloudflare 来代理, 增强 Homelab 的安全性.

总结

这是第一次使用 Cloudflare, 我的体会是 Cloudflare 就像一个 Nginx, 能够在上面配置各种规则, 比如缓存, 重定向, 负载均衡等等, 当然这只是其中一小部分功能, 其他的功能我会持续挖掘, 比如强大的 Cloudflare Workers.

参考