Cloudflare Tunnel零端口暴露:香港服务器微服务网关完整配置与内网服务安全发布
传统服务发布必须在防火墙开放 80/443 端口,暴露在公网上的每个开放端口都是潜在攻击面。Cloudflare Tunnel(cloudflared) 通过反向隧道彻底改变这一模式:服务器主动向 Cloudflare 建立出站连接,外部流量经由 Cloudflare 网络转入,服务器本身零入站端口暴露——防火墙可以全部关闭,攻击者扫描到的只有一台”闭口”服务器。
一、传统发布 vs Tunnel 对比
| 维度 | 传统 Nginx 发布 | Cloudflare Tunnel |
|---|---|---|
| 服务器入站端口 | 至少开放 80/443 | 零(防火墙全关) |
| DDoS 防护 | 依赖高防 IP | Cloudflare 全球网络吸收 |
| SSL 证书 | 需要 certbot 申请 | 自动(Cloudflare Edge) |
| 源站 IP 隐藏 | 难(Cloudflare 代理也可能泄漏) | 完全隐藏 |
| 内网服务发布 | 需要 NAT/端口映射 | 直接发布,无需 NAT |
| 访问控制 | 需要自行配置 Auth | Cloudflare Access 统一 |
二、安装 cloudflared
<code"># Ubuntu/Debian 安装 curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \ -o cloudflared.deb dpkg -i cloudflared.deb cloudflared --version # 认证(需要 Cloudflare 账号,绑定到你的域名) cloudflared tunnel login # 浏览器弹出授权页面,选择对应域名授权 # 成功后在 ~/.cloudflared/cert.pem 生成证书
三、创建和配置隧道
<code"># 创建命名隧道 cloudflared tunnel create hk-production # 输出:Created tunnel hk-production with id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # 同时在 ~/.cloudflared/ 生成隧道凭证文件 # 将凭证文件移到系统目录(用于 systemd 服务) mkdir -p /etc/cloudflared cp ~/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json /etc/cloudflared/ cp ~/.cloudflared/cert.pem /etc/cloudflared/ # 查看已创建的隧道 cloudflared tunnel list
<code"># /etc/cloudflared/config.yml(隧道路由配置)
tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /etc/cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
# 入口规则(按域名路由到不同后端服务)
ingress:
# 主站
- hostname: yourdomain.com
service: http://localhost:8080
originRequest:
connectTimeout: 10s
noTLSVerify: false
# API 服务
- hostname: api.yourdomain.com
service: http://localhost:8000
originRequest:
httpHostHeader: api.yourdomain.com
# 内部监控(需要 Cloudflare Access 保护)
- hostname: grafana.yourdomain.com
service: http://localhost:3000
# 数据库管理工具(仅内网可用,Access 强制认证)
- hostname: adminer.yourdomain.com
service: http://localhost:8888
# WebSocket 应用
- hostname: ws.yourdomain.com
service: http://localhost:3001
originRequest:
noTLSVerify: true
# SSH 访问(通过 Cloudflare Access 代理)
- hostname: ssh.yourdomain.com
service: ssh://localhost:22
# 兜底规则(必须有,处理未匹配请求)
- service: http_status:404<code"># 为每个 hostname 在 Cloudflare DNS 创建 CNAME 记录 cloudflared tunnel route dns hk-production yourdomain.com cloudflared tunnel route dns hk-production api.yourdomain.com cloudflared tunnel route dns hk-production grafana.yourdomain.com cloudflared tunnel route dns hk-production adminer.yourdomain.com cloudflared tunnel route dns hk-production ws.yourdomain.com cloudflared tunnel route dns hk-production ssh.yourdomain.com # 这些 CNAME 指向 Cloudflare 隧道节点,不暴露真实 IP
四、systemd 服务(开机自启)
<code"># 安装 cloudflared 系统服务 cloudflared service install # 或手动创建 systemd 服务 cat > /etc/systemd/system/cloudflared.service << 'EOF' [Unit] Description=Cloudflare Tunnel After=network.target [Service] Type=simple User=cloudflared ExecStart=/usr/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run Restart=on-failure RestartSec=5s StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target EOF useradd -r -s /bin/false cloudflared chown cloudflared:cloudflared /etc/cloudflared/*.json /etc/cloudflared/config.yml systemctl daemon-reload systemctl enable --now cloudflared systemctl status cloudflared
五、UFW 全闭防火墙(仅保留出站)
<code"># Tunnel 建立后,服务器无需任何入站端口 # 可以将防火墙设置为全拒入站 ufw default deny incoming ufw default allow outgoing # 如果需要保留 SSH 直连(调试用),只允许特定 IP # ufw allow from 你的家庭IP to any port 22 ufw enable ufw status # 理想状态:没有任何 ALLOW (v6) 入站规则
六、Cloudflare Access 保护内部服务
<code">
对需要身份验证的服务(Grafana/Adminer/SSH)配置 Cloudflare Access:
1. 登录 Cloudflare Zero Trust 控制台(one.dash.cloudflare.com)
2. Access → Applications → Add an Application → Self-Hosted
- Application domain: grafana.yourdomain.com
- Session duration: 8h
3. 创建访问策略:
Policy name: 工程师访问
Action: Allow
规则:
- Emails: alice@yourdomain.com, bob@yourdomain.com
- 或者 Email domain: yourdomain.com(整个域名)
附加条件(提高安全性):
- Country: China, Hong Kong, Singapore(地理位置限制)
4. 配置身份提供商:
Settings → Authentication → Add new
→ 选择 Google Workspace / GitHub / One-Time PIN
5. 用户访问 grafana.yourdomain.com 时:
→ 跳转到 Cloudflare Access 登录页
→ 验证通过后访问 Grafana
→ 8小时内无需再次验证(Session)
七、通过 Cloudflare Access 代理 SSH
<code"># 本地 ~/.ssh/config 配置(员工机器)
Host ssh.yourdomain.com
ProxyCommand cloudflared access ssh --hostname %h
User deploy
IdentityFile ~/.ssh/id_ed25519
# 连接时自动通过 Cloudflare Access 验证身份
ssh ssh.yourdomain.com
# 效果:
# 1. cloudflared 打开浏览器,验证 Cloudflare Access 身份
# 2. 验证通过,SSH 连接建立
# 3. 服务器的 22 端口从未对公网暴露八、流量监控与健康检查
<code"># 查看隧道连接状态 cloudflared tunnel info hk-production # 实时查看隧道日志 journalctl -u cloudflared -f | grep -E "registered|error|connection" # Cloudflare 控制台查看流量 # Zero Trust → Networks → Tunnels → hk-production # 可以看到:请求量、延迟分布、连接节点等 # 健康检查:从隧道测试各服务 curl -v https://api.yourdomain.com/health curl -v https://grafana.yourdomain.com # 会跳转到 Access 登录
九、多节点隧道(高可用)
<code"># 同一个隧道可以在多台服务器上运行(自动负载均衡) # 在第二台香港服务器上运行同一个隧道: # 复制凭证文件和配置到第二台服务器 scp /etc/cloudflared/xxxxxxxx-*.json root@第二台服务器IP:/etc/cloudflared/ scp /etc/cloudflared/config.yml root@第二台服务器IP:/etc/cloudflared/ # 在第二台服务器启动 cloudflared systemctl start cloudflared # Cloudflare 控制台 → Tunnels → hk-production # 可以看到两个 connector,流量自动在两台服务器间分配 # 任意一台宕机,流量自动切换到另一台(无感知)
十、总结
Cloudflare Tunnel 是香港服务器安全架构的终极形态:零端口暴露意味着攻击者无法直接触达服务器,DDoS 攻击被 Cloudflare 全球网络在边缘层吸收,Cloudflare Access 提供企业级身份认证。对于对安全要求高的业务(金融、用户数据、企业内部系统),这套方案应当是标配而非可选项。