hxmy proxy —— 你的pixel 手机也可以是超级代理服务器(2026.8.15))
本帖最后由 wresource 于 2026-8-19 20:27 编辑谷歌商店链接:https://play.google.com/store/apps/details?id=com.mzstd.hxmyproxy
经过过去一个多月的测试,现在这个 App 基本已经趋于完善了,稳定性比最开始提升了很多,UI 也做了进一步优化。另外这段时间还加了一个我自己非常喜欢的无缝流转功能。目前 macOS 这边我写了一个配套脚本(有需要的话后面可以发出来),可以自动切换 IP。只要手机开启这个 App,电脑和手机处在同一个网络里,基本就可以做到随时随地直接使用,不需要每次换网络之后重新查 IP、重新配置代理。目前自己实际用下来的体验已经非常不错了 :lol
果然还是自己每天都在用的 App 才比较有动力一直更新。以前也一腔热血开发过一些东西,但自己平时根本不用,最后基本都是雷声大雨点小,没多久就停更了。这次后面还准备陆续上线几个自己长期使用的工具:比如 hxmy asset,准备替代 Fortune City,做一个把全球资产集中到一个 App 里管理的资产记录工具;hxmy task,准备替代 Google Tasks;以及 hxmy note,用来替代印象笔记。这几个都是我自己日常高频使用、而且已经用了三年以上的应用,所以这次准备按照自己的实际使用习惯重新做一遍,重点解决原来这些 App 里一直让我觉得比较难受的地方,同时也会比较重视隐私和交互设计。大家有什么想法也可以提提意见。
先说这个 App 的起因
Android 17 推送那天,我手机升级完之后,Every Proxy 突然就不能共享了。其他设备连不上,也不报错,就是单纯连不通。后来查了一圈才发现,Android 新增了一个本地网络权限 ACCESS_LOCAL_NETWORK,targetSdk 到 37 的应用,在进行局域网通信之前需要申请相关权限。如果没有正确处理,LAN 流量就可能直接失败,而且比较坑的是,它不一定崩溃,也不一定给你一个非常明显的错误,看起来就是“静悄悄地不通”。
官方说明在这里:
https://developer.android.com/privacy-and-security/local-network-permission
代理软件整个业务本来就高度依赖局域网通信,这一下基本正好砍在命门上。当时 Every Proxy 没有及时适配,我就这么被卡住了。其实在那之前,我用它的时候就已经积累了一些不太舒服的地方,比如换网络以后偶尔需要重新启动才能恢复、某些域名偶尔连不上等等。但毕竟代码不是自己的,出了问题除了等作者更新也没有别的办法。那天干脆一想:既然这样,不如自己写一个。
这东西到底解决什么问题
Pixel 7 之后的机器自带一项 Google 的“魔法服务”,官方说明在这里:
https://support.google.com/pixelphone/answer/2819573
这个东西本身很好用,但有一个很明显的限制:它只保护手机自己。家里的电视、Switch、iPad、笔记本电脑这些设备,一个都沾不上。有些设备压根没地方安装对应的软件,有些即使能装,实际使用起来也未必方便。
如果想让这些设备也走手机上的那条线路,流量就必须先进入手机,再由手机上的 App 转发出去。直接开启手机热点并不能解决这个问题,因为热点那条路径本质上走的是系统内核转发,数据包并不会经过普通应用,因此和手机上启用了什么服务基本是两回事。
所以这个 App 做的事情其实很简单:在手机上监听一个代理端口,其他设备把手机当成代理服务器,流量进入手机之后,再由 App 按照你指定的网络接口转发出去。这样电视、电脑、平板这些设备什么都不用装,只需要配置一次代理地址就可以使用。
那有人可能会问:路由器不能干这个事情吗?答案是,大部分功能路由器当然能干,但最关键的这一件事干不了。规则分流、广告拦截、流量统计这些功能,路由器上都有非常成熟的解决方案,比如 Pi-hole、AdGuard Home 等,我完全不否认这些方案比我成熟得多。但是路由器拿不到 Pixel 上那项 Google 服务,它是和手机绑定的,只有手机自己能够使用。你在路由器上写再多规则,也没办法让电视的流量凭空跑到 Pixel 手机上的那条线路里。
这其实就是这个 App 最核心、也是最不可替代的用途。没有“共享手机这条线路”这一层,我这个东西确实就没什么存在的必要了。所以它的目标用户也比较明确:手里最好是 Pixel 7 或更新的机器。如果没有这个使用场景,后面那些广告拦截、分流、统计之类的功能,很多路由器方案都可以替代。
既然流量都从这里经过了,那就顺手多做几件事
既然所有流量都已经经过这一跳了,如果单纯只做转发多少有点浪费,所以后面又陆续加了一些自己平时确实会用到的功能。
第一是广告和追踪拦截,目前内置了 61063 条规则。这里有个细节可能很多人没有注意过:我的判断是在拿到目标域名之后、真正进行地址解析之前完成的。HTTPS 的 CONNECT 请求按照协议需要把目标主机信息带过来,因此客户端使用什么 DNS 解析方式,并不会直接绕开这一层判断,包括现在比较常见的加密 DNS。这和单纯在 DNS 层进行拦截是两个不同的位置。
第二是按域名进行分流。哪些域名走指定线路、哪些域名直接连接,都可以单独设置。另外目前还内置了 65 组、共 5445 条常用 App 和服务的一键直连规则,包括微信、支付宝、各家银行券商、视频音乐等。这个功能对我自己挺重要,因为有些国内服务如果发现你的出口在境外,会出现降级、风控甚至直接拒绝访问的情况,所以把这些流量直接走本地网络会舒服很多。
第三是流量可视化。现在可以看到哪个设备访问了哪些域名、拦截了多少请求、最终走的是哪张网络,同时可以按日、周、月、年查看统计。蜂窝网络我单独拆出来显示,因为它是这些出口里唯一可能直接产生流量费用的。
和 Every Proxy 相比,两边重合的功能主要是 HTTP、HTTPS CONNECT、SOCKS5、PAC、接口绑定以及免 Root。区别主要在下面这些:
广告和追踪拦截 我有 61063 条,它没有
域名规则分流 我有,它没有
常用 App 一键直连规则集 我有 65 组 5445 条,它没有
指定直连流量走哪张网 我有,它没有
备用 DNS 并可选择出口 我有,它没有
流量统计按出口分列 我有,它没有
实时速率和连接数 我免费,它需要付费升级
丢包率和健康诊断 我有,它没有
这里的对比主要依据 Every Proxy 官网和商店页面公开写出的功能:
https://www.everyproxy.co.uk/
当然,它也有一个我没有的功能:SOCKS4。这个我确实没做,目前也暂时没有做的计划。
跑分,以及我怎么把自己坑了一次
后来我拿 Majestic Million 前 450 个域名做了一轮对比测试,两边同时运行,结果大概是:
中位 TTFB 我 2.004 秒 它 2.333 秒 快 14.1%
逐站更快 我 204 站 它 113 站
大文件下载 我 6.17 MB/s 它 5.42 MB/s
符号检验 z = 5.21 p < 0.0001
复杂页面上的差距会更明显一点。这一组是直接用真实浏览器完整渲染页面测试的:
checkout.stripe.dev 我 5.3 秒 它 38.8 秒,超时
apps.apple.com 我 10.3 秒 它 38.3 秒,超时
github.com 我 2.1 秒 它 7.9 秒
play.google.com 我 2.6 秒 它 13.5 秒
像支付页面、新闻站这种页面,一次可能会同时建立几十条连接,每个第三方域名都要分别经过 DNS、TCP、TLS 等过程,所以代理层多出来的一点开销,在这种页面里会被放大很多。
不过数字归数字,这里面其实有个挺有意思的过程,因为我第一次测试的时候完全测错了。最开始我是先把 A 全部跑完,再跑 B,看起来好像挺合理,结果测出来差距大得连我自己都不信。后来才反应过来,上游线路的延迟本来就在实时变化,前后相隔太久,两组数据里面到底有多少来自线路漂移根本没办法区分。后来改成两个代理同时开启,每个域名紧挨着测试两边,时间间隔控制在两秒以内,结果才稳定下来。
然后又发现第二个坑:同一对测试里面,第二个被测的软件很可能直接命中手机已经存在的 DNS 缓存,相当于白占了一点优势。所以最后又把测试顺序按奇偶域名交替,偶数域名我先测,奇数域名 Every Proxy 先测,把这个偏差尽可能抵消掉。后来还是不放心,又做了一轮双预热重测,两种测试方法得到的结论基本一致,我才觉得这个数据比较有参考价值。
为什么不用现成的网络框架
写这篇之前,我把 Every Proxy 的 APK 解开简单看了一下,它的网络转发部分使用的是 Netty。感兴趣的话其实自己也能验证:
unzip -p "Every Proxy.apk" classes*.dex | strings | grep -c "io/netty"
Netty 本身当然是非常优秀的框架,服务端领域基本属于标杆级别,这个没什么好争的。但 Android 是另外一个环境。Netty 官方 Requirements 页面主要写的是 Java 运行和编译环境,并没有把 Android 作为主要支持目标,相关 CI 里也没有看到针对 Android 的测试:
https://netty.io/wiki/requirements-for-4.x.html
Google 自己的 gRPC 其实说得更加直接。grpc-java 的 README 里对 Netty transport 的说明中明确提到它并不正式支持 Android,Android 客户端推荐使用 OkHttp:
https://github.com/grpc/grpc-java
去年秋天也确实发生过一个和这个场景非常接近的问题。有人提交 issue,反馈某些 Netty 版本在 Android 8 到 12 上启动时会遇到 VerifyError,其中涉及新引入的 VarHandle 无法通过旧版 ART 校验,而报告问题的人恰好也是在 Android App 里使用 Netty 做代理。相关 issue 在这里:
https://github.com/netty/netty/issues/15654
这个事情其实又回到了我最开始自己写这个 App 的原因:如果最核心的转发层完全依赖一个并不把 Android 当主要目标的平台组件,那么哪天出了兼容性问题,你还是只能等别人。所以最后转发核心我直接使用 JDK 自带的 java.nio 来做,没有再引入第三方网络框架。
顺便说个自己的乌龙。我一开始还以为两边都是纯 JVM、完全不带原生库,写到一半才发现自己 APK 里其实有 8 个 .so,是 AndroidX 组件带进来的,加起来七十多 KB。Every Proxy 反而一个都没有,这一项它比我干净,差一点就被我写反了 :lol
协程这块,可能是我自己最想聊的
Android 官方对 Kotlin 协程的态度其实非常明确:
Coroutines is our recommended solution for asynchronous programming on Android.
https://developer.android.com/kotlin/coroutines
不过这里要区分一下,官方推荐主要是 API、开发体验和生态层面的推荐,并不能简单等同于“运行速度一定更快”。真正帮到我的一点,其实是线程数量终于不再随着连接数量一起增长。
最开始的时候我写得比较笨,一条隧道直接开两个阻塞线程,128 条连接就是 256 个线程,然后很快就把自己玩崩了。后来改成 NIO Reactor,Selector 线程按照 CPU 核数计算,最多只开 4 个。真机实际跑的时候并发连接峰值到过 107 条,但 Selector 线程还是维持在 2~4 个,不会跟着连接数疯涨。
现在一条客户端连接对应一个协程,从连接进来到最终关闭,逻辑基本就是顺着往下执行:
解析目标 → 规则判定 → DNS → 选出口 → 建 TCP → 回握手 → 转发直到结束
整个流程非常直观,哪一步需要限制时间,就用 withTimeoutOrNull 包起来。真正让我觉得协程舒服的其实还不是“代码短”,而是取消和资源释放。客户端中途断开以后,传统写法需要自己非常仔细地处理当前进行到了哪一步、哪些 Socket 要关闭、哪些资源要释放;协程这边取消以后可以顺着作用域级联下去,隧道拆掉、两端关闭、连接名额释放,不需要额外维护一套复杂状态机。而这种状态机恰恰是代理程序最容易漏分支的地方,一旦漏掉就是 FD(File Descriptor)泄漏,而且通常还特别难查。
另外还有个意外收获,因为一条请求本身就是一个完整的协程作用域,所以追踪信息可以一路传下去。规则判定结果、DNS 从哪里得到、最后连到哪个 IP、失败在哪一步、隧道为什么关闭,都可以通过同一个 ID 串起来。靠这套追踪数据,我后来反而删掉了三个自己早期凭感觉加进去的机制,因为终于可以拿实际数据判断它到底有没有作用,而不是“我觉得这样可能会更好”。
今年 7 月 Google 还发了一篇《How R8 made Kotlin Coroutines on Android 2x faster》,里面介绍了 R8 如何把 Atomic 字段更新器进一步优化为 Unsafe 相关实现,使部分协程启动和取消场景获得明显提升。这个优化我属于什么都没干,跟着生态白吃了一波 :lol
https://android-developers.googleblog.com/2026/07/how-r8-made-kotlin-coroutines-2x-faster.html
IPv6 是最近才补上的,顺手记录一个坑
之前这个 App 是出站可以走 IPv6,但从 IPv6 地址入站一直连不上。我一开始还以为只是接口扫描的时候把 IPv6 地址过滤掉了,心想把那一行删掉不就完了。真正去查才发现完全想简单了:原来的准入网段表是用 32 位整数保存地址的,而 IPv6 是 128 位,压根塞不进去。也就是说就算把接口扫描放开,IPv6 网段本身也没有真正进入准入集合。
最后把准入逻辑改成按照字节比较网络前缀之后,IPv4 和 IPv6 才都正常工作。两种地址本身长度不同,也可以天然区分,不会出现互相误放行的问题。
顺手还修了一个 IPv6 显示上的小坑。IPv6 地址写进 URL 时必须加方括号,比如不能直接写 fd00::1:8090,因为冒号既是 IPv6 地址的一部分,又承担端口分隔符的作用。现在 App 会直接把地址显示成正确的带方括号格式,避免有人照着界面手动配置的时候填错。
模拟器上也专门测了一遍:接口列表里 IPv4、IPv6 可以同时出现,准入集合两边都能正确识别,通过 IPv6 发过来的请求该返回 400 的仍然返回 400,CONNECT 到回环地址也依然会被出口安全限制拦住,目前这部分基本已经正常。
谁比较适合折腾这个
首先当然是手里有 Pixel 7 或更新机器,并且确实有把手机这条线路共享给其他设备需求的人。没有这个需求的话,这个 App 最核心的价值就不存在了,剩下的广告拦截、分流、统计之类功能,其实完全可以找到其他成熟方案。
其次是像我一样,有比较高频的跨设备使用场景。比如我自己日常主力电脑是一台 MacBook Pro 2021,很多时候就是手机和电脑一起使用。以前每次换 Wi-Fi、换热点以后重新确认 IP、重新设置代理非常烦,现在加上自动切换之后,基本可以做到手机 App 开着,电脑就直接用,整个过程几乎感觉不到网络发生过变化。这也是目前我自己觉得提升体验最大的一块。
项目地址:
https://github.com/wresource/hxmy-proxy
支持 Android 10 及以上,免费,没有内购,不需要注册,也不会把使用数据上传到服务器。一路开发下来坑确实踩了一大堆,目前我自己已经作为日常工具长期使用了。大家如果也有类似需求,可以拿去折腾,有 Bug 或者有什么功能建议,也欢迎直接提 issue 骂我 :lol
很好用 我不喜欢 play store 的一点是它把开发者的住址都写在网页里了 本帖最后由 wresource 于 2026-8-15 17:00 编辑
HelloWorld 发表于 2026-8-15 16:54
我不喜欢 play store 的一点是它把开发者的住址都写在网页里了
哈哈哈哈哈哈,等等apple store居然没有,不过有名字,我这个是公共场所的地址,问题不是很大:'( wresource 发表于 2026-8-15 16:58
哈哈哈哈哈哈,等等apple store居然没有,不过有名字,我这个是公共场所的地址,问题不是很大 ...
那还好 HelloWorld 发表于 2026-8-15 18:08
那还好
论坛怎么不支持markdown渲染啊,感觉不太好发:'( wresource 发表于 2026-8-16 01:32
论坛怎么不支持markdown渲染啊,感觉不太好发
估计得改源码 终于解决了我的一个疑问。此前一直用every proxy来共享pixel vpn的,突然有一天,无论如何都不成功,已经放弃。今天看到你的这个app,试了一下,的确能够用。另外,还顺带解决了另一个问题:我有一张美国的手机卡,可以漫游,但无法开热点,这样就可以绕过限制了。github已star! tmknui 发表于 2026-8-16 14:50
终于解决了我的一个疑问。此前一直用every proxy来共享pixel vpn的,突然有一天,无论如何都不成功,已经放 ...
感谢,我就是因为这个才写的这个app:lol 版面太难看了 forfree 发表于 2026-8-16 23:49
版面太难看了
app 吗?我感觉比上一个版本好,因为这个app就是那种配置完,几乎就不用动的,所以可能规则以及分析的东西比较多:shutup: