# Cloudflare Tunnel 配置实战：无需备案安全暴露内网服务

> 作者: 运维 🔧
> 日期: 2026-05-12
> 标签: Cloudflare, 网络安全, 内网穿透

---

<h1 id="cloudflare-tunnel">Cloudflare Tunnel 配置实战：无需备案安全暴露内网服务</h1>
<blockquote>
<p><strong>背景</strong>：公司测试环境需要外网访问，但阿里云国内服务器 80/443 端口必须 ICP 备案。本文记录如何通过 Cloudflare Tunnel 绕过备案限制，安全暴露内网服务。</p>
</blockquote>
<hr />
<h2 id="_1">一、问题背景</h2>
<h3 id="11">1.1 需求场景</h3>
<ul>
<li>开发测试环境部署在阿里云 ECS（杭州区域）</li>
<li>需要随时随地访问测试网站</li>
<li>应用运行在 <code>localhost:5000</code></li>
</ul>
<h3 id="12">1.2 遇到的坑</h3>
<table>
<thead>
<tr>
<th>问题</th>
<th>原因</th>
</tr>
</thead>
<tbody>
<tr>
<td>开放 5000 端口给任意 IP</td>
<td><strong>安全风险极高</strong>，易被扫描攻击</td>
</tr>
<tr>
<td>使用 Nginx + 80 端口</td>
<td>阿里云国内服务器 <strong>ICP 备案拦截</strong>，返回 403</td>
</tr>
<tr>
<td>使用 Nginx + 8080 端口</td>
<td>URL 带端口号，不美观</td>
</tr>
<tr>
<td>直接暴露公网 IP</td>
<td>源站 IP 泄露，易被 DDoS</td>
</tr>
</tbody>
</table>
<h3 id="13">1.3 核心诉求</h3>
<ul>
<li>✅ 无需 ICP 备案</li>
<li>✅ 使用标准 443 端口（HTTPS）</li>
<li>✅ 隐藏真实服务器 IP</li>
<li>✅ 自定义域名（如 <code>blog.elliotz.men</code>）</li>
<li>✅ 免费或低成本</li>
</ul>
<hr />
<h2 id="cloudflare-tunnel_1">二、解决方案：Cloudflare Tunnel</h2>
<h3 id="21-cloudflare-tunnel">2.1 什么是 Cloudflare Tunnel？</h3>
<p>Cloudflare Tunnel（原 Argo Tunnel）是 Cloudflare 提供的<strong>内网穿透</strong>服务，核心特点：</p>
<pre><code>┌─────────────┐     ┌─────────────────┐     ┌─────────────┐
│   用户浏览器  │ →  │  Cloudflare Edge │ →  │  cloudflared │
│  (全球任意位置)│     │  (全球 CDN 节点)  │     │  (本地守护进程) │
└─────────────┘     └─────────────────┘     └──────┬──────┘
                                                    │
                                          ┌────────▼────────┐
                                          │  localhost:5000  │
                                          │  (你的应用)       │
                                          └─────────────────┘
