Featured image of post Cloudflare Argo 远程托管固定隧道脚本使用指南

Cloudflare Argo 远程托管固定隧道脚本使用指南

Cloudflare Argo 远程托管固定隧道脚本使用指南

本文介绍的 Bash 脚本专为自动化管理 Cloudflare Argo (Cloudflare Tunnel) 设计。通过集成 Cloudflare Zero Trust REST API,实现了一键创建远程托管隧道、自动配置域名路由、自动绑定 DNS 记录并输出连接器 Token 的全流程自动化,省去了手动编写本地 config.yml 和管理凭证文件的步骤。

功能特性

  • 一键开通固定隧道:输入隧道名、域名和本地服务端口,自动在云端完成所有映射配置。
  • 零配置文件依赖:采用 Cloudflare 官方推荐的 Remote Managed 架构,无需本地 credentials.json 或 config.yml。
  • 自动化 DNS 解析:创建隧道时同步完成 CNAME 解析记录的添加。
  • 一键生成连接器 Token:直接输出 Token,复制即可在任意机型(Linux、Windows、Docker 等)上快速部署连接器。
  • 人性化交互:支持在任意输入步骤中输入 0 安全返回主菜单。

前置准备

获取 Account ID 和 Zone ID

  1. 登录 Cloudflare 控制台。
  2. 点击你要绑定的目标域名。
  3. 进入该域名的概述页面,将页面向下拉,右侧边栏的 API 区域可以看到 Account ID 和 Zone ID。
  4. 复制备用。

创建 API Token

脚本需要一个有权创建隧道和修改 DNS 的 API Token:

  1. 点击右上角头像,选择我的个人资料,然后在左侧菜单点击 API 令牌。
  2. 选择自定义令牌,开始使用。
  3. 设置令牌名称。
  4. 在权限区域,添加以下两组权限:
    • 第一组:Account | Cloudflare Tunnel | Edit
    • 第二组:Zone | DNS | Edit
  5. 创建令牌,复制保存(注意只显示一次)。

填写到脚本中

拿到这三个参数后,打开脚本文件,找到配置文件区:

1
2
3
CF_ACCOUNT_ID="你的Account_ID"
CF_API_TOKEN="你的API_Token"
CF_ZONE_ID="你的Zone_ID"

请确保保留外层的双引号,不要留空格。保存退出后即可运行 bash argo_tunnel.sh

菜单功能详解

启动脚本后,你将看到如下交互菜单:

1
2
3
4
5
6
7
8
====================================================
         Cloudflare Argo 固定隧道管理               
====================================================
 1) 查看所有固定隧道
 2) 创建固定隧道 (包含域名配置与 Token 生成)
 3) 删除固定隧道
 0) 退出
----------------------------------------------------

查看所有固定隧道

列出当前账户下所有未被删除的 Argo 隧道。输出信息包括 Tunnel ID、隧道名称、当前连线状态。

创建固定隧道

选择此项后,引导你完成三步输入:

  1. 隧道名称:例如 my-web-tunnel。
  2. 完整域名:例如 app.yourdomain.com。
  3. 本地服务地址:默认值为 http://localhost:8001。

后台自动执行四步:

  • 创建云端 Remote Managed Tunnel
  • 设置 Ingress 路由规则
  • 添加 DNS CNAME 记录
  • 提取 Connector Token

删除固定隧道

输入目标隧道的 Tunnel ID 即可清理云端隧道实例。

如何使用生成的 Token 启动连接器?

方式 A:命令行直接运行

安装 cloudflared 后执行:

1
cloudflared tunnel run --token <你的_TOKEN>

方式 B:Docker 一键部署(推荐)

无需在宿主机安装 cloudflared:

1
2
docker run -d --name argo-connector --restart always \
  cloudflare/cloudflared:latest tunnel --no-autoupdate run --token <你的_TOKEN>

常用技巧与注意事项

  1. 中途退出/取消:在任何输入步骤中输入 0 并回车,脚本会中止操作并安全返回主菜单。
  2. 依赖包自动补全:脚本首次运行会自动检测系统环境,若缺少 curl 或 jq,会自动通过 apt/pacman/yum 补齐。
  3. DNS 重复问题:如果输入的域名之前已经手动创建过 CNAME/A 记录,脚本会提示跳过或报错,不会覆盖原记录。

脚本代码

  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
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/usr/bin/env bash

