You need to enable JavaScript to run this app.
文档中心
云手机

云手机

复制全文
下载 pdf
最佳实践
基于 SSH 隧道实现本地 ADB 调试云手机实例
复制全文
下载 pdf
基于 SSH 隧道实现本地 ADB 调试云手机实例
当您需要在本地使用 ADB 调试云手机实例时,云手机平台提供了一种基于 SSH 隧道的安全接入方式。​
您在本地执行 ADB 连接后,请求会通过一条加密隧道转发到目标云手机实例的 ADB 服务,不需要为实例开放公网 ADB 端口。调试凭证由 OpenAPI 一次性签发,具备明确的有效期,用完即失效,适用于应用安装、日志抓取、shell 调试和自动化测试等日常场景。​
本文介绍如何调用 GetEdgeTunnelConnectionInfo 接口获取隧道信息,并在本地建立 SSH 隧道后使用 ADB 连接云手机实例。​
使用场景​
  • 需要通过 ADB 对云手机实例做应用安装、日志抓取、shell 调试、自动化测试等操作。​
  • 本地或办公网络访问 ADB 公网端口不便,或希望使用统一的鉴权凭证进行访问控制。​
  • 希望通过一次性签发的连接凭证来限制调试通道的作用范围与有效期。​
前提条件​
请提前在本地机器上准备以下工具。​
创建并绑定 ADB 密钥​
方式一:(推荐)本地生成密钥并导入公钥​
在本地生成密钥对后,将公钥导入控制台即可完成绑定,私钥始终保留在本地。适用于希望自行管理密钥的场景。​
  1. 执行以下命令,在本地生成密钥。​
注意​
HOME/ANDROID_SDK_HOME 路径中不得包含空格,否则 ADB Server 将静默失败,不会生成密钥文件。​
  • ​
    # 1. 准备一个无空格的 HOME 目录并导出​
    export ANDROID_HOME_ADB=/tmp/android_home_$(date +%s)​
    mkdir -p $ANDROID_HOME_ADB/.android​
    chmod 700 $ANDROID_HOME_ADB/.android​
    export HOME=$ANDROID_HOME_ADB​
    export ANDROID_SDK_HOME=$ANDROID_HOME_ADB​
    ​
    # 2. 触发 adb server 生成标准 ADB 公私钥对(PKCS#8 私钥 + AOSP mincrypt 公钥)​
    adb devices 2>/dev/null # 即使没有设备也会生成 adbkey​
    ​
    # 3. 检查生成结果(私钥 ≈ 1704 字节,权限 600;公钥 ≈ 721 字节)​
    ls -l $HOME/.android/​
    # -rw------- 1 user wheel 1704 adbkey ← 私钥,不要外泄​
    # -rw-r--r-- 1 user wheel 721 adbkey.pub ← 公钥,粘贴到控制台​
    ​
    # 4. 复制公钥内容,用于下一步粘贴​
    cat $HOME/.android/adbkey.pub​
    ​
  1. 登录 云手机控制台。​
  1. 单击目标业务卡片中的“进入业务”按钮。​
  • ​​​
  1. 在左侧目录树选择“网络与安全 > ADB 密钥对管理”,创建密钥对。​
  1. 在创建密钥对时,“绑定对象”选择“实例维度”、“创建方式”选择“导入已有公钥”,将第 1 步里复制的公钥内容粘贴至输入框。​
  1. 对已创建的密钥对 绑定目标实例。​
  1. 重启实例,使配置生效。​
注意​
重启实例为必要步骤,若跳过重启,ADB 密钥配置可能不会生效。​
方式二:通过控制台自动创建密钥对​
控制台将自动生成密钥对并完成绑定,私钥由平台统一托管,无需在本地执行任何命令。适用于无需手动管理密钥的场景。​
  1. 登录 云手机控制台。​
  1. 单击目标业务卡片中的“进入业务”按钮。​
  • ​​​
  1. 在左侧目录树选择“网络与安全 > ADB 密钥对管理”,创建密钥对。​
  1. 在创建密钥对时,“绑定对象”选择“实例维度”、“创建方式”选择“自动创建密钥对”,创建完成后密钥将自动下载。​
  1. 执行如下命令,将下载的私钥文件 保存到本机。​
  • ​
    # 保存路径示例:~/.android/adbkey;并设置权限​
    chmod 600 ~/.android/adbkey​
    export HOME=~ # 确保指向保存这个 adbkey 的 .android 父目录​
    export ANDROID_SDK_HOME=$HOME​
    export ADB_VENDOR_KEYS=$HOME/.android/adbkey # 备用环境变量​
    ​
  1. 对已创建的密钥对 绑定目标实例。​
  1. 重启实例,使配置生效。​
注意​
重启实例为必要步骤,若跳过重启,ADB 密钥配置可能不会生效。​
安装并检查基础工具​
  1. OpenSSH 客户端:用于执行 ssh -L 建立本地端口转发操作。​
  • 执行如下命令,返回 OpenSSH 客户端的版本号,即表示客户端已安装并且可以正常使用。​
  • ​
    ssh -V​
    ​
  1. ADB 客户端:是 Android 官方提供的调试命令行工具,用于连接本地转发端口,下载地址。​
  • 执行如下命令,返回本地 ADB 的版本信息,即表示工具已安装并且可以正常使用。​
  • ​
    adb version​
    ​
  1. 选择并安装如下工具:两种工具都是作为 OpenSSH 的 ProxyCommand,把 SSH 字节流通过 WebSocket 转发到隧道服务,任选其一安装即可。​
  • ws-tunnel 命令工具(推荐):火山引擎云手机官方提供的 OpenSSH ProxyCommand 辅助工具,专为本方案的隧道服务适配,开箱即用。​
  • 如何安装:下载压缩包并解压至本地进行安装。​
  • ​
    ​
    ws-tunnel-dist.tar.gz
    ​
    ​
  • 执行如下命令,返回 ws-tunnel v2.51.0-7-g167ae0f-20260731 版本信息,即表示工具已安装并且可以正常使用。​
  • ​
    ws-tunnel --version​
    ​
  • 支持使用以下文件验证工具完整性。​
  • ​
    ​
    SHA256SUMS
    ​
    ​
  • websocat 开源工具:开源的通用 WebSocket 字节流转发工具,可作为 ws-tunnel 的替代方案,下载地址。​