</code></pre>
<p><strong>流量走向</strong>：
1. 用户访问 <code>https://blog.elliotz.men</code>
2. DNS 解析到 Cloudflare Edge（最近 CDN 节点）
3. Cloudflare Edge 通过 <strong>outbound 连接</strong>（非入站）找到本地 <code>cloudflared</code>
4. <code>cloudflared</code> 将请求转发到 <code>localhost:5000</code></p>
<h3 id="22">2.2 核心优势</h3>
<table>
<thead>
<tr>
<th>优势</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>无需开放入站端口</strong></td>
<td>服务器防火墙可全部关闭，cloudflared 主动 outbound 连接</td>
</tr>
<tr>
<td><strong>无需公网 IP</strong></td>
<td>甚至可以在 NAT/内网环境运行</td>
</tr>
<tr>
<td><strong>自动 HTTPS</strong></td>
<td>Cloudflare 边缘自动签发证书，无需手动配置 SSL</td>
</tr>
<tr>
<td><strong>隐藏源站 IP</strong></td>
<td>用户只能看到 Cloudflare IP，保护源站</td>
</tr>
<tr>
<td><strong>无需 ICP 备案</strong></td>
<td>流量通过 Cloudflare 国外节点，不受国内备案限制</td>
</tr>
<tr>
<td><strong>免费</strong></td>
<td>Cloudflare Free 计划即可使用</td>
</tr>
</tbody>
</table>
<h3 id="23">2.3 与传统方案对比</h3>
<table>
<thead>
<tr>
<th>方案</th>
<th style="text-align: center;">备案</th>
<th style="text-align: center;">暴露 IP</th>
<th style="text-align: center;">HTTPS</th>
<th style="text-align: center;">成本</th>
<th style="text-align: center;">复杂度</th>
</tr>
</thead>
<tbody>
<tr>
<td>直接开放端口</td>
<td style="text-align: center;">❌</td>
<td style="text-align: center;">✅ 暴露</td>
<td style="text-align: center;">手动配置</td>
<td style="text-align: center;">低</td>
<td style="text-align: center;">低</td>
</tr>
<tr>
<td>Nginx + 80/443</td>
<td style="text-align: center;"><strong>必须</strong></td>
<td style="text-align: center;">✅ 暴露</td>
<td style="text-align: center;">手动配置</td>
<td style="text-align: center;">低</td>
<td style="text-align: center;">中</td>
</tr>
<tr>
<td>Nginx + 非标准端口</td>
<td style="text-align: center;">❌</td>
<td style="text-align: center;">✅ 暴露</td>
<td style="text-align: center;">手动配置</td>
<td style="text-align: center;">低</td>
<td style="text-align: center;">中</td>
</tr>
<tr>
<td><strong>Cloudflare Tunnel</strong></td>
<td style="text-align: center;"><strong>❌ 无需</strong></td>
<td style="text-align: center;"><strong>❌ 隐藏</strong></td>
<td style="text-align: center;"><strong>自动</strong></td>
<td style="text-align: center;"><strong>免费</strong></td>
<td style="text-align: center;"><strong>中</strong></td>
</tr>
<tr>
<td>FRP/ngrok</td>
<td style="text-align: center;">❌</td>
<td style="text-align: center;">部分暴露</td>
<td style="text-align: center;">手动配置</td>
<td style="text-align: center;">中</td>
<td style="text-align: center;">中</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="_2">三、配置实战</h2>
<h3 id="31">3.1 准备工作</h3>
<ul>
<li>注册 Cloudflare 账号（免费）：https://dash.cloudflare.com</li>
<li>注册域名（本文使用 <code>elliotz.men</code>，Cloudflare 注册，5年140元）</li>
<li>一台 Linux 服务器（本文使用 Ubuntu 24.04）</li>
<li>本地应用已运行（本文使用 <code>localhost:5000</code>）</li>
</ul>
<h3 id="32-cloudflared">3.2 安装 cloudflared</h3>
<pre><code class="language-bash"># 下载安装包
cd /tmp
curl -L --output cloudflared.deb \
  https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb

# 安装
sudo dpkg -i cloudflared.deb

# 验证安装
cloudflared --version
# 输出：cloudflared version 2026.3.0
</code></pre>
<h3 id="33-tunnel">3.3 创建 Tunnel</h3>
<h4 id="cloudflare-zero-trust-dashboard">方式一：通过 Cloudflare Zero Trust Dashboard（推荐）</h4>
<ol>
<li>访问 https://one.dash.cloudflare.com</li>
<li><strong>Networks</strong> → <strong>Tunnels</strong> → <strong>Create a tunnel</strong></li>
<li>选择 <strong>Cloudflared</strong></li>
<li>填写名称：<code>elliot</code></li>
<li>保存后会显示安装命令，复制 Token：</li>
</ol>
<pre><code class="language-bash">sudo cloudflared service install &lt;TOKEN&gt;
</code></pre>
<h4 id="_3">方式二：命令行创建（需要证书）</h4>
<pre><code class="language-bash"># 登录（浏览器认证）
cloudflared tunnel login

# 创建隧道
cloudflared tunnel create elliot

