Post

Cloudflare Tunnel 内网穿透完整配置指南 - 零公网IP实现域名直连

本文基于真实配置实践,详细介绍如何使用 Cloudflare Tunnel 实现零公网IP的内网穿透方案。通过自有域名配合 cloudflared 工具,可将内网服务(HTTP/SSH等)安全暴露到公网,无需路由器端口映射或固定IP。适用于家庭服务器、开发环境、远程访问等场景。本次更新基于多设备实际配置经验,新增快速配置指南和多用户管理方案。

更新日志

  • 2025-10-12: 新增第十四部分“快速配置指南”,包含单设备5步快速配置和多设备最佳实践;完善SSH配置详解,包括用户端软件安装和每项参数含义;添加服务器端多用户管理方案,包括账户管理、权限隔离和安全加固。
  • 2025-10-11: 初始发布,涵盖完整配置流程和实战案例。

摘要

传统内网穿透方案往往需要公网IP或第三方服务,存在稳定性、安全性、成本等问题。Cloudflare Tunnel 作为官方免费服务,通过加密隧道连接内网与 Cloudflare 边缘网络,配合自有域名即可实现稳定的内网穿透。本文记录了从零开始的完整配置过程,涵盖 cloudflared 安装、隧道创建、DNS配置、服务部署等关键步骤,并提供 HTTP 与 SSH 双协议实战案例。

一、技术背景

1.1 传统内网穿透痛点

  • 公网IP依赖:需要运营商分配公网IP或购买云服务器
  • 路由器配置:端口映射配置复杂,安全风险高
  • 第三方服务:依赖 frp、ngrok 等工具,存在稳定性问题
  • 成本考量:商业服务收费,免费服务限制多

1.2 Cloudflare Tunnel 优势

  • 零成本:Cloudflare 提供免费 Tunnel 服务
  • 高安全:端到端加密,无需开放防火墙端口
  • 高可用:依托 Cloudflare 全球边缘网络
  • 易管理:Web 面板 + 命令行双重管理

二、架构原理

2.1 整体架构图

graph TB
    subgraph "用户端"
        U1[浏览器用户]
        U2[SSH客户端]
        U3[移动设备]
    end
    
    subgraph "Cloudflare 全球网络"
        CF1[边缘节点 - 美国]
        CF2[边缘节点 - 欧洲]
        CF3[边缘节点 - 亚洲]
        DNS[Cloudflare DNS]
    end
    
    subgraph "家庭/企业内网"
        subgraph "服务器"
            CD[cloudflared 守护进程]
            WEB[Web服务 :8080]
            SSH[SSH服务 :22]
            DB[数据库 :5432]
        end
        RT[路由器/防火墙]
    end
    
    U1 --> CF2
    U2 --> CF1
    U3 --> CF3
    
    CF1 -.-> |加密隧道| CD
    CF2 -.-> |加密隧道| CD
    CF3 -.-> |加密隧道| CD
    
    CD --> WEB
    CD --> SSH
    CD --> DB
    
    DNS --> CF1
    DNS --> CF2
    DNS --> CF3
    
    RT -.-> |仅出站连接| CF1

2.2 数据流向图

sequenceDiagram
    participant User as 用户浏览器
    participant CF as Cloudflare边缘
    participant Tunnel as cloudflared隧道
    participant Service as 内网服务
    
    Note over User,Service: 1. 初始连接建立
    Tunnel->>CF: 建立持久WebSocket连接
    CF->>Tunnel: 连接确认
    
    Note over User,Service: 2. 用户请求处理
    User->>CF: HTTPS请求 app.example.com
    CF->>CF: DNS解析到隧道
    CF->>Tunnel: 转发请求到隧道
    Tunnel->>Service: HTTP请求 localhost:8080
    Service->>Tunnel: HTTP响应
    Tunnel->>CF: 返回响应
    CF->>User: HTTPS响应

2.3 协议支持矩阵

graph LR
    subgraph "支持的协议类型"
        HTTP[HTTP/HTTPS<br/>Web服务]
        SSH_P[SSH<br/>远程终端]
        TCP[TCP<br/>数据库/自定义]
        WS[WebSocket<br/>实时通信]
    end
    
    subgraph "应用场景"
        WEB_APP[Web应用<br/>博客/管理后台]
        REMOTE[远程开发<br/>SSH/VS Code]
        DATABASE[数据库访问<br/>PostgreSQL/MySQL]
        GAMING[游戏服务器<br/>Minecraft等]
    end
    
    HTTP --> WEB_APP
    SSH_P --> REMOTE
    TCP --> DATABASE
    TCP --> GAMING
    WS --> WEB_APP

2.4 工作流程详解

  1. 隧道建立:cloudflared 客户端与 Cloudflare 边缘建立持久连接
  2. DNS 绑定:子域名通过 CNAME 记录指向隧道
  3. 流量代理:用户请求经 Cloudflare 转发至内网服务
  4. 协议支持:支持 HTTP/HTTPS、SSH、TCP 等多种协议

三、环境准备

