Blog
Cloudflare Tunnel 暴露内网服务的安全姿势
最早我在路由器上做端口映射:公网:8443 → 家里反代。朋友访问博客、自己远程看图床,都靠这一条 DNAT。后来故事按「迁移」展开——不是功能清单,是一条路为什么走不下去、另一条路怎么接上。
写这篇时距离彻底关掉最后一个入站端口大约三个月。情绪已经平了,细节还记得。适合在你开始嫌映射麻烦、又还没下决心迁的时候读。
端口映射时代:能用,但总在抢修
第一阶段大约半年。光猫桥接,主路由有公网 IP 的日子里,映射很诚实:开 443,指到内网 Caddy,证书用 Let's Encrypt 或干脆路由器抛 SSL。
问题成串出现。运营商偶尔换 CGNAT,公网 IP 一夜之间从「真」变成「假」,映射形同虚设。DDNS 客户端还在报成功,外面已经连不进来。有公网时,扫描海立刻贴上来:443 上的爆破、奇怪路径探测、偶发的大流量探测把上行打满。
我还试过改端口、只允许某些国家 IP、在反代上堆限流。每一层都能挡一点,但家里 IP 直接暴露这件事没变。出差住酒店,SSH 还走另一个映射端口,心里更慌。
某次维护忘了关「临时 8080 测试映射」,第二天日志里已经是陌生 UA 的狂欢。那晚我写下:入站洞越少越好,最好是零。
转折:CGNAT 收回最后的侥幸
真正逼我迁移的是一次持续两周的 CGNAT。客服口径含糊,端口映射彻底死。我用 VPS 反代回连家里,配得像毛线球:VPS nginx 指回 WireGuard 地址,证书挂 VPS,家庭源站只听内网。
能用。但每加一个 hostname,就要改 VPS 配置、重载、查防火墙。WireGuard 断了,整站全挂,且排查路径跨两台机器。我意识到自己在「手工实现一个劣质 Tunnel」。
同期 Cloudflare 的 Tunnel 已经够稳:出站连接,家里不用开入站;边缘证书;还可套 Access。迁移动机从「尝鲜」变成「停止和运营商赌公网」。
迁移周:先搬一个不痛的站点
我没有一天切全部。第一周只搬静态博客。
云端建 Tunnel,本机用 compose 跑 cloudflared,token 放 .env:
services:
tunnel:
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
DNS 切到 Cloudflare 橙云。源站只监听内网或 localhost,路由器上删掉 80/443 入站规则。删的那一刻手指是抖的——像拆掉多年习惯的安全毯,尽管那条毯早就破了。
博客通了之后,我把「端口映射检查」从每周待办划掉。取而代之的是:看 Tunnel 是否在线、源站容器是否在听。
第二周:私人服务套 Access
Immich、Grafana、面板类服务不能只靠应用密码。我给 hostname 套 Access:邮箱 OTP,或绑定自己的身份源。策略改完用无痕窗口验证——未登录应直接挡在边缘,连登录页都不该随手刷到。
服务令牌留给自动化,不把个人登录 cookie 预期套在脚本上。有一次策略写错邮箱域名,自己被锁在外面,Zero Trust 日志里一行拒绝原因,改完即愈。比 SSH 锁门好恢复:控制面在云上,不依赖我还进得了家宽。
主机名分成三类:迁移清单的核心
笔记里强制分类,避免「所有东西都挂同一个域名心态」:
- 公开可读:博客、静态页。Tunnel + 常规缓存即可,回源不要带管理接口。
- 私人但常用:Immich、RSS、看板。Tunnel + Access。
- 绝不能露:SSH、数据库、路由器管理、NAS 管理口。走 WireGuard,不进 Tunnel。
第三类一破防就是整网风险。隧道很方便,不等于所有端口都该送上 CDN。迁移时最容易犯的错,是把「既然 Tunnel 通了」推成「SSH 也走个网页版吧」。我克制了。
和 WireGuard 重新分工
| 需求 | 迁完后的选择 |
|---|---|
| 给朋友看一个 HTTPS 站点 | Tunnel |
| 自己挂载 NFS / 用 SMB | WireGuard |
| 临时演示内网 Web | Tunnel + Access |
| 管理 SSH、交换机 | WireGuard |
两者共存:WG 是「我进入内网的钥匙」,Tunnel 是「把某个 Web 应用安全递到公网」。端口映射时代那张「公网端口表」归档进 git 历史,不再维护。
迁完后的摩擦与残留习惯
源站只绑 127.0.0.1 时,cloudflared 若在另一网络命名空间会够不着,要改成 Docker 服务名或合适的 host 网关。橙云下证书由 CF 处理,源站 HTTP 即可,我曾在源站硬上 HTTPS,绕了一圈才明白多余。
多 hostname 时,一个 Tunnel 配多 ingress,按主机名分流,默认 catch-all 回到 404,避免扫到的路径回源到奇怪服务。Tunnel 副本多了会抢,token 泄露就重建——这些写进运维笔记,不再写进「紧急时靠记忆」。
搬家三个月后,路由器入站规则短得令人愉快。暴露面收敛,比在公网 IP 上堆 WAF 规则更符合家庭场景。端口映射不是技术落后,是威胁模型和运营商现实变了;Tunnel 接过的,是「家宽不再当服务器入口」这件事。
若你还处在「映射还能凑合」的阶段,不必为了追新立刻迁。等到第一次 CGNAT 或第一次被扫到心慌,再打开这篇当迁移剧本即可。路径我走过一遍,坑大多标在上面了。