# ==============================================================================
# Cloudflare Argo 远程托管固定隧道管理脚本
# 功能:创建隧道(含路由与DNS绑定并输出Token)、查看列表、删除隧道
# ==============================================================================

CF_ACCOUNT_ID="********************"
CF_API_TOKEN="********************"
CF_ZONE_ID="********************"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

pause() {
    echo ""
    read -r -p "按回车键返回主菜单..."
}

check_env() {
    if [[ "$CF_ACCOUNT_ID" == *"你的"* || "$CF_API_TOKEN" == *"你的"* || "$CF_ZONE_ID" == *"你的"* ]]; then
        echo -e "${RED}[X] 请先在脚本顶部配置好你的 CF_ACCOUNT_ID、CF_API_TOKEN 和 CF_ZONE_ID!${NC}"
        exit 1
    fi

    if ! command -v jq &> /dev/null || ! command -v curl &> /dev/null; then
        echo -e "${BLUE}--> 正在自动安装基础依赖 (curl, jq)...${NC}"
        if command -v pacman &> /dev/null; then
            sudo pacman -Sy --noconfirm jq curl
        elif command -v apt &> /dev/null; then
            sudo apt update && sudo apt install -y jq curl
        elif command -v yum &> /dev/null; then
            sudo yum install -y jq curl
        fi
    fi
}

list_tunnels() {
    echo -e "\n${CYAN}====== 当前 Argo 固定隧道列表 ======${NC}"
    RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel?is_deleted=false" \
        -H "Authorization: Bearer ${CF_API_TOKEN}")

    SUCCESS=$(echo "$RESPONSE" | jq -r '.success // false')
    if [ "$SUCCESS" != "true" ]; then
        echo -e "${RED}[X] 获取列表失败:${NC}"
        echo "$RESPONSE" | jq '.errors'
        pause
        return
    fi

    TOTAL=$(echo "$RESPONSE" | jq '.result | length')
    if [ "$TOTAL" -eq 0 ]; then
        echo -e "${YELLOW}当前没有活跃的隧道。${NC}"
    else
        echo "$RESPONSE" | jq -r '.result[] | "ID: \(.id) | 名称: \(.name) | 状态: \(.status)"'
    fi
    pause
}