3.1 前置条件

  • Cloudflare 账号:免费注册即可
  • 自有域名:已接入 Cloudflare DNS 托管
  • Linux 服务器:Ubuntu 24.04 LTS(本文环境)
  • 出站网络:能够访问 Cloudflare 服务

3.2 系统信息确认

1
2
3
4
5
6
7
8
# 检查系统版本
cat /etc/os-release

# 检查CPU架构
uname -m

# 检查网络连通性
ping -c 4 1.1.1.1

四、cloudflared 安装

4.1 Ubuntu/Debian 官方源安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 更新软件源并安装依赖
sudo apt-get update
sudo apt-get install -y wget gnupg lsb-release

# 添加 Cloudflare 官方密钥和源
wget -q https://packages.cloudflare.com/cloudflare-main.gpg -O- | \
  sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] \
  https://packages.cloudflare.com/ $(lsb_release -cs) main" | \
  sudo tee /etc/apt/sources.list.d/cloudflare.list

# 安装 cloudflared
sudo apt-get update
sudo apt-get install -y cloudflared

# 验证安装
cloudflared --version

4.2 通用二进制安装(备选方案)

1
2
3
4
5
6
7
8
9
10
# 下载最新版本(适用于网络受限环境)
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
  -o cloudflared

# 设置可执行权限并移动到系统目录
chmod +x cloudflared
sudo mv cloudflared /usr/local/bin/

# 验证安装
cloudflared --version

五、隧道配置流程

5.0 配置流程总览

flowchart TD
    Start([开始配置]) --> Install[安装 cloudflared]
    Install --> Auth[Cloudflare 认证]
    Auth --> Create[创建隧道]
    Create --> DNS[配置 DNS 路由]
    DNS --> Config[编写配置文件]
    Config --> Service[部署系统服务]
    Service --> Test[测试验证]
    Test --> Monitor[监控运维]
    
    Auth --> AuthSub[浏览器授权选择域名]
    Create --> CreateSub[生成隧道ID和凭证文件]
    DNS --> DNSSub[子域名CNAME指向隧道]
    Config --> ConfigSub[ingress规则配置]
    Service --> ServiceSub[systemd守护进程]
    Test --> TestSub[HTTP/SSH连通性验证]
    
    style Start fill:#e1f5fe
    style Monitor fill:#c8e6c9
    style Test fill:#fff3e0

5.1 Cloudflare 认证

1
2
# 登录 Cloudflare 账号
cloudflared tunnel login

💡 提示:执行后会输出一个 URL,在浏览器中打开并选择要管理的域名进行授权。

5.2 创建隧道

1
2
3
4
5
# 创建命名隧道
cloudflared tunnel create my-tunnel

# 查看隧道信息
ls -la ~/.cloudflared/

输出示例

1
2
Created tunnel my-tunnel with id 167e64e3-17b5-4bf8-bd7b-f7691f658416
Tunnel credentials written to /home/user/.cloudflared/167e64e3-17b5-4bf8-bd7b-f7691f658416.json

5.3 DNS 路由配置

1
2
3
4
5
# 将子域名指向隧道(以 app.example.com 为例)
cloudflared tunnel route dns my-tunnel app.example.com

# SSH 访问子域名
cloudflared tunnel route dns my-tunnel ssh.example.com

六、服务配置

6.1 创建配置文件

1
2
3
4
5
6
7
# 创建系统级配置目录
sudo mkdir -p /etc/cloudflared

# 复制凭证文件到系统目录
sudo cp ~/.cloudflared/167e64e3-17b5-4bf8-bd7b-f7691f658416.json /etc/cloudflared/
sudo chown root:root /etc/cloudflared/167e64e3-17b5-4bf8-bd7b-f7691f658416.json
sudo chmod 400 /etc/cloudflared/167e64e3-17b5-4bf8-bd7b-f7691f658416.json

6.2 配置 ingress 规则

ingress 路由机制图

flowchart LR
    subgraph "外部请求"
        R1[app.example.com]
        R2[ssh.example.com]
        R3[api.example.com]
        R4[其他域名]
    end
    
    subgraph "cloudflared ingress 处理"
        I1[规则1: hostname匹配]
        I2[规则2: hostname匹配]
        I3[规则3: hostname匹配]
        I4[兜底规则: 404]
    end
    
    subgraph "内网服务"
        S1[localhost:8080<br/>Web服务]
        S2[localhost:22<br/>SSH服务]
        S3[localhost:3000<br/>API服务]
        S4[HTTP 404<br/>错误页面]
    end
    
    R1 --> I1 --> S1
    R2 --> I2 --> S2
    R3 --> I3 --> S3
    R4 --> I4 --> S4

配置文件创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建 /etc/cloudflared/config.yml
sudo tee /etc/cloudflared/config.yml >/dev/null <<'EOF'
tunnel: my-tunnel
credentials-file: /etc/cloudflared/167e64e3-17b5-4bf8-bd7b-f7691f658416.json

ingress:
  # HTTP 服务转发
  - hostname: app.example.com
    service: http://localhost:8080
  
  # SSH 服务转发
  - hostname: ssh.example.com
    service: ssh://localhost:22
  
  # 兜底规则(必需)
  - service: http_status:404
EOF

6.3 创建 systemd 服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 创建服务文件
sudo tee /etc/systemd/system/cloudflared.service >/dev/null <<'EOF'
[Unit]
Description=cloudflared tunnel
After=network-online.target
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/local/bin/cloudflared --config /etc/cloudflared/config.yml tunnel run my-tunnel
Restart=on-failure
TimeoutStartSec=0
User=root

[Install]
WantedBy=multi-user.target
EOF

# 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared

# 检查服务状态
sudo systemctl status cloudflared --no-pager

七、实战案例

7.1 HTTP 服务暴露

启动测试服务

1
2
3
4
5
6
7
8
# 创建测试页面
echo "Hello from Cloudflare Tunnel on $(hostname)" > /tmp/index.html

# 启动 Python HTTP 服务器
python3 -m http.server 8080 --bind 127.0.0.1 --directory /tmp &

# 验证本地访问
curl http://localhost:8080

外网访问验证

1
2
3
4
5
6
7
# 测试外网访问
curl -I https://app.example.com

# 预期输出
# HTTP/2 200 
# server: cloudflare
# content-type: text/html

7.2 SSH 服务配置

SSH 连接流程图

sequenceDiagram
    participant Client as SSH客户端
    participant CF as Cloudflare边缘
    participant Tunnel as cloudflared
    participant SSH as SSH服务器
    
    Note over Client,SSH: SSH through Cloudflare Tunnel
    
    Client->>Client: 读取 ~/.ssh/config
    Client->>Client: 启动 ProxyCommand
    Client->>CF: cloudflared access ssh连接
    CF->>Tunnel: 建立SSH隧道
    Tunnel->>SSH: 转发到 localhost:22
    SSH->>Tunnel: SSH握手响应
    Tunnel->>CF: 返回握手
    CF->>Client: 建立SSH会话
    
    loop SSH会话
        Client->>CF: SSH命令/数据
        CF->>Tunnel: 转发
        Tunnel->>SSH: 执行
        SSH->>Tunnel: 结果
        Tunnel->>CF: 返回
        CF->>Client: 显示结果
    end

服务器端配置

1
2
3
4
5
# 确认 SSH 服务运行
sudo systemctl status ssh

# 检查端口监听
ss -lntp | grep :22

客户端 SSH 配置架构

graph TB
    subgraph "本地客户端"
        SSH_CMD[ssh命令]
        SSH_CONFIG[~/.ssh/config]
        CLOUDFLARED_CLIENT[cloudflared客户端]
    end
    
    subgraph "Cloudflare网络"
        EDGE[边缘节点]
    end
    
    subgraph "远程服务器"
        CLOUDFLARED_SERVER[cloudflared守护进程]
        SSH_SERVER[SSH服务 :22]
    end
    
    SSH_CMD --> SSH_CONFIG
    SSH_CONFIG --> CLOUDFLARED_CLIENT
    CLOUDFLARED_CLIENT --> EDGE
    EDGE --> CLOUDFLARED_SERVER
    CLOUDFLARED_SERVER --> SSH_SERVER

客户端 SSH 配置

用户端软件准备

在本地客户端(Mac/Windows/Linux)上,需要安装以下软件:

  1. SSH客户端
    • Mac:系统自带 OpenSSH
    • Windows:安装 OpenSSH(Windows 10+ 自带)或 PuTTY
    • Linux:系统自带 OpenSSH
  2. cloudflared客户端
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    # Mac (使用 Homebrew)
    brew install cloudflare/cloudflare/cloudflared
       
    # Windows (使用 Chocolatey)
    choco install cloudflared
       
    # Linux
    wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
    sudo dpkg -i cloudflared-linux-amd64.deb
    
  3. 验证安装
    1
    2
    
    ssh -V  # 检查SSH版本
    cloudflared version  # 检查cloudflared版本
    
SSH配置详解

在本地机器的 ~/.ssh/config 中添加配置,每项含义如下:

  # Cloudflare Tunnel SSH 配置示例
  Host ssh.example.com
      # 目标主机名(通过Cloudflare Tunnel访问)
      HostName ssh.example.com
      # 远程服务器用户名
      User your-username
      # SSH端口(通常22)
      Port 22
      # 代理命令:通过cloudflared建立隧道连接
      ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
      # SSH私钥文件路径
      IdentityFile ~/.ssh/id_ed25519
      # 仅使用指定密钥文件,不使用默认密钥
      IdentitiesOnly yes
      # 每15秒发送心跳包,保持连接
      ServerAliveInterval 15
      # 心跳失败3次后断开连接
      ServerAliveCountMax 3
1
2
3
4
5
6
7
8
9
10
  # 简化别名配置
  Host my-server
      HostName ssh.example.com
      User your-username
      Port 22
      ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
      IdentityFile ~/.ssh/id_ed25519
      IdentitiesOnly yes
      ServerAliveInterval 15
      ServerAliveCountMax 3

