不用 USB 调试,从电脑 SSH 连上 Root 安卓手机的全过程

机型:OPPO PJX110(一加 13)· ColorOS 16(Android 16)· 内核 6.1.141 · KernelSU 已 Root
目标:在不开 ADB、不插 USB 的前提下,从电脑远程拿到手机 root shell,用于系统优化和模块调试
环境:电脑 Windows + Git Bash,手机与电脑同一局域网(192.168.1.x)


一、为什么不用 USB 调试

我想从电脑远程管理手机——跑命令、查进程、装卸 LSPosed 模块、改系统参数。常规做法是「开发者选项 + USB 调试 + ADB」,但我不想为了偶尔用一次而长期开着调试开关,也不喜欢被线缆拴在桌前。

好在手机已经 Root(KernelSU),并且装了 Termux。思路非常简单粗暴:

在 Termux 里跑一个 SSH 服务端,电脑通过局域网连进来。

听起来十分钟就能搞定,实际却踩了好几个坑,其中最深的一个直接挖到了 OPPO 定制系统的内核网络过滤层。这篇文章完整记录过程。


二、手机端:在 Termux 里把 sshd 跑起来

打开 Termux,依次执行:

pkg install openssh -y   # 安装 SSH 服务端
termux-wake-lock         # 防止手机休眠后服务掉线
passwd                   # 设置登录密码(输入时不显示)
sshd                     # 启动 SSH 服务,默认监听 8022 端口

然后查一下手机在局域网里的 IP:

ip addr show wlan0 | grep inet
# 输出类似:inet 192.168.1.4/24

拿到 IP 之后,理论上电脑端一条命令就能连上:

ssh -p 8022 u0_a493@192.168.1.4

这里的用户名 u0_a493 是 Termux 的应用 UID,每台机、每次安装都不一样,在 Termux 里敲 whoami 就能看到。端口 8022 是 Termux sshd 的默认端口,不是标准的 22。


三、电脑端连不上:先别急着怀疑手机

不出意外,连不上。先做最基本的端口探测(Git Bash 下可以用 /dev/tcp 免装工具):

timeout 3 bash -c "echo >/dev/tcp/192.168.1.4/8022" && echo "reachable" || echo "unreachable"

结果是 unreachable

ping 192.168.1.4 是通的、0% 丢包——说明手机在线、网络可达,问题只出在 8022 这个端口上。

于是我把整个子网扫了一遍,想看看到底有没有哪台设备开着 8022:

for i in $(seq 1 254); do
  (timeout 1 bash -c "echo >/dev/tcp/192.168.1.$i/8022" 2>/dev/null \
    && echo "OPEN: 192.168.1.$i:8022") &
done
wait

结果相当离谱:254 个 IP 全部返回 OPEN

注意
踩坑提醒:如果电脑上开着代理软件(Clash / Mihomo / Surge 等),TUN 模式会接管所有 TCP 连接并对探测返回假成功,扫出来的结果全部是「OPEN」,完全不可信。要么先关掉代理,要么换用不受 TUN 影响的方式验证。
powershell -Command "Test-NetConnection -ComputerName 192.168.1.4 -Port 8022"

用 PowerShell 复测,结果是 TcpTestSucceeded : False——确认手机那一侧真的没有响应。


四、真正的根因:KernelSU 域 + OPPO BPF 网络过滤

排查到这里有点反直觉:在 Termux 里敲 sshd 明明没有任何报错,用 netstat 也看得到 8022 正在 LISTEN,但外部就是连不进来。

最终的根因非常有意思,涉及 OPPO 定制系统在底层做的网络过滤。

问题链条

所有服务通过 KernelSU 开机脚本启动
    → 进程的 SELinux 域是 u:r:ksu:s0
    → OPPO 的 BPF 网络过滤器按域拦截入站连接
    → 此时 iptables / SELinux 全部放行也没用(BPF 生效层级更底)

换句话说:即使你手动补上 iptables ACCEPT 规则、即使把 SELinux 设成 permissive,OPPO 的 BPF 程序依然会在内核网络栈层面直接丢弃来自 u:r:ksu:s0 域的入站连接。

这也解释了为什么会出现「服务在跑、端口在听、ping 得通,但 TCP 握手永远不成功」——丢包发生在比防火墙更靠下的位置。

解决方案

结论只有一句话:在 Termux App 内部启动 sshd,不要通过 KernelSU 开机脚本启动。

因为 Termux App 内启动的进程运行在正常的应用域(u:r:untrusted_app:s0),OPPO 的 BPF 过滤器不会拦截这个域的入站连接。

# 在 Termux App 里直接执行(不要用 su,也不要写进 KernelSU 启动脚本)
sshd

改完立刻就能连上了:

ssh -p 8022 u0_a493@192.168.1.4

五、配置免密登录

每次连都要输密码太麻烦,配一对 SSH 密钥:

# 电脑端生成密钥(已有可跳过)
ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519

# 把公钥推到手机上
PUB=$(cat ~/.ssh/id_ed25519.pub)
ssh -p 8022 u0_a493@192.168.1.4 \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
   echo '$PUB' >> ~/.ssh/authorized_keys && \
   chmod 600 ~/.ssh/authorized_keys"

之后连接不再需要输入密码:

ssh -p 8022 u0_a493@192.168.1.4

六、一键启动脚本与开机自启

问题来了:手机一重启,Termux 里的 sshd 就没了,每次都得手动打开 Termux 敲一次。做一个一键脚本:

# ~/start_ssh.sh
#!/data/data/com.termux/files/usr/bin/bash
pkg install openssh -y 2>/dev/null
termux-wake-lock
sshd
echo "SSH 服务已启动,端口 8022"
chmod +x ~/start_ssh.sh

以后重启手机,打开 Termux 执行 bash ~/start_ssh.sh 即可。

进阶:用 Termux:Boot 实现真·开机自启

如果装了 Termux:Boot 插件(从 F-Droid 下载,不要从 Google Play),就能做到开机后台自动启动,连 Termux 都不用手动打开:

mkdir -p ~/.termux/boot
cat > ~/.termux/boot/start_ssh.sh << 'EOF'
#!/data/data/com.termux/files/usr/bin/bash
termux-wake-lock
sshd
EOF
chmod +x ~/.termux/boot/start_ssh.sh

Termux:Boot 会在开机后自动执行 ~/.termux/boot/ 下的所有脚本。记得在系统设置里把 Termux 和 Termux:Boot 的电池优化白名单打开,否则 ColorOS 依然会把它们清掉。


七、连上之后能做什么

拿到 shell 后再 su 切到 root,就拥有了一台可远程操作的安卓设备。

# 从电脑连接(免密)
ssh -p 8022 u0_a493@192.168.1.4

# 拿到 root shell
su
# KernelSU 会弹窗请求授权,允许即可
# uid=0(root) gid=0(root) context=u:r:ksu:s0

常用操作一览:

操作 命令
查看进程 top -b -n 1 -m 15 -s 6
查看内存 free -m
查看第三方应用 pm list packages -3
冻结应用 pm disable-user --user 0 <包名>
强制停止应用 am force-stop <包名>
安装 APK pm install -r /path/to/app.apk
查看 LSPosed 日志 grep <关键词> /data/adb/lspd/log/verbose_*.log
查看内核参数 sysctl vm.swappiness

八、踩坑总结

现象 原因 解决
端口扫描全 OPEN 254 个 IP 全部显示端口开放 电脑端 Clash / Mihomo 的 TUN 接口拦截了连接探测,对所有连接返回假成功 用 PowerShell Test-NetConnection 绕过验证
SSH 连接超时 ping 通,但 8022 端口连不上 sshd 由 KernelSU 脚本启动,SELinux 域为 u:r:ksu:s0,被 OPPO BPF 网络过滤器按域拦截入站连接 改为在 Termux App 内部启动 sshd,使用正常 App 域
卸载 APK 失败 DELETE_FAILED_INTERNAL_ERROR 包已处于 stopped 状态且挂在受限用户下 改用 pm uninstall --user 0 <包名>
SSH 间歇性断开 执行长时间命令时连接中断 手机休眠后系统清理后台进程 termux-wake-lock + 电池优化白名单

九、写在最后

整个排查过程最大的收获,是搞清楚了 Android 厂商在内核层面做的安全机制。OPPO 的 BPF 网络过滤比 iptables 和 SELinux 更底层——传统的防火墙放行手段对它完全无效,甚至很难察觉到它的存在。

这也提醒一件事:Root 之后 ≠ 可以为所欲为,厂商的安全防线是分层的,绕过一层不代表绕过全部。

如果你也遇到类似问题,核心原则只有一条:

小贴士
让需要联网的服务运行在普通 App 域里,而不是 Root 脚本的特权域里。
© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容