Android VPN 转 Socks5 代理应用分享

2023-02-17 21:20:27 +08:00
 heiher

大家好,我又来分享轮子啦~

SocksTun是我最近开源的一个基于HevSocks5Tunnel实现的 Android VPN ,用于将手机端的 TCP 、UDP 流量通过 Socks5 代理进行转发。其实它只是一个参考实现,主要用于演示如何用 HevSocks5Tunnel 实现 VPN 。它可以对接明文的标准 Socks5 协议,比如 Socks5 服务(或映射)部署在本地局域网,也是能具有一些实用性的吧。

特性支持

使用方法

服务端

HevSocks5Server

HevSocks5Server支持 UDP 从 TCP 转发,可以运行在 Linux/BSD 和 macOS 系统上,配置、使用方法也比较简单。

# 下载、编译
git clone --recursive https://github.com/heiher/hev-socks5-server
cd hev-socks5-server
make

# 运行
hev-socks5-server conf.yml

conf.yml:

main:
  workers: 4
  port: 1080
  listen-address: '::'

misc:
  limit-nofile: 65535

其它

任意支持标准 Socks5 协议的 TCP(Connect)和 UDP(Associate)的服务端即可。

手机客户端

  1. 从项目发布页下载 APK 并安装。
  2. 打开应用,配置 Socks5 地址、端口和 DNS 地址。
  3. 如果使用 HevSocks5Server 服务端,钩选 UDP relay over TCP ;使用其它服务端则去掉。
  4. 保存配置后,点击启用开启 VPN 服务。

性能评测

Android VPN App 目前还没有做过性能、能耗的评测(其实是不会~),之前在低性能的 RK3399(AArch64 架构)设备做过几款 tun2socks 的评测,结论是只有 HevSocks5Tunnel 可以几乎跑满物理网卡的最大带宽,并且对应的 CPU 资源使用最少。那么,基于它实现的 Android VPN 应该具有相对较好的节能效果吧。

速率

CPU 使用率

最后

最开心的事情当然是开源的这些小轮子能跑起来,确实对大家有用,期待支持与反馈~