步骤一、调用 OpenAPI 获取隧道(Tunnel)连接信息​
调用 GetEdgeTunnelConnectionInfo 接口,为目标实例签发一次性调试凭证。凭证是一段包含鉴权信息,有明确有效期的连接地址,一次调试对应一份凭证,过期或调试结束后即失效。接口会直接返回可复制执行的 SSH 建连命令与 ADB 连接命令模板,避免手工拼接隧道地址时遗漏 URL 中的鉴权参数(即 ? 之后由 & 连接的 Query 参数,例如签名、会话 ID、有效期等),或在命令行中因特殊字符(如 &)未做转义而导致连接失败。​
步骤二、建立 SSH 隧道​
推荐直接从响应的 ConnectionInfo.Note 字段复制生成的 SSH 命令执行,示例代码如下。​
​
ssh \​
-o "ProxyCommand=ws-tunnel --url '<TunnelURL>'" \​
-o HostKeyAlias=<HostKeyAlias> \​
-o ControlMaster=yes \​
-o ControlPath=/tmp/edge-tunnel-<ConnectionId>.sock \​
-o ExitOnForwardFailure=yes \​
-o ServerAliveInterval=30 \​
-o ServerAliveCountMax=6 \​
-L 5555:<TargetHost>:5555 \​
-Nf \​
adb@<SSHHost>​
​
SSH 参数说明​
​
参数​
说明​
ProxyCommand=ws-tunnel --url '<TunnelURL>'​
设置 SSH 不使用默认的直连方式,而是先通过 ws-tunnel 工具将连接送入火山引擎的隧道服务,再抵达目标云手机实例。默认使用 ws-tunnel --url '<TunnelURL>'。若使用 websocat 替代,则替换为 websocat - --binary '<TunnelURL>'。​
如需手动拼接 URL,请将其中的 % 字符进行转义,即将 % 替换为 %%,避免因字符解析问题导致连接失败。​
HostKeyAlias=<HostKeyAlias>​
为本条隧道连接设置一个“名称”用于身份校验。SSH 首次连接时会把对方的“名称”记录至本地 ~/.ssh/known_hosts,下次再连同一别名时用它验证对方是否被替换。请直接使用接口返回的 HostKeyAlias,避免与本地已有 SSH 主机记录产生冲突。​
ControlMaster / ControlPath​
开启 SSH 的“连接复用”,后续对同一隧道的操作复用第一次的连接,避免重复握手。ControlPath 是这条连接在本地留下的“控制文件”路径,建议用接口返回的 ConnectionId 拼接以区分不同调试会话;关闭时使用 ssh -O exit 退出,不用强杀进程。​
ExitOnForwardFailure=yes​
若本地端口转发失败,SSH 立即退出,而不是继续保持一个“空隧道”误以为连接成功。当出现端口占用、参数错误等问题时,帮助排查及时发现问题。​
ServerAliveInterval / ServerAliveCountMax​
让 SSH 定期发出“心跳包”以确认连接存活。建议保留默认值,避免长时间无 ADB 交互时隧道被中间网络设备当作“闲置连接”提前断开。​
-L 5555:<TargetHost>:5555​
把本地 5555 端口“接管”下来,之后 ADB 访问 127.0.0.1:5555 的流量都会被转发到目标云手机实例的 ADB 端口。若本地 5555 已被占用,可换成 -L 15555:<TargetHost>:5555,相应地 adb connect 也要改成对应端口。​
-Nf​
让 SSH 只负责“打通隧道”,从而不打开远程 shell,并放到后台运行。排查问题时可以替换为 -N 或 -vvv 打印详细日志定位具体步骤。​
​
确认隧道已建立​
执行以下命令确认本地端口已经在监听。​
​
lsof -iTCP:5555 -sTCP:LISTEN​
​
若返回中出现由 SSH 进程持有的 5555 端口 LISTEN 记录,即代表本地端口已经在监听,隧道建立成功。​
​
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME​
ssh 12345 user 5u IPv6 0x123456789 0t0 TCP localhost:5555 (LISTEN)​
ssh 12345 user 6u IPv4 0x987654321 0t0 TCP localhost:5555 (LISTEN)​
​
步骤三、使用 ADB 连接云手机实例​
  1. SSH 隧道建立成功后,在本地执行以下命令即可通过 ADB 连接目标实例。​
  • ​
    adb connect 127.0.0.1:5555​
    ​
  1. 执行如下命令,查看设备列表。​
  • ​
    adb devices​
    ​
  • 当返回结果中设备状态为 device 时,表示连接成功,如下所示。​
  • ​
    List of devices attached​
    127.0.0.1:5555 device​
    ​
  • 此时可使用 ADB 命令连接云手机,了解更多。​
  • ​
    # 指定要操作的目标设备​
    adb -s 127.0.0.1:5555 shell​
    ​
    # 把当前目录下的 app.apk 安装包安装到指定的云手机实例上 ​
    adb -s 127.0.0.1:5555 install app.apk​
    ​
    # 实时打印该云手机实例的系统日志​
    adb -s 127.0.0.1:5555 logcat​
    ​
步骤四、结束调试并清理连接​
调试完成后,请主动断开 ADB 连接并关闭 SSH 隧道,避免残留监听进程和端口占用。​
  1. 执行如下命令,断开 ADB 连接。​
  • ​
    adb disconnect 127.0.0.1:5555​
    ​
  1. 若使用了 步骤二 中的 ControlPath,可以执行如下命令关闭 SSH 隧道。​
说明​
  • -S 后的路径需与 步骤二 中 ControlPath 的路径保持一致。​
  • adb@<SSHHost> 需与 步骤二 中 SSH 命令末尾的目标一致。​
  • ​
    ssh -O exit \​
    -S /tmp/edge-tunnel-sess_0380BB16CB10CF6B2DF0319EEA20078E.sock \​
    adb@7644710100737809196.1806209850762334208​
    ​
  • ​
最近更新时间:2026.08.25 10:10:52
这个页面对您有帮助吗?
有用
有用
无用
无用