---
name: cloudflared-ssh
description: 让任何云 Linux 机器通过 Cloudflare quick tunnel 实现 SSH 公网访问，无需公网 IP、自有域名或 Cloudflare 账号。一条命令安装 sshd + cloudflared、配置 root 密码（可自定义，留空则生成随机 16 位密码）、启动 tunnel 并输出连接信息。支持 x86_64 / aarch64 多架构，附 stop.sh 关闭暴露、status.sh 查看域名。适用于临时远程访问、演示、无公网 IP 的云/内网机器。
version: "1.1.0"
author: "WorkBuddy"
created: "2026-08-23"
updated: "2026-08-23"
tags:
  - ssh
  - cloudflare
  - tunnel
  - remote-access
license: MIT
---

# Cloudflared SSH 快速公网访问

本 Skill 把"用 Cloudflare quick tunnel 把本地 SSH 暴露到公网"封装成一条命令，让**任何云 Linux 机器**都能被外网 SSH 进来——不需要公网 IP、不需要自有域名、不需要 Cloudflare 账号。

## 适用场景
- 云机器没有固定公网 IP / 被 NAT 隔离，想从外地 SSH 进来
- 临时演示、远程协助、临时开发机
- 任何"我需要从别处 SSH 进这台机器"的时刻

## 目录结构
```
cloudflared-ssh/
├── SKILL.md
└── scripts/
    ├── setup.sh     # 安装 + 配置 + 启动 tunnel + 输出连接信息
    ├── stop.sh      # 关闭 tunnel（--full 同时停 sshd），撤销公网暴露
    └── status.sh    # 查看当前 tunnel 状态与域名
```

## 前置条件
- 有 `root` 或 `sudo` 权限（非 root 会自动 sudo 重跑）
- 机器能出网（至少能访问 `github.com` 或 `pkg.cloudflare.com` 之一）
- 本机（用来连接的那台）需安装 `cloudflared`（作为 SSH 的 ProxyCommand 代理）
- 支持架构：`x86_64`(amd64)、`aarch64`(arm64)、`armv7`、`i386`；arm 架构仅 github 路径可用

## 用法

```bash
# 1) 随机密码（自动生成 16 位强密码，仅 root 登录）
bash <skill-directory>/scripts/setup.sh

# 2) 自定义 root 密码
bash <skill-directory>/scripts/setup.sh myStrongPass123

# 3) 更安全的模式：新建 cfuser 专用账号 + 强制密钥登录，禁用 root 密码
bash <skill-directory>/scripts/setup.sh --no-root
#   然后把自己的公钥写入 /home/cfuser/.ssh/authorized_keys

# 查看当前域名 / tunnel 状态（不重跑、不换域名）
bash <skill-directory>/scripts/status.sh

# 用完关闭公网暴露
bash <skill-directory>/scripts/stop.sh          # 仅关 tunnel
bash <skill-directory>/scripts/stop.sh --full   # 连 sshd 一起停
```

> `<skill-directory>` 指本 Skill 所在目录，即 `cloudflared-ssh/`。

## 脚本做了什么（幂等、自包含、多架构）
1. **安装 cloudflared**：优先从 github release 下载对应架构；若 github 被墙且为 amd64，自动改用 `pkg.cloudflare.com` 官方 apt 仓库（已实测可用）。
2. **安装并启动 sshd**：`openssh-server` + 生成缺失的 host key（`ssh-keygen -A`，修复容器/新镜像启动即退出的问题）+ 监听 `0.0.0.0:22`。
3. **设置密码 / 账号**：root 自定义或随机 16 位（`openssl rand`）；`--no-root` 时新建 `cfuser` 并强制密钥登录。
4. **启动 quick tunnel**：`cloudflared tunnel --url ssh://localhost:22`，自动循环抓取分配的 `*.trycloudflare.com` 域名。
5. **输出访问信息**：域名、用户、密码、连接命令，并保存到 `/root/.cf-ssh-info`（权限 600）。

## 从本机连接
本机先装 cloudflared（mac/Win: `brew install cloudflared` / `winget install Cloudflare.cloudflared`），然后：

```bash
ssh -o ProxyCommand="cloudflared access ssh --hostname %h" root@<域名>
```

或写入 `~/.ssh/config`：
```
Host sandbox
    HostName <域名>
    User root
    ProxyCommand cloudflared access ssh --hostname %h
```
之后 `ssh sandbox` 输密码即可。

> **关键**：不能裸连 22 端口。Cloudflare 边缘只收 443，SSH 流量必须经本机 `cloudflared` 客户端做隧道封装。

## 底层原理
- SSH 服务跑在本地 `:22`，本身不出网。
- `cloudflared` 在本地起一个到 Cloudflare 边缘（quic/http2）的反向隧道，把 `ssh://localhost:22` 暴露为 `https://xxx.trycloudflare.com`。
- 连接时，本机 `cloudflared access ssh` 把 SSH 流量封装进隧道，回源到这台机器的 `:22`。

## 安全建议（重要）
| 风险 | 建议 |
|------|------|
| **root + 密码直曝公网** | `trycloudflare.com` 域名公开可扫。优先用 `setup.sh --no-root`（新建专用账号 + 密钥）；若必须 root，连上立即 `passwd` 改密码 |
| **长期暴露** | 用完即 `stop.sh` 关 tunnel；不要用它做长期入口 |
| **机器重启** | 脚本不注册 systemd 服务，重启后需重新 `setup.sh`（且域名会变） |
| **固定域名替代** | 有 Cloudflare 账号 + 自有域名时，用持久隧道：`cloudflared tunnel --hostname 子域.域名 --url ssh://localhost:22` |
| **连接侧** | 客户端也应装 cloudflared，且建议本地 `~/.ssh/config` 固定 Host 别名 |

## 注意事项
| 项 | 说明 |
|----|------|
| **域名是临时的** | quick tunnel 域名随机，进程退出 / 机器重启即失效，需重跑脚本拿新域名（`status.sh` 可在不重跑时查当前域名） |
| **会休眠的机器** | 若机器休眠/回收，tunnel 随之失效 |
| **arm 架构** | 仅 github 下载路径可用；`pkg.cloudflare.com` 只提供 amd64 deb |
| **信息落盘** | 连接信息（含密码）写入 `/root/.cf-ssh-info`，权限 600；请妥善保管或及时删除 |

## 排错
- **连不上 22**：先看 `setup.sh` 输出里 `22 端口未监听` 警告；多因缺 host key，脚本已自动 `ssh-keygen -A`。本机需装 `cloudflared` 才能用 ProxyCommand。
- **域名一直抓不到**：看 `/tmp/cf-ssh-tunnel.log`，通常是机器出网被限制；确保能访问 `region1.argotunnel.com`。
- **github 下载失败**：amd64 会自动走 `pkg.cloudflare.com` 兜底；arm 架构无兜底，需手动上传对应二进制到 `/usr/local/bin/cloudflared`。
- **架构不匹配**：脚本按 `uname -m` 自动选 amd64/arm64；若手动放置二进制请确认架构一致，否则运行即崩溃。