4703 次点击
所在节点    分享创造
42 条回复
specture
137 天前
@heiher 请问一下在 ios 或者安卓上怎么做 dns 的 hijack ? 我看 clash.meta 的实现是在 tun 中判断 udp 的目的 IP 和端口,然后调用 fakedns server 做解析。Hev-socks5-tunnel 的实现下应该怎么做呢?
heiher
137 天前
@specture #21 在 Socks5 服务端做分流、规则策略等。
specture
136 天前
@heiher 请问下这个 socks5 服务端是值本机的 socks5 服务端部分还是指 远程服务器侧的 socks5 服务?按我理解应该是本机的部分?因为并不是所有流量都要走代理,所以一定会在本机这做解析和分流
specture
136 天前
@heiher 如果是本机的服务端部分,我理解是否正确:dns 请求的 UDP 53 端口请求流量通过 socks-tunnel 从 tun 到 tunnel 再到本机运行的 clash/v2ray 等 socks5“服务端”。 服务端里面基于 dst.port 和 dst.ip 判断是否为 dns 请求,如果是 dns 请求调用 fakedns 做解析,拿到解析结果后通过一个 udpconn 写回发起 dns 请求的 127.0.0.1:59001 这样的源地址?
cnfzv
134 天前
用的别的普通 socket 服务器( https://github.com/txthinking/socks5),失败了 socks5: 2023/12/29 23:42:38 [E]: client want to used addr 0.0.0.0:0, listen addr: [::]:56804
cnfzv
133 天前
@cnfzv 。找到问题了,简单的 socks 服务器不支持 udp bind 导致的。。。。。。
heiher
133 天前
@specture hev-socks5-tunnel 只做 tun2socks 业务,如果有部分流量本地直连的需求,那么分流器要运行在本地侧。分流器是 socks5 服务器,通过 socks5 协议与 socks5-tunnel 交互。关于 fakedns 流程大概是这样:

1. 应用程序请求解析域名的 ip 地址,相应的 dns 请求发送到 tun 。
2. socks5-tunnel 收到 tun 上的 udp 协议的 dns 请求后,通过 socks5 udp associate 方式发送给分流器。
3. 分流器通过协议识别(比如目标端口或报文内容等)发现是 dns 请求,重定向请求至内部的 fakedns 模块,生成 fake ip 的 dns 响应,发回 socks5-tunnel 。
4. 应用程序收到 dns 响应后,开始发起对 fake ip 的访问。相应的 tcp 或 udp 报文再次被分流器捕获,分流器通过报文中目标地址的 fake ip 查找分流规则, 建立与远程服务器的连接。
heiher
133 天前
@cnfzv 如果 socks5 服务端不支持 udp associate 命令,只能支持 tcp/ip 。基于 udp 的 dns 也不能支持。换一些 socks5 服务端即可。
cnfzv
133 天前
@heiher 0,0 我测试了,包括你提供的服务器都不好用。。。。使用你的 hev-socks5-server ,选择使用 tcp 中继可以使用,取消选择后 udp 请求会有问题。
hev-socks5-server 部署在 Ubuntu22 上,使用你的安卓应用 sockstun 访问,安卓代码使用 Windows 编译,hev-socks5-tunnel 已经更新到 2.6.5 。
以下是使用的其他 socks5 服务器,
https://github.com/snail007/goproxy
https://github.com/txthinking/socks5
https://github.com/things-go/go-socks5
heiher
133 天前
@cnfzv udp 走 udp 传输的话,客户端要求有访问到服务器端任意 udp 端口的能力。
cnfzv
133 天前
@heiher Windows 防火墙已经关闭,Ubuntu 默认防火墙没有开启。
在你的 hev-socks5-server 上,使用 https://github.com/tabjy/android-vpn-tun2socks 可以访问,但是访问多个网站后域名解析用的 udp 请求好像会有问题,浏览器会提示 DNS_PROBE_FINISHED_NO_INTERNET 。
cnfzv
132 天前
核实了,应该就是 issues 中提到的服务端 TCP 流处理问题,服务端没有处理,没有正常返回请求。但是看了下协议,这种方式好像不符合协议标准吧? https://datatracker.ietf.org/doc/html/rfc1928#autoid-3
实在研究不动了,希望作者能解答
cnfzv
132 天前
😭找到另一个帖子的回复了。 有关 TCP delay 都是系统默认配置,“粘包”效果是因为 socks5 客户端有意实现为预测发送,是有减少延迟作用的。不知道切换前怎样,切换后应该是 dns 经过 socks5 服务器端,不知道是不是因为 dns 的延迟。浏览器的开发者选项中网络传输页面应该可以显示每个资源的加载时间,不妨对比看看,需要注意的是尽可能网络环境的抖动影响,比如本地跑 socks5 服务器,访问本地或国内 http 资源。
这么操作明显和 rfc1928 协议逻辑不一样了,在握手未完成之前就提交了请求,而遵守协议的其他服务端会因为没有在握手后收到请求而无法进行相应。
--另外我找到的 https://github.com/tabjy/android-vpn-tun2socks 好像也有问题,UDP 请求貌似不太对,会导致服务端疯狂监听端口但又不进行连接。
23 年最后一折腾,我好像总会踩坑,唉,心累
heiher
131 天前
@cnfzv 如果将 TCP 视作为流,而不是报文。在客户端对服务端的响应预测无误的情况下,服务端仍不能正确处理流上数据,我觉得这是服务端的实现问题。
specture
131 天前
@heiher 感谢解答。按照类似的方式实现了目标
cnfzv
131 天前
@heiher 但是这种预测和协议的标准不符了吧? 就像去传统的自动售货机买饮料一样,你需要先投币,等机器识别后按按钮饮料才会掉下来,但是你投币和按按钮同时进行购买是没法成功的。你的这种实现等于是做出了一个部分兼容 socks5 的新协议出来了
heiher
131 天前
@cnfzv socks5 协议标准有对这一细节做具体的约束吗?在你的类比味结论是没法成功,而 socks5 协议的消息格式设计其实是可以成功的。比如 hev-socks5-server 、xray 等就是严谨处理流上数据的实现。

我不否则事实上与某些服务端存在兼容问题,之前分析过一个案例,问题实质就是:服务端分配了一块较大的接收缓存区,简单粗暴的读取了这一时刻客户端方向的全部流数据,假定接收缓存区中只有当前阶段的请求消息,而不是按照 socks5 消息格式一段一段处理掉,导致后续片断被丢弃。

因此,我自己目前得出的结论是:不是我设计了个新协议,而是有的服务端实现的不好。:D (除了降低 rtt 以外,合并发送还有消除 socks5 传输特征的考虑
cnfzv
131 天前
@heiher 这个是协议说明 https://datatracker.ietf.org/doc/html/rfc1928 ,根据标准里的说明。
客户端连接到服务器并发送版本 标识符/方法选择消息,服务端是要返回方法选择信息的,在交互完成后可以传输子协商信息的,而在子协商之后才是发送详细请求。Once the method-dependent subnegotiation has completed, the client sends the request details.
而你使用传输方式或者说用了预测发送,但是这种方式,是基于“服务器一定允许连接“的假设而进行的。
诚然,这种方式确实如你所说优化了传输效率,对于实际使用会有不少的提升,但是这种方式并不符合协议的标准。
并不是我非得在这里认死理抬杠,是因为这么个搞法兼容性真的很爆炸,github 找了好几个 go 的 socks 服务没有一个能好用的,使用 openssh 的 sock5 转发也是没法使用的,不是我事多,是这么个搞法兼容性真的很难受😭
heiher
131 天前
@cnfzv 理解。openssh 的 socks5 server 是可以的。ssh -D 1080
cnfzv
131 天前
@heiher 😥你确定吗? ssh -D 0.0.0.0:8000 并不好用,使用你的安卓程序连接的,并不好用。只有 dns 请求过不去

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/917046

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX