安卓平台实现 Tailscale 与代理 APP 共存
1. 背景
国内普遍网络环境问题,导致我们经常需要使用代理软件(如 Clash / Mihomo /v2ray /sing-box 等)进行科学上网。
在 Windows / MacOS 等桌面平台上,Tailscale 可以与代理软件正常共存工作;但是在 Android 平台,由于同时只能同时运行一个 VPN 应用,导致 Tailscale 应用和代理 APP 无法共存,只能同时开启一个,这种限制对于 Tailscale 深度用户来说是极大的不便。
经过一些研究和探索,最终成功按照 Github Issue #410 · tailscale/tailscale 所提出的方案巧妙地实现了 Tailscale 与代理 APP 的共存工作,既保留了两者 APP 的核心能力,又使它们有效地协同进行分流。
效果:
本方案需要你对代理 APP 的配置文件进行修改,为 Tailscale 应用配置分流。
如果你对代理 APP 的配置文件尚不熟悉,请左转这个推荐博客阅读了解:OpenEvonix の Mihomo 原理与配置文件科普
2. 基本思路
安卓原生拥有工作空间
机制,其类似于各家国产 ROM 的 “应用双开”,可以创建一个隔离的用户空间来安装应用。工作空间
的特点在于其拥有一个独立的 VPN 应用槽位,其中运行的 VPN 应用与外界 VPN 应用不会互相冲突,这个特性可以被我们用来实现 Tailscale & 代理共存。
具体方案如下:
- 安装 Insular(炼妖壶)来管理
工作空间
- 将 Tailscale APP 克隆到
工作空间
中,并启动 - 在
工作空间
中安装 Every Proxy 应用,此应用可以对外暴露一个 socks5 端口,将 Tailscale VPN 网络通过 socks5 共享出来 - 在主用户空间中为代理 APP 配置分流:当目标地址为
100.64.0.0/10
,或目标域名为*.ts.net
时,将流量转发到前面的 socks5 端口 - 在代理 APP 中,将需要访问 Tailscale 网络的 APP 加入代理应用白名单
配置完成后,主用户空间中的 APP 就可以访问 Tailscale 网络了,同时也可以正常使用代理软件的服务。
3. 操作流程
3.1. 安装并配置 工作空间
前往 F-Droid 或者 GitLab 安装 Insular(炼妖壶)。安装完成后第一次运行,会要求你配置工作空间
,按流程操作进行配置即可。
安装完毕后,可以看到桌面上出现了 “工作” 文件夹,以及默认自动包含的一些系统应用。
注:三星 OneUI 用户可以直接使用 “安全文件夹” 功能,不需要再额外安装炼妖壶
3.2. 安装 Tailsale 并启用
打开炼妖壶 APP,将 Tailscale APP 克隆进壶中界
,并在工作空间中启动并登录 Tailscale。
如果安装完毕后,炼妖壶 APP 内的应用列表显示为空,请尝试进入 APP 权限设置页面为炼妖壶打开 “读取应用列表” 权限
成功登录后,可以看到 Tailscale 与主用户空间的代理 APP 互不干扰,可以正常共存运行,此时就可以在工作空间
内的所有 APP 中访问 Tailscale 网络了。
注意:此时主用户空间的 APP 还无法访问 Tailscale,为了达到此目的,我们需要进一步配置 EveryProxy 与代理 APP。
3.3. 安装并配置 Every Proxy
在工作空间
中安装 Every Proxy,使用 socks5 导出 Tailscale 服务接口。
Every Proxy 的 Google Play 下载链接
安装完毕后,按如下配置设置 socks5 服务器,并启用它。记得设置好认证使用的用户名 / 密码,防止你的 socks5 服务被滥用
注意:千万不要安装最下面的
Network bridge
组件,在本方案中它是没有必要的,而且会导致连接出现问题
3.3.1. 测试一下效果~
现在,你应该可以使用任意 socks5 客户端连接到这个端口,并通过 socks5 代理访问 Tailscale 网络了。你可以尝试将手机连接到 WiFi,然后在电脑上进行测试。
例如,你在 100.64.0.1
这个设备的 80 端口启动一个 nginx 服务器,然后在电脑上执行如下命令:
curl --socks5 <你的socks5用户名>:<你的socks5密码>@<手机局域网IP>:58888 100.64.0.1:80
curl 命令应该可以正常访问到 nginx 服务器:
3.4. 为代理 APP 配置分流
接下来回到主用户空间,我们的目标是让主用户空间的 APP 也可以用上 Tailscale 网络。
既然前面已经暴露了 Tailscale 服务的 socks5 端口,这里只需要修改代理 APP 的分流配置,将 Tailscale 网段的流量导向此 sock5 端口即可。配置文件的修改思路如下:
- 新增一个 socks5 出站条目,指向 Every Proxy 的 socks5 端口。地址为
127.0.0.1
,端口为58888
,对应设置用户名和密码 - 新增分流规则:当目标地址为
100.64.0.0/10
,或目标域名为*.ts.net
时,通过分流将流量引导到 Every Proxy 的 socks5 端口 - 其他各项配置不变,非 Tailscale 网段正常进行代理 / 直连
以 Mihomo 为例,参考下面的例子修改配置文件:
# ........
proxies:
# 新增指向Every Proxy的socks5出站
- name: "Tailscale-socks5"
type: socks5
server: 127.0.0.1
port: 58888
udp: true
username: <你的socks5用户名>
password: <你的socks5密码>
# ........
rules:
# 在分流规则头部设置Tailscale分流规则
- IP-CIDR,100.64.0.0/10,Tailscale-socks5,no-resolve # 将100.64.0.0/10网段分流到Tailscale socks5接口
- DOMAIN-SUFFIX,ts.net,Tailscale-socks5,no-resolve # 将 *.ts.net 域名分流到Tailscale socks5接口
# ........
另外,记得一定要把需要访问 Tailscale 网络的应用加到代理 APP 的应用白名单中~
设置完成后,重启代理 APP,你在主用户空间的应用就可以成功访问 Tailscale 网络了。
4. 一些注意点
4.1. 电池优化 & 自启动
考虑到部分国产 ROM 对自启动和后台程序运行限制十分严格,因此建议对工作空间中 Tailscale APP 和 Every Proxy 设置禁用电池优化并开启自启动权限,以避免 APP 在后台运行时间过长被杀。
另外,如果要使用 Tailscale 网络,也必须保证代理 APP 一直处于运行状态。因为我们需要依赖代理 APP 将主用户空间 100.64.0.0/10
网段的流量分流到工作空间的 Tailscale APP 中。
4.2. Taildrop 相关问题
由于工作空间
和主用户空间的储存空间是隔离开的,因此使用 Taildrop 文件投送时可能会遇到一些小麻烦。这里给出解决方案:
4.2.1. 发送文件
在主用户空间发送文件时,需要把文件通过工作空间
的 Tailscale 发送出去。
这其实也很简单,在主用户空间正常分享文件→选择 “切换到工作空间”→选择工作空间的 Tailscale APP→发送,整个流程相比原来只要多点一步 “切换”。
4.2.2. 接收文件
Tailscale 1.84 版本开始支持使用安卓 SAF 框架选择 Taildrop 接收文件的保存位置,这让我们可以直接选择将接收文件保存到主用户分区内的 Download 目录,保持和原来完全一样的体验。
设置方法:点击右上角账户按钮→Permissions→Taildrop directory access→Pick a different directory→进入 SAF 选择界面,切换到 “个人”,进入 Download 目录并点击 “使用此文件夹”,确认即可。
5. 其他方案
除了本文提到的这个方案以外,还有一些其他方案同样可以实现 Tailscale 与代理 APP 共存。当然他们多多少少都存在一些问题,这里仅做一下记录:
5.1. 使用另一个运行代理服务的设备作为 Tailscale 网络的 exit-node
非常烂的思路:
- 需要额外有一个设备永远在线,负责作为 exit-node 并运行代理软件
- 本机所有需走代理和走 Tailscale 网络的请求与响应全部通过 exit-node 中转,这会造成严重的延迟问题
- 在 NAT 环境下如果无法打洞成功,则网速还会严重受限于 Derper 服务器带宽
强烈不建议使用此方案
5.2. 使用 tailscale-magisk 模块
如果你的设备已经 root,可以使用 Magisk-Tailscaled 模块来实现在安卓设备上运行 linux 版 tailscale。安装模块后,直接在有 root 权限的终端执行 tailscale 命令使用即可。关于虚拟组网互联的所有必要功能都是可以正常工作的。
缺点:由于项目尚未针对安卓平台进行 tailscaled 的交叉编译,因此只能以 userspace 模式工作,而且存在一些 BUG,比如 MagicDNS 不支持等,还有一些重要功能比如 Taildrop 等也无法使用,较为遗憾。
5.3. 代理 APP 使用 box4magisk 模块,Tailscale 仍使用 APP
相反,可以尝试将代理改为使用模块运行 mihomo/sing-box 二进制程序,Tailscale 仍然使用 APP。这样既保留了 Tailscale APP 的全部功能,又使代理软件可以正常发挥效果。
缺点:本方案经过作者长时间研究,一直没有成功运行。问题的根源是 Mihomo 的 TUN 接口对安卓 VPN 存在一些兼容性问题,而且 fake-ip 的加入会产生更多毛病。限于作者精力有限,没有进一步进行研究。
5.4. Tailscale APP userspace-networking 模式
在 GitHub Issue #10126 中,我们提出可以让 Tailscale APP 支持和桌面端一样的 userspace-networking
模式,即不启用 TUN 接口和 Android VPN Service,仅在本地监听 socks5 和 http 代理端口来提供服务。
这样,我们就不再需要工作空间
和 Every Proxy,只要直接在手机上启动一个 userspace-networking
模式的 Tailscale APP,然后用代理 APP 配置分流,将流量导向它监听的端口即可。
这个方案应该是最终极、最优雅的解决方案,只可惜相关功能还尚未实现。
作者会持续跟踪 Issue 进展,并在功能完成以后第一时间更新本文。敬请期待!
6. Q&A
6.1. 会导致耗电增加吗?
答:确实会产生一些额外的耗电,特别是当应用频繁使用 Tailscale 网络时。
不过由于我们使用代理 APP 进行了妥善的分流,因此只有访问 Tailscale 网络的请求才会被 Tailscale APP 接收并处理,这样最大程度避免了不必要的流量处理与耗电。
7. 致谢
Android app doesn’t seem to play nicely with other VPN apps. · Issue #410 · tailscale/tailscale