配置项详细说明

  • Host:SSH连接的别名,可自定义
  • HostName:实际连接的域名/IP
  • User:远程服务器的用户名
  • Port:SSH服务端口(默认22)
  • ProxyCommand:使用cloudflared作为代理,建立安全隧道
  • IdentityFile:指定SSH私钥文件路径
  • IdentitiesOnly:仅使用指定的密钥文件
  • ServerAliveInterval:心跳间隔,防止连接超时
  • ServerAliveCountMax:最大心跳失败次数
SSH密钥对生成
1
2
3
4
5
6
7
8
# 生成ED25519密钥对(推荐)
ssh-keygen -t ed25519 -C "[email protected]"

# 或RSA(兼容性更好)
ssh-keygen -t rsa -b 4096 -C "[email protected]"

# 查看公钥
cat ~/.ssh/id_ed25519.pub

SSH 连接测试

1
2
3
4
5
6
7
8
# 通过域名连接
ssh ssh.example.com

# 通过别名连接
ssh my-server

# 详细调试模式
ssh -vvv my-server
服务器端多用户管理方案

对于多用户访问同一服务器的场景,需要合理管理用户权限和SSH访问:

用户账户管理
1
2
3
4
5
6
7
# 创建新用户
sudo useradd -m -s /bin/bash newuser
sudo passwd newuser

# 设置用户组(可选)
sudo usermod -aG sudo newuser  # 添加到sudo组
sudo usermod -aG docker newuser  # 添加到docker组
SSH密钥管理
1
2
3
4
5
6
7
8
9
# 为每个用户创建独立的authorized_keys
sudo mkdir -p /home/newuser/.ssh
sudo touch /home/newuser/.ssh/authorized_keys
sudo chmod 700 /home/newuser/.ssh
sudo chmod 600 /home/newuser/.ssh/authorized_keys
sudo chown -R newuser:newuser /home/newuser/.ssh

# 添加用户公钥
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..." | sudo tee -a /home/newuser/.ssh/authorized_keys
权限隔离配置
1
2
3
4
5
6
7
8
9
# 限制用户访问目录(使用chroot或权限设置)
# 编辑 /etc/ssh/sshd_config 添加:
# Match User newuser
#     ChrootDirectory /home/newuser
#     AllowTcpForwarding no
#     X11Forwarding no

# 重启SSH服务
sudo systemctl restart ssh
多用户Tunnel配置

为不同用户配置独立的子域名和tunnel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# /etc/cloudflared/config.yml - 多用户配置
tunnel: main-tunnel
credentials-file: /etc/cloudflared/credentials.json

ingress:
  # 管理员SSH
  - hostname: admin.example.com
    service: ssh://localhost:22
  
  # 普通用户SSH
  - hostname: user1.example.com
    service: ssh://localhost:22
  
  # 开发用户SSH
  - hostname: dev.example.com
    service: ssh://localhost:22
  
  - service: http_status:404
1
2
3
4
# 为每个用户创建DNS路由
cloudflared tunnel route dns main-tunnel admin.example.com
cloudflared tunnel route dns main-tunnel user1.example.com
cloudflared tunnel route dns main-tunnel dev.example.com
客户端多用户配置
# 多用户SSH配置
Host admin-server
    HostName admin.example.com
    User admin
    ProxyCommand cloudflared access ssh --hostname %h
    IdentityFile ~/.ssh/id_ed25519_admin

Host user1-server
    HostName user1.example.com
    User user1
    ProxyCommand cloudflared access ssh --hostname %h
    IdentityFile ~/.ssh/id_ed25519_user1

Host dev-server
    HostName dev.example.com
    User developer
    ProxyCommand cloudflared access ssh --hostname %h
    IdentityFile ~/.ssh/id_ed25519_dev
安全加固建议
1
2
3
4
5
6
7
8
9
10
11
# 禁用密码认证,只允许公钥
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

# 禁用root登录
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

# 限制用户登录
echo "AllowUsers admin user1 developer" | sudo tee -a /etc/ssh/sshd_config

# 重启服务
sudo systemctl restart ssh

八、配置验证与调试

8.1 完整验证流程

flowchart TD
    Start([开始验证]) --> ServiceCheck{cloudflared服务运行?}
    ServiceCheck -- 否 --> StartService[启动服务]
    ServiceCheck -- 是 --> TunnelCheck{隧道连接正常?}
    
    StartService --> TunnelCheck
    TunnelCheck -- 否 --> CheckLogs[检查日志]
    TunnelCheck -- 是 --> DNSCheck{DNS解析正确?}
    
    CheckLogs --> FixConfig[修复配置]
    FixConfig --> ServiceCheck
    
    DNSCheck -- 否 --> FixDNS[修复DNS设置]
    DNSCheck -- 是 --> HTTPTest{HTTP服务可达?}
    
    FixDNS --> DNSCheck
    HTTPTest -- 否 --> CheckIngress[检查ingress规则]
    HTTPTest -- 是 --> SSHTest{SSH服务可达?}
    
    CheckIngress --> FixConfig
    SSHTest -- 否 --> CheckSSHConfig[检查SSH配置]
    SSHTest -- 是 --> Success([验证成功])
    
    CheckSSHConfig --> FixSSHConfig[修复SSH配置]
    FixSSHConfig --> SSHTest
    
    style Success fill:#c8e6c9
    style Start fill:#e1f5fe

8.2 服务状态检查

1
2
3
4
5
6
7
8
# 查看隧道连接状态
sudo journalctl -u cloudflared -f --no-pager

# 检查端口监听
netstat -tulpn | grep cloudflared

# 查看隧道指标
curl http://127.0.0.1:20241/metrics

8.3 问题诊断矩阵

graph TB
    subgraph "常见问题类型"
        P1[网络连接问题]
        P2[配置文件问题]  
        P3[DNS解析问题]
        P4[权限问题]
        P5[端口占用问题]
    end
    
    subgraph "诊断方法"
        D1[ping/curl测试]
        D2[配置文件验证]
        D3[dig/nslookup]
        D4[权限检查]
        D5[端口扫描]
    end
    
    subgraph "解决方案"
        S1[检查防火墙/代理]
        S2[修复配置语法]
        S3[重新配置DNS]
        S4[修复文件权限]
        S5[停止冲突进程]
    end
    
    P1 --> D1 --> S1
    P2 --> D2 --> S2
    P3 --> D3 --> S3
    P4 --> D4 --> S4
    P5 --> D5 --> S5

8.4 常见问题排查

隧道无法连接

1
2
3
4
5
6
7
8
# 检查网络连通性
curl -I https://api.cloudflare.com/client/v4/zones

# 检查配置文件语法
cloudflared tunnel ingress validate

# 测试隧道配置
cloudflared tunnel ingress rule https://app.example.com

DNS 解析问题

1
2
3
4
5
6
7
# 检查 DNS 记录
dig app.example.com
nslookup ssh.example.com

# 检查 Cloudflare DNS 设置
curl -X GET "https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records" \
  -H "Authorization: Bearer {api_token}"

九、高级配置

9.1 多服务架构设计

graph TB
    subgraph "外部访问"
        U1[Web用户]
        U2[API客户端]
        U3[数据库客户端]
        U4[SSH用户]
        U5[管理员]
    end
    
    subgraph "Cloudflare 边缘"
        CF[全球边缘节点]
    end
    
    subgraph "域名路由"
        D1[app.example.com]
        D2[api.example.com]
        D3[db.example.com]
        D4[ssh.example.com]
        D5[admin.example.com]
    end
    
    subgraph "内网服务集群"
        subgraph "Web层"
            WEB[React App :3000]
            ADMIN[Admin Panel :8081]
        end
        subgraph "API层"
            API[REST API :8080]
        end
        subgraph "数据层"
            DB[PostgreSQL :5432]
        end
        subgraph "系统层"
            SSH_S[SSH Server :22]
        end
        CD[cloudflared]
    end
    
    U1 --> D1 --> CF
    U2 --> D2 --> CF  
    U3 --> D3 --> CF
    U4 --> D4 --> CF
    U5 --> D5 --> CF
    
    CF --> CD
    CD --> WEB
    CD --> API
    CD --> DB
    CD --> SSH_S
    CD --> ADMIN

9.2 多服务配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# /etc/cloudflared/config.yml - 扩展版本
tunnel: my-tunnel
credentials-file: /etc/cloudflared/credentials.json

ingress:
  # Web 应用
  - hostname: app.example.com
    service: http://localhost:3000
  
  # API 服务
  - hostname: api.example.com
    service: http://localhost:8080
  
  # 数据库管理
  - hostname: admin.example.com
    service: http://localhost:8081
    originRequest:
      httpHostHeader: admin.example.com
  
  # SSH 访问
  - hostname: ssh.example.com
    service: ssh://localhost:22
  
  # TCP 代理(如数据库)
  - hostname: db.example.com
    service: tcp://localhost:5432
  
  - service: http_status:404

9.3 负载均衡配置

graph TB
    subgraph "用户请求"
        REQ[高并发请求]
    end
    
    subgraph "Cloudflare 负载均衡"
        LB[Load Balancer]
        CACHE[Edge Cache]
    end
    
    subgraph "多实例部署"
        T1[Tunnel 1<br/>Primary]
        T2[Tunnel 2<br/>Backup]
        T3[Tunnel 3<br/>Backup]
    end
    
    subgraph "后端服务池"
        S1[Service Instance 1]
        S2[Service Instance 2] 
        S3[Service Instance 3]
    end
    
    REQ --> CACHE
    CACHE --> LB
    LB --> T1
    LB --> T2
    LB --> T3
    
    T1 --> S1
    T2 --> S2
    T3 --> S3
    
    style T1 fill:#c8e6c9
    style T2 fill:#ffecb3
    style T3 fill:#ffecb3

9.4 Cloudflare Access 安全集成

