不开端口,不配 DNS,用树莓派在家搭一个公网可访问的 Web 服务

原文:Cloudflare Argo Tunnel with Rust+Raspberry Pi,作者 Steven Pack

家里有一块吃灰的树莓派,一直想用来跑点什么,但总绕不开两个问题:家庭宽带没有固定 IP,路由器也不想随便开放端口。

这篇文章记录的,就是 Cloudflare 一位工程师的实验:把树莓派、Rust 异步 Web 框架和 Cloudflare Tunnel 三者结合起来,在完全不动路由器、不配 DNS 记录的前提下,把树莓派上的 Web 服务暴露到公网。

整个过程出乎意料地顺滑。


问题在哪里

想让家里的机器对外提供服务,传统方式大概有这几条路:

  • 动态域名解析(DDNS):家庭宽带 IP 会变,得在路由器上跑一个 DDNS 客户端,不稳定,配置也烦琐
  • 端口映射:在路由器上开放指定端口转发到内网机器,等于把内网暴露了一个口子,有安全风险
  • 租云服务器:花钱,而且家里的树莓派就成了摆设

Cloudflare Tunnel(原名 Argo Tunnel)的思路完全不同:让内网机器主动向外建立一条持久连接,流量通过这条连接进来,不需要任何入站规则。


原理:反向隧道

整个架构用一句话描述就是:

树莓派上的 cloudflared 客户端,向最近的 Cloudflare 节点建立一条出站的 HTTP/2 长连接;当外网用户请求你的域名时,Cloudflare 把请求通过这条连接反向推送给树莓派,树莓派处理后再原路返回。

几个关键点:

  • 流量方向是"出站"的。树莓派只需要能访问外网,不需要任何端口对外开放
  • 安全性由证书保证cloudflared 登录时会生成一个证书文件(cert.pem),隧道连接用它来做身份验证
  • Cloudflare 负责域名解析和 HTTPS。你只需要有一个托管在 Cloudflare 上的域名,其余的它帮你搞定

准备工作

需要以下几样东西:

  • 一块树莓派(作者用的是 Raspberry Pi 3 Model B),已安装 Raspbian
  • 一个托管在 Cloudflare 的域名
  • 树莓派能正常访问外网

确认树莓派联网正常,最简单的方法是 curl 一下:

bash 复制代码
curl -I https://www.cloudflare.com

看到 HTTP/2 200 就说明出站连接没问题。


第一步:安装 cloudflared

cloudflared 是 Cloudflare 提供的隧道客户端。树莓派是 ARM 架构,需要下载对应版本:

bash 复制代码
wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
mkdir argo-tunnel
tar -xvzf cloudflared-stable-linux-arm.tgz -C ./argo-tunnel
cd argo-tunnel
./cloudflared --version

如果看到版本号输出,就说明可以正常运行了。


第二步:登录并授权域名

运行登录命令:

bash 复制代码
./cloudflared login

它会输出一个 URL,让你在浏览器里打开(因为树莓派是无头环境,复制到自己的电脑浏览器里打开就行)。登录 Cloudflare 账号后,选择你想用来建隧道的域名,点击授权。

授权成功后,树莓派控制台会显示:

复制代码
You have successfully logged in.
If you wish to copy your credentials to a server, they have been saved to:
/home/pi/.cloudflared/cert.pem

这个 cert.pem 就是隧道的凭证文件,后续都会用到它。


第三步:用内置 Hello World 验证隧道

在正式部署自己的服务之前,先用 cloudflared 自带的 Hello World 模式验证隧道是否通:

bash 复制代码
./cloudflared --hostname tunnel.yourdomain.com --hello-world

tunnel.yourdomain.com 换成你自己的子域名。启动后会看到类似这样的日志:

复制代码
INFO[0005] Connected to LAX
INFO[0010] Connected to SFO-DOG

这说明客户端已经连上了 Cloudflare 节点。此时在浏览器里访问 https://tunnel.yourdomain.com,应该能看到一个 Hello World 页面。

路由器没动,防火墙没动,DNS 没手动配置,就这样通了。


第四步:用 Rust 跑一个真正的 Web 服务

Hello World 验证完隧道没问题,下一步换成一个真实的 Rust Web 服务。原博客作者选择了 Gotham,一个基于异步 I/O 的 Rust Web 框架。

首先安装 Rust 工具链:

bash 复制代码
curl https://sh.rustup.rs -sSf | sh
# 安装完成后刷新环境变量
source $HOME/.cargo/env

克隆 Gotham 并编译 hello_world 示例:

bash 复制代码
git clone https://github.com/gotham-rs/gotham
cd gotham/examples/hello_world
cargo build

树莓派编译比较慢,cargo build 花了将近 8 分钟。编译完成后运行:

bash 复制代码
cd ../../target/debug
./gotham_examples_hello_world
# Listening for requests at http://127.0.0.1:7878

Web 服务现在监听在本地 7878 端口。把隧道指向它:

bash 复制代码
./cloudflared --hostname gotham.yourdomain.com http://127.0.0.1:7878

访问 https://gotham.yourdomain.com,Rust 服务的响应就出来了。


第五步:配置开机自启

每次 SSH 进去手动启动太麻烦,需要让两个进程在系统启动时自动运行。

配置 cloudflared 自启

先把证书和配置文件放到系统目录:

bash 复制代码
sudo cp ~/.cloudflared/cert.pem /etc/cloudflared
sudo nano /etc/cloudflared/config.yml

config.yml 内容:

yaml 复制代码
hostname: gotham.yourdomain.com
url: http://127.0.0.1:7878

然后安装为系统服务:

bash 复制代码
sudo ./cloudflared service install

cloudflared 会自动注册成 systemd 服务,开机自启。

配置 Rust Web 服务自启

把编译好的二进制文件复制到一个稳定的位置:

bash 复制代码
cp target/debug/gotham_examples_hello_world /home/pi/argo-tunnel/server/bin/

编辑 /etc/rc.local,在 exit 0 之前加一行:

bash 复制代码
/home/pi/argo-tunnel/server/bin/gotham_examples_hello_world &

重启树莓派,SSH 回来后检查两个进程是否都在运行:

bash 复制代码
sudo ps -aux | grep cloudflared
sudo ps -aux | grep gotham

看到进程就说明配置成功了。


这件事有意思在哪

纯粹的技术实现层面,这个方案并不复杂,每一步都很直白。但把这几样东西组合在一起,解决的问题其实很实际:

家宽没有固定 IP 不再是障碍。 Cloudflare Tunnel 的连接是从内网发起的,IP 怎么变都无所谓,隧道会自动重连。

不需要开防火墙端口。 对家庭网络来说,不在路由器上开洞,安全性本质上好了一个层次。所有流量都经过 Cloudflare,还能顺带享受 DDoS 防护和 HTTPS。

Rust 在资源受限设备上表现不错。 Gotham 是异步框架,内存占用低,这一点在只有 1GB 内存的树莓派上很重要。编译慢是确实慢,但一次编译、长期运行,是嵌入式类场景的合理取舍。

当然,这个方案也有局限。Cloudflare Tunnel 需要你有一个托管在 Cloudflare 上的域名,流量也会经过 Cloudflare 的节点,如果对数据经过第三方有顾虑,就需要另想办法。


小结

这个实验的路径是这样的:

  1. 树莓派联网,安装 cloudflared
  2. cloudflared login 授权域名,获取证书
  3. 先用内置 Hello World 验证隧道通路
  4. 安装 Rust,编译 Gotham 示例,把隧道指向本地 Web 服务
  5. 配置 systemd 和 rc.local 实现两个进程的开机自启

整个过程没有动过路由器,没有手动配过 DNS,家里的树莓派就这样对外提供了一个有正经域名和 HTTPS 的 Web 服务。

对于那些一直想折腾树莓派但被网络配置挡在门外的人来说,这条路值得一试。


相关推荐
笨熊呆呆瓜1 小时前
【可靠性配置】华为M-LAG防环机制
网络
郑寿昌1 小时前
虚幻引擎UE5 Lumen兼容PBR材质全解析
服务器·网络·材质
奇妙之二进制2 小时前
zmq源码分析之session
网络
奇妙之二进制2 小时前
zmq源码分析之PUSH/PULL 模式的负载均衡分析
运维·网络·负载均衡
早起傻一天~G2 小时前
vue2+element-UI表单封装
前端·vue.js·ui
pixcarp2 小时前
Nginx实战部署与踩坑总结 附带详细配置教程
服务器·前端·后端·nginx·golang
IP老炮不瞎唠2 小时前
什么是Grok?以及如何解决卡顿、风控问题
服务器·网络
Live&&learn2 小时前
Vue项目打包后内联字符串不显示的原因
前端·javascript·vue.js
淼淼爱喝水2 小时前
eNSP 防火墙 NAT 策略配置(Easy IP/No-PAT/NAPT/ 黑洞路由)
服务器·网络·tcp/ip·ensp·防火墙·nat