Android 端口转发(Forward & Reverse) 的实操与避坑全指南
我的 Android 系统镜像精简得非常彻底,常用的网络调试工具(nc, python, telnetd)都没有内置。本次使用反向代理进行演示
# 1. 操作
# 1.1 示例一:在手机端快速查看电脑端内容
电脑端(服务端)
# 启用 python 内置模块 http.server 监听端口 9999 python3 -m http.server 99991
2建立反向转发 (Reverse):
adb reverse tcp:8888 tcp:99991手机端(客户端)测试: 使用手机自带的
curl(如果也没有,直接用浏览器访问http://localhost:8888):adb shell "curl http://localhost:8888"1预期结果:手机成功获取到了你电脑目录下分析脚本的文件列表,可以预览下载等操作。
# 1.2 示例二:用 Python 脚本实现“动态文件列表”接口
在电脑端创建脚本 server.py:
import http.server import socketserver import os PORT = 9999 class ListFileHandler(http.server.SimpleHTTPRequestHandler): def list_directory(self, path): # 强制列出当前目录下的所有 .csv 或 .py 文件 files = [f for f in os.listdir(path) if not f.startswith('.')] file_list_str = "\n".join(files) self.send_response(200) self.send_header("Content-type", "text/plain; charset=utf-8") self.end_headers() self.wfile.write(f"当前目录下的文件有:\n{file_list_str}".encode('utf-8')) return None with socketserver.TCPServer(("", PORT), ListFileHandler) as httpd: print(f"Serving at port {PORT}") httpd.serve_forever()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20运行此脚本.
python server.py开启反向转发
adb reverse tcp:8888 tcp:9999在手机端访问:
127.0.0.1:8888, 你会直接在手机终端看到清晰的文件名列表
# 1.3 手机使用电脑的代理工具
当手机没有网络,这里代理不通的时候。 可以让手机访问这个端口来翻墙或上网
建立反向代理隧道: 在电脑终端执行,将手机内部的
7890映射到电脑的7890:adb reverse tcp:7890 tcp:78901手机端配置(以 shell 为例): 在
adb shell中设置环境变量,让命令行工具(如curl)走这个代理:export http_proxy=http://localhost:7890 export https_proxy=http://localhost:78901
2测试联网:
adb shell "curl -I https://www.google.com"1全局上网(针对手机 App): 如果你希望手机里的 App 也能上网,需要在手机的 WiFi 设置 -> 修改网络 -> 代理 -> 手动 中,将代理服务器主机名设为
127.0.0.1,端口设为7890。由于你执行了reverse,手机访问自己的127.0.0.1:7890实际上就是在访问电脑。
⚠️ 关键避坑与技术细节
DNS 解析问题(大坑): 这是最容易失败的地方。即便你转发了 TCP 端口,手机可能依然无法解析域名(DNS)。
- 对策:在手机的代理设置里,确保代理协议支持远程 DNS 解析(如 SOCKS5),或者直接在
curl时使用 IP 地址测试。
- 对策:在手机的代理设置里,确保代理协议支持远程 DNS 解析(如 SOCKS5),或者直接在
代理工具设置: 在电脑端的代理软件中,务必开启 “允许局域网连接” (Allow LAN)。虽然
adb reverse看起来是 localhost 访问,但某些代理软件的防火墙策略会拦截非本进程发起的请求。HTTPS 证书: 如果你在电脑上使用了自签名证书的抓包工具(如 Charles 或 Fiddler),手机端访问 HTTPS 网站时会报证书错误,需要在手机上安装对应的根证书。
清理工作:恢复手机自己的上网功能
- 撤销 ADB 端口映射(电脑端操作)
# 停止所有的反向代理(针对 reverse) adb reverse --remove-all # 停止所有的正向转发(针对 forward,如果有的话) adb forward --remove-all1
2
3
4
5 - 清除手机系统代理设置(手机端操作 设置 -> WLAN -> 点击当前连接的 WiFi 详情/修改网络 -> 代理 -> 改为“无”。
- 清理 Shell 环境变量(adb shell 操作)
# 或者手动 unset 掉变量 unset http_proxy unset https_proxy1
2
3 - 清理进阶: 追求高效,可以把清理动作写成一个简单的脚本或 zsh alias,每次调试完“一键恢复”
alias adb_clean='adb reverse --remove-all && adb forward --remove-all && echo "ADB tunnels cleared."'
# 1.3.1 在未连接任何wifi的情况下设置代理
android 系统设计上的一个原生限制:系统级的代理设置界面是与具体的 WiFi 热点(SSID)绑定的。此方案实际测试下来感觉还是有点问题,作为参考记录下
对于这种需要在断网/无 WiFi 场景下通过 adb reverse 共享电脑网络的需求, 可以采用以下几种“非常规”手段来绕过这个 UI 限制:
1. 命令行强制注入(无需 WiFi,需 Root 或开发者权限)
是最硬核、最有效的方法。Android 的系统代理配置实际上存储在 Settings 数据库中。你可以直接通过 adb shell 修改它:
- 设置全局代理(立即生效):
settings put global http_proxy 127.0.0.1:7890 settings put global https_proxy 127.0.0.1:7890 settings put global all_proxy 127.0.0.1:78901
2
3 - 移除代理(恢复时必做):注:这种方式是系统级的,不管你连不连 WiFi,所有的流量都会尝试走这个代理。
settings delete global http_proxy settings delete global https_proxy settings delete global all_proxy1
2
3
# 二、问题记录
# 1. 端口幽灵冲突:多进程监听同一端口
- 现象:开启了 Python 服务监听
9999,结果curl出来的是 Node 博客的内容,且 Python 端没报错。 - 深层原因:
- IPv4 vs IPv6:一个进程占用了 IPv4,另一个占用了 IPv6,系统允许共存。
- 内核优先级:内核会根据地址具体程度或监听顺序分配流量,导致请求被 Node 进程“拦截”。
- 对策:养成使用
lsof -i :端口号确认真实 PID 的习惯。
# 三、 专家级进阶建议
- 清理习惯:
端口映射是持久生效的(只要不拔线)。为了避免占用系统资源或导致后续冲突,演示/调试结束后养成清理习惯:
adb reverse --remove-all
adb forward --remove-all
2
无线调试同样适用: 如果你开启了
adb connect [IP]无线连接,上述所有forward和reverse命令依然有效,这在调试 Redmi 7A/8A 等特定机型 的渲染性能时,可以摆脱数据线的物理束缚。配合 Python 自动化: 既然你擅长编写 Python 脚本,可以将这些命令封装进你的
AkShareAna分析流程中。例如:脚本分析完 BYD 财务报表后,自动执行adb reverse,然后通过os.system启动浏览器展示结果,实现“分析-传输-预览”全自动化。