在家庭服务器上通过 Cloudflare Tunnel + Caddy 暴露多个 Web 应用
Source: Dev.to
介绍
在家庭服务器上发布多个 Web 应用时,获取静态 IP、管理 SSL 证书以及处理复杂的安全设置往往会成为瓶颈。本文阐述了一种实用方法,利用 Cloudflare Tunnel、Caddy 和 WSL2 的组合,安全地暴露多个 Web 应用。
架构层级
| 层 | 角色 |
|---|---|
| Cloudflare Tunnel | 将你的家庭服务器连接到互联网(通过 cloudflared 命令配置)。 |
| Caddy | 充当反向代理,添加安全头部,并收集访问日志。 |
| App Services | 运行在不同端口上的 Web 应用(例如 Streamlit)。 |
Caddy 通过 Cloudflare Tunnel 接收请求,并将其转发到相应的应用。URL 采用 service_name.example.org 的模式。
- App Services:
8xxx范围的端口(应用执行端口) - Caddy:
9xxx范围的端口(反向代理端口) - URL 命名约定:
{service_name}.example.org
如何编写 Caddyfile
在 Caddy 2.x 中,先声明站点地址,然后写反向代理和日志指令。
:9530 {
log {
output file /var/log/caddy/access.log {
roll_size 10mb
roll_keep 30
}
format json
}
reverse_proxy localhost:8530 {
header_up X-Forwarded-Proto https
}
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
}
}
该配置的作用
- 反向代理:将 9530 端口的流量转发到
localhost:8530上的应用。 - 安全头部:添加
Strict-Transport-Security和X-Content-Type-Options。 - 访问日志:以 JSON 格式写入
/var/log/caddy/access.log,当文件达到 10 MiB 时滚动,并保留最近的 30 个文件。
注意: 通用的
Content‑Security‑Policy: default-src 'self'对于加载外部资源的应用(如 Streamlit)可能过于严格。请根据实际需求为每个应用调整 CSP。
提供的安全层级
| 层级 | 保护内容 |
|---|---|
| Cloudflare | WAF、DDoS 缓解、自动 SSL |
| cloudflared | 隐蔽家庭 IP 地址 |
| Caddy | 添加安全头部,记录请求 |
| Application authentication | OTP/PIN 或其他访问控制 |
| Data protection | 使用 Fernet 加密敏感数据 |
| Cloudflare Access(可选) | SSO 与多因素认证 |
Cron 设置(每日日志分析)
每晚会运行一个 cron 任务,分析 Caddy 的访问日志并通过 Gmail 发送可疑活动警报。
55 23 * * * /home/user/logger/daily_log_analyzer.py
分析工作流
- 提取 当天的 JSON 格式 Caddy 日志条目。
- 聚合 状态码、服务、IP 地址和 User‑Agent 字符串。
- 发送 聚合数据至 Gemini 2.5 Flash 进行模式检测。
- 通过 Gmail 通知任何发现。
通过将 Cloudflare Tunnel 与 Caddy 结合使用,你可以在没有静态 IP 的情况下暴露家庭服务器上的服务,同时受益于自动 SSL、WAF/DDoS 保护以及企业级安全头部。此方案让个人开发环境的安全性堪比生产级部署。