flowchart TB
    subgraph "身份提供商"
        IDP1[Google Workspace]
        IDP2[Microsoft Azure AD]
        IDP3[GitHub]
        IDP4[SAML IdP]
    end
    
    subgraph "Cloudflare Access"
        AUTH[Access 认证网关]
        POLICY[访问策略引擎]
        JWT[JWT 令牌验证]
    end
    
    subgraph "受保护资源"
        APP1[admin.example.com]
        APP2[api.example.com]
        SSH_APP[ssh.example.com]
    end
    
    subgraph "用户访问流程"
        USER[用户] --> AUTH
        AUTH --> IDP1
        IDP1 --> AUTH
        AUTH --> POLICY
        POLICY --> JWT
        JWT --> APP1
        JWT --> APP2
        JWT --> SSH_APP
    end
    
    style AUTH fill:#fff3e0
    style POLICY fill:#e8f5e8
    style JWT fill:#f3e5f5

Access 策略配置示例

方法一:Web 面板配置
  1. 登录 Cloudflare Zero Trust 控制台

    1
    2
    
    # 访问 https://one.dash.cloudflare.com/
    # 选择你的域名
    
  2. 创建 Access 应用程序
    • 导航到 Access > Applications
    • 点击 Add an application
    • 选择 Self-hostedSaaS
  3. 配置应用程序详情

    1
    2
    3
    4
    5
    
    # 应用程序配置示例
    Name: SSH Access to Server
    Session Duration: 24 hours
    Application domain: ssh.example.com
    Application type: SSH
    
  4. 设置身份策略

    1
    2
    3
    4
    5
    6
    7
    8
    
    # 策略配置
    Policy Name: Admin SSH Access
    Action: Allow
    Include Rules:
      - Emails: [email protected]
      - Groups: [email protected]
    Require Rules:
      - IP ranges: 192.168.1.0/24 (可选)
    
  5. 配置身份提供商
    • 导航到 Settings > Authentication
    • 添加提供商:Google、GitHub、Azure AD 等
方法二:API 配置示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1. 获取账户和区域信息
curl -X GET "https://api.cloudflare.com/client/v4/accounts" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json"

# 2. 创建 Access 应用程序
curl -X POST "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/access/apps" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "SSH Access",
    "domain": "ssh.example.com",
    "type": "ssh",
    "session_duration": "24h",
    "policies": ["POLICY_ID"]
  }'

# 3. 创建访问策略
curl -X POST "https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/access/policies" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Admin Access Policy",
    "include": [
      {"email": {"email": "[email protected]"}},
      {"ip": {"ip": "192.168.1.0/24"}}
    ],
    "require": [],
    "exclude": []
  }'
方法三:Terraform 配置示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# main.tf
terraform {
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }
  }
}

# 配置 Cloudflare 提供商
provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

# 创建 Access 应用程序
resource "cloudflare_access_application" "ssh_app" {
  zone_id          = var.zone_id
  name             = "SSH Access to Server"
  domain           = "ssh.example.com"
  type             = "ssh"
  session_duration = "24h"
}

# 创建访问策略
resource "cloudflare_access_policy" "admin_policy" {
  application_id = cloudflare_access_application.ssh_app.id
  zone_id        = var.zone_id
  name           = "Admin SSH Access"
  precedence     = 1
  decision       = "allow"

  include {
    email = ["[email protected]"]
  }

  include {
    ip = ["192.168.1.0/24"]
  }
}

# 配置身份提供商 (GitHub 示例)
resource "cloudflare_access_identity_provider" "github" {
  account_id = var.account_id
  name       = "GitHub OAuth"
  type       = "github"

  config {
    client_id     = var.github_client_id
    client_secret = var.github_client_secret
  }
}

# variables.tf
variable "cloudflare_api_token" {
  description = "Cloudflare API Token"
  type        = string
  sensitive   = true
}

variable "zone_id" {
  description = "Cloudflare Zone ID"
  type        = string
}

variable "account_id" {
  description = "Cloudflare Account ID"
  type        = string
}

variable "github_client_id" {
  description = "GitHub OAuth App Client ID"
  type        = string
}

variable "github_client_secret" {
  description = "GitHub OAuth App Client Secret"
  type        = string
  sensitive   = true
}
方法四:多租户配置示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 多租户 Access 配置
# 为不同用户组配置不同的访问权限

# 管理员策略 - 完全访问
admin_policy:
  name: "Administrator Access"
  include:
    - email: ["[email protected]"]
    - groups: ["admins"]
  allow:
    - ssh: "ssh.example.com"
    - http: "admin.example.com"

# 开发者策略 - 开发环境访问
dev_policy:
  name: "Developer Access"
  include:
    - email_domain: ["@company.com"]
    - groups: ["developers"]
  allow:
    - ssh: "dev.example.com"
    - http: "staging.example.com"
  deny:
    - http: "admin.example.com"

# 访客策略 - 只读访问
guest_policy:
  name: "Guest Access"
  include:
    - email: ["[email protected]"]
  allow:
    - http: "portal.example.com"
  require:
    - mfa: true
验证配置
1
2
3
4
5
6
7
8
# 测试 Access 策略
curl -I https://ssh.example.com \
  -H "CF-Access-Client-Id: YOUR_CLIENT_ID" \
  -H "CF-Access-Client-Secret: YOUR_CLIENT_SECRET"

# 检查策略应用
cloudflared access login
cloudflared access ssh --hostname ssh.example.com

