Caddy+FRP+Podman实现安全内网穿透
🌐 Caddy + FRP + Podman 内网穿透实战笔记
本笔记记录了如何利用腾讯云服务器(公网)作为中转,穿透香橙派(内网)上的容器服务(如 AList、NocoDB),并使用 Caddy 实现全自动 HTTPS 证书申请与域名分流。
🏗️ 总体架构与端口规划
整个系统的核心逻辑是:外网用户访问域名 ➡️ 云服务器 Caddy (80/443) ➡️ 内部转发至 FRPS (8080) ➡️ FRP 隧道 ➡️ 香橙派 FRPC ➡️ 内网容器应用。
📌 端口分配一览表
| 设备 / 服务 | 内部监听端口 | 对外暴露/安全组端口 | 作用说明 |
|---|---|---|---|
| 云服务器 Caddy | 80, 443 | **80, 443** | 面向外网用户,处理 HTTP/HTTPS 请求与证书申请 |
| 云服务器 FRPS | 52339 (自定义) | 52339 | FRP 隧道通信端口(香橙派与云服务器的接头暗号) |
| 云服务器 FRPS | 8080 (内部) | 无需放行 | 内部 HTTP 虚拟转发端口,供 Caddy 反向代理 |
| 香橙派 AList | 5244 | 无需放行 | 内网实际运行的 Web 服务 |
| Windows 远程 | 3389 | 53389 (云服务器) | 走 TCP 隧道独立暴露的内网桌面端口 |
⚠️ 核心铁律: 同一台服务器上,同一个端口在同一时间只能被一个软件监听。因此,FRP 的通信端口绝不能设为 80 或 443,这两个端口必须完全留给 Caddy。
🛠️ 第一部分:云服务器端配置(FRP 服务端 + Caddy)
建议在云服务器创建统一管理目录(如 /home/ubuntu/app),包含以下三个文件,使用 Podman Compose 一键启动。
1. frps.toml (FRP 服务端配置)
bindPort = 52339 # 隧道连接端口,需在腾讯云安全组放行
vhostHttpPort = 8080 # 内部 HTTP 转发端口,无需在安全组放行
# 安全验证 Token(地下党通关暗号,建议设为复杂的随机字符串)
auth.method = "token"
auth.token = "你的高级自定义密码字符串"
2. Caddyfile (Caddy 反向代理配置)
Caddy 会自动为绑定的域名申请 SSL 证书。注意大括号与空格语法:
# AList 服务
zadg.baidaoya.site {
reverse_proxy 127.0.0.1:8080 {
header_up Host {http.request.host}
header_up X-Real-IP {http.request.remote.host}
header_up X-Forwarded-For {http.request.remote.host}
header_up X-Forwarded-Proto {http.request.scheme}
}
}
# 示例:未来若扩展 NocoDB 服务,直接在此追加
# nocodb.baidaoya.site {
# reverse_proxy 127.0.0.1:8080 {
# header_up Host {http.request.host}
# ...
# }
# }
3. docker-compose.yml (Podman Compose 主配置)
version: '3.8'
services:
frps:
image: docker.io/snowdreamtech/frps:latest
container_name: frps
restart: always
ports:
- "52339:52339"
volumes:
- ./frps.toml:/etc/frp/frps.toml
caddy:
image: docker.io/caddy:latest
container_name: caddy
restart: always
# 🚨 关键:必须走 host 网络模式,否则在容器内无法通过 127.0.0.1:8080 访问旁边的 frps
network_mode: "host"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
🛠️ 第二部分:香橙派端配置(FRP 客户端)
在香橙派上建立管理目录(如 /data/frp)。
1. frpc.toml (FRP 客户端配置)
serverAddr = "你的云服务器公网IP"
serverPort = 52339
auth.method = "token"
auth.token = "你的高级自定义密码字符串" # 🚨 必须与云服务器完全一致
# ---- 网页服务代理(HTTP模式,支持多域名复用 8080) ----
[[proxies]]
name = "zadg"
type = "http"
localIP = "10.88.0.5" # AList容器在Podman内的内网IP(或直接写容器名)
localPort = 5244 # AList容器内部端口
customDomains = ["zadg.baidaoya.site"] # 🚨 必须与Caddyfile中的域名一字不差
# ---- 非网页服务代理(TCP模式,必须独立占用云服务器端口) ----
[[proxies]]
name = "win_remote_desktop"
type = "tcp"
localIP = "192.168.1.100" # 家里 Windows 电脑的局域网静态 IP
localPort = 3389 # Windows 远程桌面固定端口
remotePort = 53389 # 映射到云服务器的公网端口(需在腾讯云安全组放行)
2. podman-compose.yml (FRP 客户端 Compose)
version: '3.8'
services:
frpc:
image: docker.io/snowdreamtech/frpc:latest
container_name: frpc
restart: always
# 🚨 关键:开启 host 模式,打破网络隔离,确保能稳定读取配置并穿透内网
network_mode: "host"
environment:
- TZ=Asia/Shanghai
volumes:
- /data/frp/frpc.toml:/etc/frp/frpc.toml
🚀 第三部分:常用运维与排查口诀
改成 Compose 格式后,日常维护不再需要繁琐的单条容器命令,直接在项目目录下执行:
1. 基础管理命令
- 后台启动服务:
podman-compose up -d - 停止并删除容器:
podman-compose down - 重启单个服务(如修改配置后):
podman-compose restart <服务名> - 查看实时日志:
podman logs -f <容器名>
2. 经典故障排查“剥洋葱法”
当遇到“隧道通了,但域名打不开”时,由内向外排查:
- 看日志确认隧道: 香橙派执行
podman logs frpc,若看到[zadg] start proxy success,说明隧道完全正常。 - 云服务器内网盲测: 在云服务器终端执行
curl -I -H "Host: zadg.baidaoya.site" http://127.0.0.1:8080。 - 若返回
200 OK或302,说明隧道无误,压力在 Caddy 证书 或 安全组。 - 若返回
404,说明frpc.toml里的customDomains字母打错了。 - 看 Caddy 报错: 云服务器执行
podman logs caddy。若卡在证书申请,检查腾讯云安全组是否放行了 80/443,以及 DNS 解析是否已经指向云服务器 IP。
配置
frps的podmancompose
services:
frps:
image: docker.1ms.run/snowdreamtech/frps:latest
container_name: frps
ports:
- "52639:52369"
volumes:
- ./frps.toml:/etc/frp/frps.toml
environment:
TZ: "Asia/Shanghai"
networks:
- podman-network
security_opt:
- no-new-privileges:true
networks:
podman-network:
external: true
name: znetfrpc的podmancompose
services:
frpc:
image: docker.io/snowdreamtech/frpc:latest
container_name: frpc
volumes:
- ./frpc.toml:/etc/frp/frpc.toml
environment:
TZ: "Asia/Shanghai"
networks:
- podman
security_opt:
- no-new-privileges:true
networks:
podman:
external: truefrps的frps.toml
bindPort = 52369
vhostHttpPort = 8080
auth.method = "token"
auth.token = "ccef2d7f141dc1"frpc的frps.toml
serverAddr = "49.111.111.111"
serverPort = 52639
auth.method = "token"
auth.token = "ccef2d7f141dc1"
# 映射 NocoDB 容器
[[proxies]]
name = "zadg"
type = "http"
localIP = "10.88.0.5"
localPort = 5244
customDomains = ["zadg.baidaoya.site"]💡 后续扩展新 Web 服务公式
日后若想在香橙派上上线新服务(例如 NocoDB):
- 香橙派端: 在
frpc.toml里追加一个[[proxies]]块,设置name、localPort和新的二级域名(如nocodb.baidaoya.site),随后重启frpc。 - 云服务器端: 在
Caddyfile里直接复制一份反向代理配置,改成新的二级域名,随后重启caddy。 - 域名解析: 在腾讯云后台为新二级域名添加一条 A 记录,指向云服务器公网 IP,即可瞬间无感秒开 HTTPS 直连!