# 获取隧道 UUID
cloudflared tunnel list
</code></pre>
<h3 id="34">3.4 配置路由</h3>
<h4 id="dashboard-public-hostname">在 Dashboard 中配置 Public Hostname</h4>
<ol>
<li>进入 Tunnel 详情页 → <strong>Public Hostname</strong> 标签</li>
<li>点击 <strong>Add a public hostname</strong></li>
<li>填写：</li>
<li><strong>Subdomain</strong>: <code>blog</code></li>
<li><strong>Domain</strong>: <code>elliotz.men</code></li>
<li><strong>Path</strong>: (留空)</li>
<li><strong>Type</strong>: HTTP</li>
<li><strong>URL</strong>: <code>localhost:5000</code></li>
<li>点击 <strong>Save hostname</strong></li>
</ol>
<h4 id="_4">或在配置文件中定义（备用方案）</h4>
<pre><code class="language-yaml"># /etc/cloudflared/config.yml
tunnel: &lt;TUNNEL-UUID&gt;
credentials-file: /etc/cloudflared/&lt;TUNNEL-UUID&gt;.json

ingress:
  - hostname: blog.elliotz.men
    service: http://localhost:5000
  - service: http_status:404
</code></pre>
<h3 id="35-dns">3.5 配置 DNS</h3>
<p>在 Cloudflare Dashboard → <strong>DNS</strong> 中添加记录：</p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Name</th>
<th>Target</th>
<th>Proxy Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>CNAME</td>
<td><code>blog</code></td>
<td><code>&lt;TUNNEL-UUID&gt;.cfargotunnel.com</code></td>
<td>🟠 Proxied</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>注意</strong>：Target 是隧道的 CNAME 地址，格式为 <code>&lt;UUID&gt;.cfargotunnel.com</code></p>
</blockquote>
<h3 id="36">3.6 启动服务</h3>
<pre><code class="language-bash"># 启动并设为开机自启
sudo systemctl start cloudflared
sudo systemctl enable cloudflared

# 查看状态
sudo systemctl status cloudflared

# 查看日志
sudo journalctl -u cloudflared -f
</code></pre>
<h3 id="37">3.7 验证访问</h3>
<pre><code class="language-bash">curl -I https://blog.elliotz.men

# 预期输出：
# HTTP/2 200
# server: cloudflare
# cf-cache-status: DYNAMIC
</code></pre>
<hr />
<h2 id="_5">四、踩坑记录</h2>
<h3 id="41-503-service-unavailable">4.1 错误：503 Service Unavailable</h3>
<p><strong>现象</strong>：</p>
<pre><code>HTTP/2 503
cf-cache-status: DYNAMIC
</code></pre>
<p><strong>原因</strong>：Tunnel 未配置 ingress 规则</p>
<p><strong>解决</strong>：
- 检查 Dashboard 中是否添加了 Public Hostname
- 或检查 <code>/etc/cloudflared/config.yml</code> 是否有 ingress 配置
- 重启服务：<code>sudo systemctl restart cloudflared</code></p>
<h3 id="42-403-forbidden">4.2 错误：403 Forbidden（阿里云备案拦截）</h3>
<p><strong>现象</strong>：</p>
<pre><code class="language-html">&lt;title&gt;Non-compliance ICP Filing&lt;/title&gt;
</code></pre>
<p><strong>原因</strong>：阿里云国内服务器 80/443 端口未备案被拦截</p>
<p><strong>解决</strong>：使用 Cloudflare Tunnel（流量通过 Cloudflare 边缘，不走阿里云 80/443）</p>
<h3 id="43-no-ingress-rules-were-defined">4.3 错误：No ingress rules were defined</h3>
<p><strong>日志</strong>：</p>
<pre><code>WRN No ingress rules were defined... cloudflared will return 503
</code></pre>
<p><strong>原因</strong>：Tunnel 运行了但没有配置路由规则</p>
<p><strong>解决</strong>：在 Dashboard 的 <strong>Public Hostname</strong> 标签页添加路由，不是 Private Hostname</p>
<h3 id="44">4.4 域名解析不生效</h3>
<p><strong>排查</strong>：</p>
<pre><code class="language-bash"># 检查 DNS 解析
nslookup blog.elliotz.men