9.3 自动更新配置

1
2
3
4
5
6
7
8
# 创建更新脚本
sudo tee /etc/cron.daily/cloudflared-update >/dev/null <<'EOF'
#!/bin/bash
/usr/local/bin/cloudflared update
systemctl restart cloudflared
EOF

sudo chmod +x /etc/cron.daily/cloudflared-update

十、性能与安全

10.1 性能优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 配置文件优化选项
tunnel: my-tunnel
credentials-file: /etc/cloudflared/credentials.json

# 连接池配置
connection-pool-size: 4
heartbeat-interval: 30s
max-heartbeats: 3

ingress:
  - hostname: app.example.com
    service: http://localhost:8080
    originRequest:
      # 启用压缩
      enableCompression: true
      # 连接超时
      connectTimeout: 30s
      # 保持连接
      keepAliveTimeout: 90s

10.2 安全配置

  • 最小权限原则:仅暴露必要服务端口
  • 访问控制:配合 Cloudflare Access 实现身份认证
  • 证书管理:Cloudflare 自动处理 SSL/TLS 证书
  • 日志监控:定期检查访问日志和异常连接

十一、故障排查流程

11.1 系统化排查流程

flowchart TD
    Start(🔍 开始排查) --> NetCheck{🌐 网络连通正常?}
    NetCheck -- ❌ 否 --> FixNetwork[🔧 检查出站网络]
    NetCheck -- ✅ 是 --> ServiceCheck{⚙️ cloudflared服务正常?}
    ServiceCheck -- ❌ 否 --> RestartService[🔄 重启服务]
    ServiceCheck -- ✅ 是 --> DNSCheck{🔗 DNS解析正确?}
    DNSCheck -- ❌ 否 --> FixDNS[📝 修复DNS配置]
    DNSCheck -- ✅ 是 --> ConfigCheck{📋 配置文件正确?}
    ConfigCheck -- ❌ 否 --> FixConfig[✏️ 修复配置]
    ConfigCheck -- ✅ 是 --> LogCheck[📊 查看详细日志]
    LogCheck --> ContactSupport[📞 联系技术支持]
    
    FixNetwork --> NetCheck
    RestartService --> ServiceCheck
    FixDNS --> DNSCheck
    FixConfig --> ConfigCheck
    
    style Start fill:#e1f5fe
    style ContactSupport fill:#ffebee

11.2 分层诊断架构

graph TB
    subgraph "Layer 1: 网络层"
        L1_1[网络连通性]
        L1_2[DNS 解析]
        L1_3[防火墙规则]
    end
    
    subgraph "Layer 2: 服务层"  
        L2_1[cloudflared 进程]
        L2_2[系统服务状态]
        L2_3[端口监听]
    end
    
    subgraph "Layer 3: 配置层"
        L3_1[配置文件语法]
        L3_2[ingress 规则]
        L3_3[凭证文件]
    end
    
    subgraph "Layer 4: 应用层"
        L4_1[后端服务状态]
        L4_2[应用程序日志]
        L4_3[性能指标]
    end
    
    L1_1 --> L2_1
    L1_2 --> L2_2  
    L1_3 --> L2_3
    L2_1 --> L3_1
    L2_2 --> L3_2
    L2_3 --> L3_3
    L3_1 --> L4_1
    L3_2 --> L4_2
    L3_3 --> L4_3

常用调试命令速查

检查项目命令
服务状态sudo systemctl status cloudflared
实时日志sudo journalctl -u cloudflared -f
配置验证cloudflared tunnel ingress validate
规则测试cloudflared tunnel ingress rule https://app.example.com
网络连通curl -I https://api.cloudflare.com
DNS 解析dig app.example.com
端口检查netstat -tulpn \| grep cloudflared

十二、总结

Cloudflare Tunnel 为内网穿透提供了企业级的解决方案,具备以下显著优势:

12.1 技术优势

  • 零配置公网:无需公网IP或路由器设置
  • 高度安全:端到端加密,无需开放防火墙端口
  • 协议丰富:支持 HTTP/SSH/TCP 等多种协议
  • 全球加速:依托 Cloudflare CDN 网络

12.2 应用场景矩阵

graph TB
    subgraph "个人用户"
        P1[🏠 家庭实验室<br/>NAS/媒体中心]
        P2[💻 个人开发<br/>本地服务调试] 
        P3[🎮 游戏服务器<br/>朋友联机]
    end
    
    subgraph "企业用户"
        E1[🏢 内部系统<br/>OA/ERP访问]
        E2[🔧 运维监控<br/>Grafana/Prometheus]
        E3[📊 数据分析<br/>Jupyter/BI工具]
    end
    
    subgraph "开发团队"
        D1[🚀 CI/CD流水线<br/>Jenkins/GitLab]
        D2[🐛 测试环境<br/>Staging部署]
        D3[📝 文档系统<br/>Wiki/API文档]
    end
    
    subgraph "IoT场景"
        I1[🌡️ 传感器监控<br/>温度/湿度数据]
        I2[📹 视频监控<br/>摄像头直播]
        I3[🤖 智能家居<br/>Home Assistant]
    end
    
    style P1 fill:#e3f2fd
    style E1 fill:#f3e5f5
    style D1 fill:#e8f5e8
    style I1 fill:#fff8e1

12.3 部署模式对比

graph TB
    subgraph "传统方案"
        T1[🏠 家庭路由器<br/>端口映射]
        T2[☁️ 云服务器<br/>反向代理]
        T3[🔧 第三方工具<br/>frp/ngrok]
    end
    
    subgraph "Cloudflare Tunnel"
        CF1[🛡️ 零配置安全<br/>无需端口开放]
        CF2[🌍 全球加速<br/>CDN边缘网络]
        CF3[💰 零成本<br/>免费额度充足]
    end
    
    subgraph "对比维度"
        D1[安全性]
        D2[易用性] 
        D3[成本]
        D4[性能]
        D5[稳定性]
    end
    
    T1 --> D1
    T2 --> D2
    T3 --> D3
    CF1 --> D4
    CF2 --> D5
    CF3 --> D1
    
    style CF1 fill:#c8e6c9
    style CF2 fill:#c8e6c9
    style CF3 fill:#c8e6c9

12.3 最佳实践

  1. 域名规划:使用子域名区分不同服务
  2. 安全加固:配置 Cloudflare Access 身份认证
  3. 监控告警:设置服务状态监控和日志告警
  4. 备份恢复:定期备份配置文件和凭证
  5. 版本管理:保持 cloudflared 客户端最新版本

通过本文的完整配置流程,您可以快速搭建稳定可靠的内网穿透服务,享受 Cloudflare 全球网络带来的高性能体验。

十三、参考资料

十四、快速配置指南

14.1 单设备快速配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 1. 安装 cloudflared
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

# 2. 登录并创建隧道
cloudflared tunnel login
cloudflared tunnel create my-tunnel

# 3. 配置 DNS
cloudflared tunnel route dns my-tunnel app.example.com

# 4. 创建配置文件
sudo mkdir -p /etc/cloudflared
sudo cp ~/.cloudflared/*.json /etc/cloudflared/
sudo tee /etc/cloudflared/config.yml > /dev/null <<EOF
tunnel: my-tunnel
credentials-file: /etc/cloudflared/$(ls /etc/cloudflared/*.json | xargs basename)

ingress:
  - hostname: app.example.com
    service: http://localhost:8080
  - service: http_status:404
EOF

# 5. 启动服务
sudo cloudflared service install
sudo systemctl start cloudflared

14.2 多设备配置最佳实践

架构设计

每个设备使用独立隧道,避免路由冲突:

graph TB
    subgraph "设备A"
        T1[tunnel-device-a]
        S1[SSH :22]
    end
    
    subgraph "设备B"  
        T2[tunnel-device-b]
        S2[SSH :22]
    end
    
    subgraph "Cloudflare"
        DNS1[a.example.com → tunnel-device-a]
        DNS2[b.example.com → tunnel-device-b]
    end
    
    DNS1 --> T1 --> S1
    DNS2 --> T2 --> S2

服务器端配置(每台设备重复)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 为每台设备创建独立隧道
cloudflared tunnel create device-a-tunnel
cloudflared tunnel route dns device-a-tunnel a.example.com

# 配置文件模板
sudo tee /etc/cloudflared/config.yml > /dev/null <<EOF
tunnel: device-a-tunnel
credentials-file: /etc/cloudflared/$(ls ~/.cloudflared/device-a-tunnel.json)

ingress:
  - hostname: a.example.com
    service: ssh://localhost:22
  - service: http_status:404
EOF

# 启动服务
sudo cloudflared service install
sudo systemctl start cloudflared

客户端配置(用户本地机器)

~/.ssh/config 中添加多设备条目:

# 多设备SSH配置模板
Host device-a
    HostName a.example.com
    User your-username
    ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes
    ServerAliveInterval 15
    ServerAliveCountMax 3

Host device-b
    HostName b.example.com
    User your-username
    ProxyCommand /opt/homebrew/bin/cloudflared access ssh --hostname %h
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes
    ServerAliveInterval 15
    ServerAliveCountMax 3

公钥认证配置

1
2
3
4
5
6
7
8
9
10
# 生成密钥对(如果没有)
ssh-keygen -t ed25519 -C "[email protected]"

# 复制公钥到每台设备
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@device-a
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@device-b

# 或手动添加
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

14.3 连接测试

1
2
3
4
5
6
# 测试连接
ssh device-a
ssh device-b

# 验证公钥认证(无需密码)
ssh -o PasswordAuthentication=no device-a 'echo "Connected successfully"'

14.4 故障排查快速版

1
2
3
4
5
6
7
8
9
10
11
# 检查服务
sudo systemctl status cloudflared

# 查看日志
journalctl -u cloudflared -n 10

# DNS测试
nslookup a.example.com

# 隧道状态
cloudflared tunnel list

*本文基于 Ubuntu 24.04 LTS 环境实测编写,配置过程已验证可用。如有问题或建议,欢迎反馈!

This post is licensed under CC BY 4.0 by the author.