create_argo_tunnel() {
    echo -e "\n${CYAN}====== 创建 Argo 固定隧道 ======${NC}"
    
    read -r -p "1. 请输入隧道名称 (输入 0 返回): " TUNNEL_NAME
    if [[ "$TUNNEL_NAME" == "0" || -z "$TUNNEL_NAME" ]]; then return; fi

    read -r -p "2. 请输入绑定的完整域名 (例如 app.yourdomain.com, 输入 0 返回): " FULL_DOMAIN
    if [[ "$FULL_DOMAIN" == "0" || -z "$FULL_DOMAIN" ]]; then return; fi

    read -r -p "3. 请输入本地服务地址 (默认 http://localhost:8001, 输入 0 返回): " LOCAL_SERVICE
    if [ "$LOCAL_SERVICE" == "0" ]; then return; fi
    LOCAL_SERVICE=${LOCAL_SERVICE:-"http://localhost:8001"}

    echo -e "\n${BLUE}--> [1/4] 正在云端创建远程托管隧道 [$TUNNEL_NAME]...${NC}"
    CREATE_RESP=$(curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel" \
        -H "Authorization: Bearer ${CF_API_TOKEN}" \
        -H "Content-Type: application/json" \
        --data "{\"name\":\"${TUNNEL_NAME}\",\"config_src\":\"cloudflare\"}")

    if [ "$(echo "$CREATE_RESP" | jq -r '.success // false')" != "true" ]; then
        echo -e "${RED}[X] 隧道创建失败:${NC}"
        echo "$CREATE_RESP" | jq '.errors'
        pause
        return
    fi

    TUNNEL_ID=$(echo "$CREATE_RESP" | jq -r '.result.id')
    echo -e "${GREEN}[✔] 隧道创建成功!Tunnel ID: ${TUNNEL_ID}${NC}"

    echo -e "${BLUE}--> [2/4] 正在配置云端应用程序路由 ($FULL_DOMAIN -> $LOCAL_SERVICE)...${NC}"
    ROUTE_DATA=$(jq -n \
        --arg hostname "$FULL_DOMAIN" \
        --arg service "$LOCAL_SERVICE" \
        '{
            config: {
                ingress: [
                    {hostname: $hostname, service: $service},
                    {service: "http_status:404"}
                ]
            }
        }')

    ROUTE_RESP=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/configurations" \
        -H "Authorization: Bearer ${CF_API_TOKEN}" \
        -H "Content-Type: application/json" \
        --data "$ROUTE_DATA")

    if [ "$(echo "$ROUTE_RESP" | jq -r '.success // false')" != "true" ]; then
        echo -e "${RED}[X] 云端路由设置失败:${NC}"
        echo "$ROUTE_RESP" | jq '.errors'
    else
        echo -e "${GREEN}[✔] 云端路由规则配置完毕!${NC}"
    fi

    echo -e "${BLUE}--> [3/4] 正在添加 DNS CNAME 记录...${NC}"
    DNS_RESP=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records" \
        -H "Authorization: Bearer ${CF_API_TOKEN}" \
        -H "Content-Type: application/json" \
        --data "{\"type\":\"CNAME\",\"name\":\"${FULL_DOMAIN}\",\"content\":\"${TUNNEL_ID}.cfargot.com\",\"proxied\":true}")

    if [ "$(echo "$DNS_RESP" | jq -r '.success // false')" != "true" ]; then
        echo -e "${YELLOW}[!] DNS 绑定未成功 (可能域名已存在解析),请手动确认。${NC}"
    else
        echo -e "${GREEN}[✔] DNS CNAME 绑定成功!${NC}"
    fi

    echo -e "${BLUE}--> [4/4] 正在生成连接器 Token...${NC}"
    TOKEN_RESP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/token" \
        -H "Authorization: Bearer ${CF_API_TOKEN}")

    TOKEN=$(echo "$TOKEN_RESP" | jq -r '.result // empty')

    if [ -n "$TOKEN" ]; then
        echo -e "\n${GREEN}=================== 创建完成 ===================${NC}"
        echo -e "${BLUE}域名:${NC} ${FULL_DOMAIN} -> ${LOCAL_SERVICE}"
        echo -e "${BLUE}Tunnel ID:${NC} ${TUNNEL_ID}"
        echo -e "${BLUE}连接器 Token:${NC}"
        echo -e "${YELLOW}${TOKEN}${NC}"
        echo -e "${GREEN}================================================${NC}"
        echo -e "${CYAN}你在任意客户端只需运行以下命令即可上线该连接器:${NC}"
        echo -e "cloudflared tunnel run --token ${TOKEN}"
    else
        echo -e "${RED}[X] 获取 Token 失败。${NC}"
    fi
    pause
}

delete_argo_tunnel() {
    echo -e "\n${CYAN}====== 删除 Argo 隧道 ======${NC}"
    read -r -p "请输入要删除的 Tunnel ID (输入 0 返回): " TUNNEL_ID
    if [[ "$TUNNEL_ID" == "0" || -z "$TUNNEL_ID" ]]; then return; fi

    echo -e "${BLUE}--> 正在删除云端隧道...${NC}"
    RESPONSE=$(curl -s -X DELETE "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}" \
        -H "Authorization: Bearer ${CF_API_TOKEN}")

    SUCCESS=$(echo "$RESPONSE" | jq -r '.success // false')
    if [ "$SUCCESS" == "true" ]; then
        echo -e "${GREEN}[✔] 隧道删除成功!${NC}"
    else
        echo -e "${RED}[X] 删除失败:${NC}"
        echo "$RESPONSE" | jq '.errors'
    fi
    pause
}

main_menu() {
    check_env

    while true; do
        clear
        echo -e "${CYAN}====================================================${NC}"
        echo -e "${CYAN}         Cloudflare Argo 固定隧道管理               ${NC}"
        echo -e "${CYAN}====================================================${NC}"
        echo -e " 1) 查看所有固定隧道"
        echo -e " 2) 创建固定隧道 (包含域名配置与 Token 生成)"
        echo -e " 3) 删除固定隧道"
        echo -e " 0) 退出"
        echo -e "${CYAN}----------------------------------------------------${NC}"
        read -r -p "请选择操作 [0-3]: " CHOICE

        case "$CHOICE" in
            1) list_tunnels ;;
            2) create_argo_tunnel ;;
            3) delete_argo_tunnel ;;
            0) echo -e "${GREEN}退出程序。${NC}"; exit 0 ;;
            *) echo -e "${RED}无效选项!${NC}"; pause ;;
        esac
    done
}

main_menu

本文由 BOSH 的博客助手 HerMes 整理 🔧

原文链接:[本地上传]

热爱生活 学无止境
使用 Hugo 构建
主题 StackJimmy 设计