Cloudflare Tunnel提供了一种安全的方法来连接你的网络服务到 Cloudflare 网络,而不需要开放服务器的端口到公网上,或者在 DNS 上直接暴露服务器的 IP 地址。这种方式能够帮助越过 DNS 阻断,并增强服务的安全性。

由于服务的真实 IP 地址不会在 DNS 查询中直接暴露,Cloudflare Tunnel 可以帮助绕过基于 DNS 的阻断。用户的请求首先到达 Cloudflare 的网络,然后通过建立好的安全隧道转发到后端的服务。这意味着,即使某些 DNS 请求被拦截或阻断,用户的请求仍然可以通过 Cloudflare 的网络到达目标服务。

Cloudflare Tunnel 可以让服务器主动访问 Cloudflare (CF) 的 CDN 节点。这样服务器完全不需要接受任何外来连接,增强安全性。此外,Cloudflare Tunnel 也可以让服务器处于 NAT 后面,无需公网 IP 也可以提供 Web 等服务。

要使用 Cloudflare Tunnel,相应域名必须在 CF 解析,且服务器必须能够访问最近的 CF 节点。

本文以搭建 memos 为例子,类似于一个私人微博的开源项目

https://github.com/usememos/memos

demo-screenshot

域名以二级域名:memos.abc.com 为例。

memos安装

直接docker compose起手:

1
2
3
4
5
6
7
8
9
10
$ mkdir ~/memos && cd ~/memos
$ echo "services:
memos:
image: neosmemo/memos:stable
container_name: memos
volumes:
- ~/.memos/:/var/opt/memos
ports:
- \"5230:5230\"" | sudo tee docker-compose.yml > /dev/null
$ docker compose up -d

访问http://localhost:5230,即可打开memos

Nginx设置反向代理(非必要步骤)

安装Nginx:

添加memos的反向代理配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ echo "server {
listen 80;
listen [::]:80;
server_name memos.abc.com;

location / {
proxy_pass http://localhost:5230;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}" | sudo tee /etc/nginx/conf.d/memos.abc.com.conf > /dev/null

重启Nginx,使配置生效:

1
$ sudo systemctl restart nginx

报错:[Nginx: Failed to start A high performance web server and a reverse proxy server](https://stackoverflow.com/questions/51525710/nginx-failed-to-start-a-high-performance-web-server-and-a-reverse-proxy-server)

您已经有一个进程绑定到 HTTP 端口 80。您可以运行命令 sudo lsof -i:80 来获取使用该端口的进程列表,然后尝试停止正在使用80端口的进程sudo fuser -k 80/tcp

对我来说,这个错误是由端口 80 上已有的 default nginx 站点引起的。删除默认站点有效。

1
2
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo service nginx restart

安装Cloudflared

安装

1
$ curl -L 'https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64' -o cloudflared && chmod +x cloudflared

登录

1
$ ./cloudflared tunnel login

输入命令后,终端会给出一个登陆地址,我们拷贝到浏览器里面打开,选择需要授权的域名,完成后将生成一个证书文件 ~/.cloudflared/cert.pem

创建隧道

授权完以后,我们需要创建隧道。一般建议一台服务器创建一个隧道。

1
2
3
cloudflared tunnel create <隧道名字>
# 比如
$ ./cloudflared tunnel create memos

创建完以后,会输出隧道的一个UUID,记录下来Tunnel ID。

创建 DNS 记录

我们需要把域名指向到对应的隧道。

1
2
3
4
5
6
cloudflared tunnel route dns <隧道名字> <域名>
# 比如一级域名(和Web界面不一样,不需要输入@)
cloudflared tunnel route dns memos abc.com
# 又比如二级域名
cloudflared tunnel route dns memos memos.abc.com
$ ./cloudflared tunnel route dns memos memos.abc.com

这时候,Cloudflare会自动添加一条CNAME记录到对应的域名。

对于多个其他域名,我们需要登录Cloudflare的Web控制台,对应添加CNAME记录,记录值是:

1
2
3
4
5
<隧道UUID>.cfargotunnel.com

比如

12345-123-123-123-12345.cfargotunnel.com

img

cloudflared 配置

开始配置Cloudflared,先编辑一个配置文件vim ~/.cloudflared/config.yml

输入下面的内容(根据自己要求编辑)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tunnel: <隧道UUID>
credentials-file: /root/.cloudflared/<隧道UUID>.json
protocol: h2mux
ingress:
# 第一个网站,连接到本地的80端口
- hostname: <域名1.com>
service: http://localhost:80
# 第二个网站,https协议,连接到本地的443端口,禁用证书校验(用于自签名SSL证书)
- hostname: <域名2.com>
service: https://127.0.0.1:443
originRequest:
noTLSVerify: true
originServerName: <域名2.com>
# 第三个网站,8012端口,泛域名
- hostname: <*.域名3.com>
service: http://localhost:8012
# 第四个,反代MySQL sock服务
- hostname: <mysql.域名4.com>
service: unix:/tmp/mysql.sock
# 第五个,反代SSH服务
- hostname: <ssh.域名5.com>
service: ssh://localhost:22
- service: http_status:404

更多支持的服务和配置方式,参考帮助文档:Supported protocols

我这里配置:

1
2
3
4
5
6
7
$ echo "tunnel: <隧道UUID>
credentials-file: /root/.cloudflared/<隧道UUID>.json

ingress:
- hostname: memos.abc.com
service: http://localhost:80
- service: http_status:404" | sudo tee ~/.cloudflared/config.yml > /dev/null

验证下配置有没有问题

1
$ ./cloudflared tunnel ingress validate

再测试下规则是否命中

1
$ ./cloudflared tunnel ingress rule https://memos.abc.com

如果没问题,OK,一切妥当,我们开始测试

1
$ ./cloudflared --loglevel debug --transport-loglevel warn --config ~/.cloudflared/config.yml tunnel run <隧道UUID>

终端会输出一大堆log,但没有红色报错,那就没问题。

登陆Cloudflare Zero Trust的Web控制台,左边选择Networks-Tunnels,可以看到隧道已经跑起来了,状态是HEALTHY

image-20240710163347443

按下Ctrl+z,先停掉刚才启动的服务。

配置为系统服务

1
$ ./cloudflared service install

创建系统服务后,配置文件会被拷贝到 /etc/cloudflared/config.yml

在创建系统服务后,你可以使用 systemctl 命令来管理服务。

1. 启动服务

要启动 cloudflared 服务,使用以下命令:

1
sudo systemctl start cloudflared

2. 停止服务

要停止 cloudflared 服务,使用以下命令:

1
sudo systemctl stop cloudflared

3. 重启服务

要重启 cloudflared 服务,使用以下命令:

1
sudo systemctl restart cloudflared

4. 查看服务状态

要查看 cloudflared 服务的状态,使用以下命令:

1
2
3
bash
复制代码
sudo systemctl status cloudflared

这将显示服务的运行状态、最近的日志等信息。

5. 启用服务开机自启动

要设置 cloudflared 服务在系统启动时自动启动,使用以下命令:

1
sudo systemctl enable cloudflared

6. 禁用服务开机自启动

要禁用 cloudflared 服务在系统启动时自动启动,使用以下命令:

1
sudo systemctl disable cloudflared

7. 查看服务日志

要查看 cloudflared 服务的日志,使用 journalctl 命令:

1
sudo journalctl -u cloudflared

访问站点

cloudflared启动后

打开网址 memos.abc.com,可看到我们已能成功访问到搭建的 memos 站点。