文章目录不用 root我用 Tailscale 打通了云手机的 ADB 通道TL;DR一、起因一台不听话的云手机二、先想清楚问题到底出在哪三、第一次尝试IPv6 直连失败四、关键转折需要一个牵线的人但不一定是一台服务器4.1 Tailscale 到底做了什么大白话版4.2 为什么这条路能绕开没有公网 IP五、另一半拼图无线调试让 adb 不用 root 也能开门六、实操从零到 adb devices6.1 云手机侧6.2 电脑侧6.3 配对与连接6.4 固化端口为 5555七、踩坑记录坑 1Termux 里 su 找不到坑 2Termux 的 curl 符号缺失坑 3无线调试端口会漂移坑 4cmd 和 PowerShell 语法不一样坑 5切换端口后出现 offline 僵尸设备坑 6配对端口 ≠ 连接端口八、意外发现这台云机的 adbd 居然是 root能力定位九、能力验证adb 到底能不能用adb 能力边界十、这套方案适合谁适合不适合 / 需要换路还有一个必须提前确认的点十一、日常维护重启之后怎么办十二、结语附录 A命令速查附录 B检查清单附录 C本次实测环境不用 root我用 Tailscale 打通了云手机的 ADB 通道摘要云手机没有公网 IP、没有 root、厂商也不提供 ADB 入口常规教程都要求你租一台云服务器跑 frp。本文记录另一种做法用 Tailscale 组一个虚拟局域网配合 Android 11 的「无线调试」在两个约束不租服务器、不 root下拿到完整的 adb 控制能力。包含原理、实操、踩坑和实测的能力边界。关键词云手机、ADB、Tailscale、无线调试、Android 自动化、NAT 穿透TL;DR云手机和本地电脑都装Tailscale登录同一账号云手机打开开发者选项 → 无线调试Android 11不需要 root电脑执行adb connect 100.x.y.z:端口可选adb tcpip 5555把随机端口固化成 5555结果零服务器、零 frp、零 Termux、零 rootadb 全功能可用一、起因一台不听话的云手机我手上有一台桃心云手机型号 Mate 30pro想从本地电脑用 adb 控制它做 UI 自动化。正常手机插根 USB 就行云手机不行它在云厂商的 VPC 里地址是172.18.15.x外面根本路由不到。厂商也没有提供任何 ADB 入口。搜到的教程几乎都是同一个模板云手机装 Termux → 装 proot → 修 DNS → 装 frpc 云服务器装 frps → 开放端口 → 配 token 电脑装 frpc visitor → adb connect 127.0.0.1:55556这套方案本身没问题我在另一台云机上跑通过。但它有两个硬性前提你必须有一台公网服务器对应本文的约束一不想租云手机必须有 root对应约束二这台没有更麻烦的是这类教程里的坑极多Termux 的 curl 版本错配、Go 程序的 DNS 解析失败、Android 13 的 adbd 只听 IPv6、Termux 粘贴长 URL 被输入法污染……我上一台机器全部踩过一遍。所以这次我想找一个更简单的路。二、先想清楚问题到底出在哪很多人把这件事理解成需要一条隧道。但隧道只是手段真正的问题是两台机器互相找不到对方。看一下双方的地址设备地址别人能访问吗云手机172.18.15.19❌ 厂商 VPC 内部地址我的电脑192.168.1.100❌ 家庭局域网地址我的电脑240e:878:...:17a2✅ 公网 IPv6云手机没有公网地址电脑有一个公网 IPv6。于是有一个看起来很美妙的思路让云手机主动连到我的电脑走 IPv6不就完全不需要服务器了吗这个思路在逻辑上完全成立——只要云手机也有 IPv6并且能路由到我家。三、第一次尝试IPv6 直连失败先在云手机Termux里测一下能不能用 IPv6 出网curl-6-sS-o/dev/null-wHTTP%{http_code} IP%{remote_ip}\n--max-time10https://www.baidu.com结果curl: (7) Failed to connect to www.baidu.com:443 after 149 ms: Could not connect to server加上-v看细节* IPv6: 240e:ff:e020:98c:0:ff:b061:c306, ... * IPv4: (none) * Trying [240e:ff:e020:98c:0:ff:b061:c306]:443... * Immediate connect fail for 240e:ff:e020:98c:...: Network is unreachable * connect to 240e:ff:e020:98c:... port 443 from :: port 0 failed: Network is unreachable注意这一句from :: port 0from ::的意思是内核找不到任何可用的源 IPv6 地址——不是被防火墙拦了也不是 DNS 问题而是这台云手机压根没有被分配 IPv6 地址。结论很干脆云手机只有私网 IPv4无 IPv6 电脑 私网 IPv4 公网 IPv6 ↑ 双方都没有对方能到达的地址直连这条路在物理层面就断了。顺带说一句如果当时云手机真有公网 IPv6这条路是可行的——电脑起一个 frps云机主动反向连过去即可同样不需要额外的服务器。所以这个检查值得每次换云机时都做一遍。四、关键转折需要一个牵线的人但不一定是一台服务器直连不行那就必须有第三方帮忙牵线。传统做法是自己租一台公网服务器跑 frp但牵线这件事本身已经有成熟服务免费做了。这就是 Tailscale 这类 P2P 组网工具的价值。4.1 Tailscale 到底做了什么大白话版把 Tailscale 想成一个私人快递网络登记两台设备都主动向 Tailscale 的协调服务器发起出站连接出站不受 NAT 限制发牌协调服务器给每台设备分配一个虚拟地址100.x.y.z牵线把双方信息互换两端尝试直接打洞打通 → 数据 P2P 直连速度快打不通 → 走 DERP 中继能通但慢一点加密全程 WireGuard 加密即使走中继中继也看不到内容关键在于协调服务器只负责牵线不承载业务流量除非走中继所以你不需要租一台服务器并维护它。分配完地址后100.70.52.94就是云手机在虚拟局域网里的门牌号你的电脑访问它就像访问同一局域网里的设备。你的电脑 100.95.223.67 ══► 100.70.52.94 云手机 Tailscale 虚拟网络WireGuard 加密4.2 为什么这条路能绕开没有公网 IP因为两端都是主动往外连云手机 → Tailscale 协调服务器出站NAT 允许电脑 → Tailscale 协调服务器出站NAT 允许只要云手机能上网能 apt 装包就说明能就能被拉进这个网络。这和云手机有没有公网 IP、有没有 IPv6 完全无关。五、另一半拼图无线调试让 adb 不用 root 也能开门网络通了但云手机里还得有个接活的管家——adbdadb 守护进程。平时 adbd 只听 USB。要让它监听网络端口传统做法是setprop service.adb.tcp.port5555stop adbd start adbd这三条命令需要 root。这就是为什么旧教程都强调云机必须 root。但 Android 11API 30之后系统设置里直接提供了**「无线调试」**开关设置 → 开发者选项 → 无线调试 → 打开打开后系统自己就把 adbd 启动在 TCP 模式上监听一个随机高位端口。不需要 root不需要 setprop不需要重启 adbd。打开后云机会显示IP 地址和端口 172.18.15.19:37085这个37085就是 adbd 的门牌号。于是整个方案的两个前提就都满足了问题解法两台机器互相找不到Tailscale 虚拟局域网adb 开不了门Android 11 无线调试服务器和 root一个都不需要。六、实操从零到adb devices下面是浓缩版流程。每一步都带验证方法。6.1 云手机侧① 打开开发者选项设置 → 关于手机 → 连点「版本号」7 次。② 打开无线调试设置 → 系统 → 开发者选项 → 无线调试 → 打开。记下屏幕上的端口后面会变先记着。③ 安装 Tailscale有 Google Play搜索 Tailscale开发者认准Tailscale Inc.没有用云机浏览器打开https://pkgs.tailscale.com/stable/tailscale-latest.apk直接装④ 登录并连接打开 Tailscale → Sign in → 用 Google / Microsoft / GitHub 登录 → 点开关 → 系统弹出 VPN 授权 → 允许。连接成功后会显示mate-30pro.tailXXXX.ts.net 100.70.52.94 ← 记住这个 fd7a:115c:a1e0::xxxx:xxxx⑤ 关掉电池优化设置 → 应用 → Tailscale → 电池 → 无限制。不做这一步Android 的 Doze 会在后台杀掉 VPN表现为用着用着突然断了。⑥ 关闭密钥过期强烈建议浏览器打开https://login.tailscale.com/admin/machines→ 找到云机 →...→Disable key expiry。云机重新登录很麻烦关掉省事。6.2 电脑侧① 安装 Tailscalewinget install--id Tailscale.Tailscale-e或用官网安装包。装完登录同一个账号点 Connect。验证tailscale status预期能看到云机100.95.223.67 my-pc xxx windows - 100.70.52.94 mate-30pro xxx android -② 确认 adb 可用adb version需要 platform-tools30.0.0以上adb pair随 Android 11 一同提供。建议直接用最新版。6.3 配对与连接新设备第一次连接需要配对我的这台之前配对过所以直接连上了但新云机大概率要配对。云机无线调试 →使用配对码配对设备屏幕会显示Wi-Fi 配对码 123456 IP 地址和端口 172.18.15.19:41234 ← 注意这个是配对端口电脑adb pair 100.70.52.94:41234⚠️这里有一个非常容易踩的坑云机屏幕上显示的 IP 是它的内部地址172.18.15.19你根本连不上。要把IP 换成 Tailscale 地址端口保持屏幕上的配对端口不变。然后输入 6 位配对码Enter pairing code: 123456 Successfully paired to 100.70.52.94:41234接着连接连接端口不是配对端口adb connect 100.70.52.94:37085验证adb devices -l100.70.52.94:37085 device product:CHUNMEI model:Mate_30pro ...device状态就代表完全可用。再确认 shelladb shell echo ok6.4 固化端口为 5555无线调试的端口每次重启都会变我这次就从37085漂移到了33189。固化一次省心adb tcpip 5555输出restarting in TCP mode port: 5555注意这一瞬间 adbd 会重启当前连接会断开属正常现象。重新连adb connect 100.70.52.94:5555之后只要云机没重启永远用 5555。边界adb tcpip在云机重启后失效会回到随机端口模式需要重新做一遍。七、踩坑记录坑 1Termux 里su找不到~ $ su -c id No su program found on this device. Termux does not supply tools for rooting...command -v su返回的是 Termux 自己的包装脚本/data/data/com.termux/files/usr/bin/su不是真的 su。但这不影响本方案——因为根本不需要 root也不需要 Termux。这是我一开始按旧方案排查时走的弯路。有意思的是后来发现adb shell id显示uid0(root)。原因是adbd 本身以 root 运行和 Termux 是两回事Termux 是普通 APPuid 10xxx看不到系统的 suadbd 是系统服务本来就有 root。二者上下文不同。坑 2Termux 的 curl 符号缺失CANNOT LINK EXECUTABLE curl: cannot locate symbol nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation referenced by /data/data/com.termux/files/usr/lib/libcurl.so补了libnghttp2之后又冒出cannot locate symbol libssh2_crypto_engine原因是这台云机的 Termux 环境里有一批库停留在老版本而libcurl升级到了 8.23依赖链对不上。逐个补会一直冒新错正确做法是一次性升级pkg upgrade-y中途问openssl.cnf (Y/I/N/O/D/Z)直接回车选默认升级后curl 8.23.0 ... OpenSSL/3.6.5 libssh2/1.11.1 nghttp2/1.70.0这个坑只在用 Termux 验证网络时遇到最终方案不用 Termux所以可以完全跳过。坑 3无线调试端口会漂移同一台云机先显示37085后来变成33189。每次关开无线调试、云机重启都会变。所以要么每次回云机屏幕看一眼要么用adb tcpip 5555固化。坑 4cmd 和 PowerShell 语法不一样在 cmd 里执行 PowerShell 写法adb exec-out screencap -p $env:USERPROFILE\Desktop\a.png报文件名、目录名或卷标语法不正确。因为 cmd 不认识$env:而且:在路径里非法。通用写法cmd / PowerShell 都能跑adb shell screencap -p /sdcard/screen.png adb pull /sdcard/screen.png D:\adb_test\screen.png顺便还验证了文件传输能力。坑 5切换端口后出现offline僵尸设备adb tcpip 5555之后adb devices里会同时出现100.70.52.94:37085 offline 100.70.52.94:5555 device旧的 37085 记录已经是僵尸清理即可adb disconnect 100.70.52.94:37085如果报error: no such device说明已经自动清掉了忽略。坑 6配对端口 ≠ 连接端口云机无线调试页面上「IP 地址和端口」→ 用于adb connect「使用配对码配对设备」里的端口→ 用于adb pair这是两个不同的端口。用错会直接连不上。八、意外发现这台云机的 adbd 居然是 root连接建立后我随手跑了一下adb root输出adbd is already running as root再查身份adb shell iduid0(root) gid0(root) groups0(root),1004(input),1007(log),1011(adb),... contextu:r:shell:s0uid0但contextu:r:shell:s0—— 这是整份记录里最关键的一行。它说明DAC 层面进程是 root文件权限位对它不设限MAC 层面SELinux 域仍是shell不是su/magisk继续查构建信息结果更有意思属性值标准 AOSP 的含义ro.build.typeuseradbd 应以 shell 运行ro.debuggable0不可调试ro.secure1adbd 应降权getenforceEnforcingSELinux 生效按标准 AOSP这三个属性都意味着adb root应该失败。但这台成功了而且ls /data/data能列出 118 个应用目录。结论这是厂商魔改过的镜像——在user构建上打了补丁让 adbd 无条件以 root 运行同时放宽了 shell 域对/data/data的读取。能力定位普通 shell 这台云机uid0 SELinux shell 域 Magisk 完全体✅ 能读更多文件、能pm grant、能看应用数据目录⚠️ 写系统分区、改persist.*大概率仍被 SELinux 拦❌ 不是真正的完全 root这个差异因厂商而异。换一台云机上面这些结论可能完全不同建议每台都实测记录。九、能力验证adb 到底能不能用光看到device不够我做了一层能力验证验证项命令结果shell 执行adb shell echo ok✅ok截屏screencappull✅ 720×1300 真实画面UI 控件树uiautomator dump✅ 43 个节点text 完整安装 APKadb install -r✅Success启动应用monkey -p pkg -c LAUNCHER 1✅Events injected: 1文件传输adb push/adb pull✅对 UI 自动化来说这几项已经够了看得见截屏、定位得到控件树、点得动input、装得上install。adb 能力边界完整可用设备管理、应用安装/卸载、文件推拉、截屏录屏、UI 自动化、dumpsys、logcat、am、pm、input……部分受限能力限制input text中文只支持 ASCII中文需 ADBKeyboard 或输入法广播settings put某些键Android 12 有限制screenrecord默认最长 180 秒adb backupAndroid 12 基本废弃无 root 不可用除非像这台一样厂商魔改adb root、改系统属性、直接读写/data/data、刷机。十、这套方案适合谁适合云手机Android 11允许安装第三方 APK不禁止 VPN有些厂商会锁 VPNService没有 root或不想折腾 root不想为了一次 adb 连接去租服务器本地电脑不在云厂商 VPC 内不适合 / 需要换路情况替代方案Android 11 或无线调试被裁有 root → frp / SSH 反向隧道无 root → 厂商官方 ADB云机禁止 VPNfrp 公网服务器ZeroTier同样可能被禁云机有公网 IPv6可以不用 Tailscale电脑起 frps 反向隧道自建 redroid / 容器直接adb connect 容器IP:5555什么隧道都不用还有一个必须提前确认的点云机是不是还原型实例——重启后应用和登录状态是否保留。如果不保留每次重启都要重装 Tailscale、重新登录、重新开无线调试。这会让方案的日常成本大幅上升。建议先装个无关紧要的 APP重启一次看看还在不在。十一、日常维护重启之后怎么办云机重启后按这个顺序恢复① 云机确认 Tailscale 是 Connected必要时手动连 ② 云机开发者选项 → 无线调试 → 确认开着 → 记下当前端口 ③ 电脑adb connect 100.70.52.94:当前端口 ④ 电脑adb tcpip 5555 ⑤ 电脑adb connect 100.70.52.94:5555一键脚本端口已固化为 5555 时echo off set PHONE100.70.52.94 adb connect %PHONE%:5555 adb devices -l adb -s %PHONE%:5555 shell echo ok pause断线排查顺序1. tailscale status → 云机那行是否 online 2. ping 100.70.52.94 → 通不通 3. 云机本地 nc -vz 127.0.0.1 5555 → adbd 在不在 4. 端口对不对 5. 配对是否失效failed to authenticate 6. adb kill-server / start-server十二、结语这套方案的本质是把需要自己维护的基础设施换成了已经存在的服务旧方案新方案租云服务器 装 frpsTailscale 账号root setprop 开 adbd系统设置里的无线调试Termux proot frpcTailscale APPtoken secretKey账号登录代价是引入了对 Tailscale 这个第三方服务的依赖以及云机必须允许 VPN这个新约束。但对大多数个人使用场景来说这笔交换非常划算——从三台机器、三个进程、一堆配置文件变成两个 APP 和一条命令。至于那台云机adb shell居然是 root 的意外收获算是个彩蛋。它提醒我一件事云手机厂商的镜像差异极大任何标准结论都要自己实测一遍。附录 A命令速查:: 连接 adb devices -l adb connect 100.70.52.94:5555 adb disconnect 100.70.52.94:5555 adb kill-server adb start-server :: 配对 adb pair 100.70.52.94:配对端口 :: 固定端口 adb tcpip 5555 :: 设备操作 adb shell 命令 adb push 本地 设备 adb pull 设备 本地 adb install -r apk adb uninstall 包名 :: 自动化 adb shell screencap -p /sdcard/a.png adb shell uiautomator dump /sdcard/ui.xml adb shell input tap x y adb shell input swipe x1 y1 x2 y2 ms adb shell input keyevent 键值 adb shell am start -n 包名/Activity adb shell am force-stop 包名# Tailscaletailscale status tailscale ping mate-30pro附录 B检查清单云机Android ≥ 11开发者选项已开无线调试已开端口已记录Tailscale 已装、已登录、已 Connected已记录 100.x 地址电池优化已关闭key expiry 已关闭电脑Tailscale 已装、登录同一账号tailscale status能看到云机adb ≥ 30.0.0支持adb pairadbkey已备份换电脑时免配对连接已配对adb connect成功adb devices显示 deviceadb tcpip 5555已执行adb connect ...:5555成功附录 C本次实测环境项值云机Mate 30proproduct: CHUNMEI, device: OBXIN云机内部 IP172.18.15.19云机 Tailscale100.70.52.94云机 IPv6❌ 无adb shell 身份uid0(root)contextu:rs0SELinuxEnforcing构建属性user/debuggable0/secure1厂商魔改电脑Windows 11 (10.0.22000)电脑 Tailscale100.95.223.67adb 版本1.0.41 / 34.0.4初始端口37085后漂移为 33189固化端口5555说明文中配对流程按 Android 11 标准流程编写。实测设备因之前已配对adb connect直接成功未走配对把配对界面显示的 IP 换成 Tailscale IP是基于 adbd 监听所有网卡的推断新设备首次配对时请以实际结果为准。