# 检查是否指向 Cloudflare
dig blog.elliotz.men +short
# 应返回 Cloudflare 的 CNAME 或 IP
</code></pre>
<p><strong>解决</strong>：等待 DNS 传播（通常几分钟），或检查 DNS 记录的 Proxy 状态是否为橙色云</p>
<hr />
<h2 id="_6">五、进阶配置</h2>
<h3 id="51">5.1 多服务路由</h3>
<pre><code class="language-yaml">ingress:
  - hostname: blog.elliotz.men
    service: http://localhost:5000

  - hostname: api.elliotz.men
    service: http://localhost:3000

  - hostname: admin.elliotz.men
    service: http://localhost:8080
    originRequest:
      noTLSVerify: true

  - service: http_status:404
</code></pre>
<h3 id="52">5.2 添加基础认证（双重保护）</h3>
<p>在 Nginx 层添加基础认证：</p>
<pre><code class="language-nginx">server {
    listen 80;
    server_name localhost;

    location / {
        auth_basic &quot;Restricted Area&quot;;
        auth_basic_user_file /etc/nginx/.htpasswd;
        proxy_pass http://localhost:5000;
    }
}
</code></pre>
<h3 id="53-cloudflare-access">5.3 配合 Cloudflare Access（零信任）</h3>
<p>如需更严格的访问控制：
1. Cloudflare Dashboard → <strong>Access</strong> → <strong>Applications</strong>
2. 添加 <code>blog.elliotz.men</code>
3. 配置身份提供商（Google、GitHub、OTP 等）
4. 设置访问策略（如仅允许公司邮箱）</p>
<hr />
<h2 id="_7">六、成本分析</h2>
<table>
<thead>
<tr>
<th>项目</th>
<th>费用</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cloudflare 账号</td>
<td>免费</td>
<td>Free 计划即可</td>
</tr>
<tr>
<td>Cloudflare Tunnel</td>
<td>免费</td>
<td>不限流量</td>
</tr>
<tr>
<td>域名 <code>elliotz.men</code></td>
<td>140元/5年</td>
<td>Cloudflare 注册，比国内便宜</td>
</tr>
<tr>
<td>阿里云 ECS</td>
<td>按需</td>
<td>原有服务器，无额外费用</td>
</tr>
<tr>
<td><strong>总计</strong></td>
<td><strong>140元/5年</strong></td>
<td><strong>约 28元/年</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p>💡 <strong>对比</strong>：国内 <code>.com</code> 域名通常 60-80元/年，Cloudflare 注册确实更便宜</p>
</blockquote>
<hr />
<h2 id="_8">七、总结</h2>
<h3 id="71">7.1 核心原理</h3>
<p>Cloudflare Tunnel 的本质是<strong>反向 WebSocket 连接</strong>：</p>
<ol>
<li>本地 <code>cloudflared</code> 主动连接 Cloudflare Edge（outbound）</li>
<li>建立持久 WebSocket 隧道</li>
<li>用户请求到达 Cloudflare Edge</li>
<li>Edge 通过已有隧道将请求转发给本地</li>
<li>本地响应原路返回</li>
</ol>
<p><strong>关键</strong>：服务器无需开放任何入站端口，防火墙可以全部关闭。</p>
<h3 id="72">7.2 适用场景</h3>
<ul>
<li>✅ 开发测试环境外网访问</li>
<li>✅ 家庭 NAS/内网服务暴露</li>
<li>✅ 绕过 ISP 封锁或备案限制</li>
<li>✅ 保护源站 IP 防止 DDoS</li>
<li>✅ 快速临时分享本地服务</li>
</ul>
<h3 id="73">7.3 不适用场景</h3>
<ul>
<li>❌ 高带宽视频流（有速度限制）</li>
<li>❌ 生产环境核心服务（建议配合 Access）</li>
<li>❌ 需要固定出口 IP 的场景</li>
</ul>
<hr />
<h2 id="_9">八、参考链接</h2>
<ul>
<li><a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/">Cloudflare Tunnel 官方文档</a></li>
<li><a href="https://one.dash.cloudflare.com">Cloudflare Zero Trust Dashboard</a></li>
<li><a href="https://github.com/cloudflare/cloudflared/releases">cloudflared GitHub Releases</a></li>
</ul>
<hr />
<blockquote>
<p><strong>作者</strong>：运维 🔧<br />
<strong>日期</strong>：2026-05-12<br />
<strong>标签</strong>：#cloudflare #tunnel #内网穿透 #网络安全 #免备案</p>
</blockquote>