Cloudflare Tunnel零端口暴露:香港服务器微服务网关完整配置与内网服务安全发布

Cloudflare Tunnel零端口暴露:香港服务器微服务网关完整配置与内网服务安全发布

传统服务发布必须在防火墙开放 80/443 端口,暴露在公网上的每个开放端口都是潜在攻击面。Cloudflare Tunnel(cloudflared) 通过反向隧道彻底改变这一模式:服务器主动向 Cloudflare 建立出站连接,外部流量经由 Cloudflare 网络转入,服务器本身零入站端口暴露——防火墙可以全部关闭,攻击者扫描到的只有一台”闭口”服务器。


一、传统发布 vs Tunnel 对比

维度传统 Nginx 发布Cloudflare Tunnel
服务器入站端口至少开放 80/443零(防火墙全关)
DDoS 防护依赖高防 IPCloudflare 全球网络吸收
SSL 证书需要 certbot 申请自动(Cloudflare Edge)
源站 IP 隐藏难(Cloudflare 代理也可能泄漏)完全隐藏
内网服务发布需要 NAT/端口映射直接发布,无需 NAT
访问控制需要自行配置 AuthCloudflare 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 提供企业级身份认证。对于对安全要求高的业务(金融、用户数据、企业内部系统),这套方案应当是标配而非可选项。

Telegram