V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gam2046
V2EX  ›  Android

是否有可能 Zerotier-One 直接在 Android 设备上运行?

  •  
  •   gam2046 · 2022-06-30 10:43:02 +08:00 · 10343 次点击
    这是一个创建于 862 天前的主题,其中的信息可能已经有所发展或是发生改变。

    准备

    • 获取Zerotier-One代码,并 checkout 到 1.8.9 。
    • 配置 arm 交叉编译环境并采用静态编译
      • 这里并未采用 NDK 主要是因为一直不成功
      • 所以才使用静态编译的方法,应用直接通到 syscall
    • 将编译后的程序丢到 Android 设备上,通过 root 用户运行( Android 10)
    • zerotier-cli join <ID>,加入网络
    • zerotier 可以正常打开 /dev/tun ,并且正常创建了虚拟网卡,且正确配置 IP 与路由
      • 通过ip adip route可正确显示相关信息
    • zerotier 运行无输出

    问题

    虽然看起来组网成功,并且 zerotier controller 也显示设备已连接,并正确显示版本等信息,但实际上网络访问并不通。

    通过分析(实际就是加输出日志),确认 zerotier正常进入此循环,同时也未发现 zerotier 对系统有其他额外要求,只需要存在 tun 设备即可。


    猜测

    那目前看起来比较有可能的原因,是 Android 中对 tun 的行为有所不同。常规 Android 开发中,只有 VpnService 会经由一系列检查以及用户授权后,打开 tun 设备,变更路由表,并将句柄返回给应用层。

    由此猜测可能是 Android 对 tun 有一些魔改,但是我翻阅了一下(更多的可能是水平不够),AOSP 里没看到一些可疑的操作。

    所以请问一下大佬,在有 root 的情况下,有没有可能直接在 Android 设备上使用 zerotier ,而不需要装个 APP 呢?( APP 有些设置在 UI 中也没有)

    28 条回复    2023-11-18 23:30:22 +08:00
    gam2046
        1
    gam2046  
    OP
       2022-06-30 11:16:17 +08:00
    通过 AOSP 中一些代码的对比,并未看到 AOSP 中有什么不一样的操作。几乎与 zerotier 的代码一致。

    https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/jni/com_android_server_connectivity_Vpn.cpp;l=59;drc=912b26d95c411a41126393b7d341a18f04981342

    看了下,设备中的 /dev/tun 所有者是 system:vpn ,我使用 root 去 open 原则上也是没有问题的。对 /dev/tun 的读写就直接进内核了,原与 Android 中的上层应用都无关(就是 framework 那一大堆)。

    唯一的区别是,AOSP 将设备初始化为 IFF_TUN ,而 zerotier 中设置为 IFF_TAP 。但既然 ioctl 没返回失败,就应该是没问题。

    实在找不出原因了,大佬们救救孩子吧。
    neptuno
        2
    neptuno  
       2022-06-30 11:42:20 +08:00
    超纲了,,想问一下,你这样做,好处是什么呢? zerotier 不是有安卓客户端吗
    yaott2020
        3
    yaott2020  
       2022-06-30 12:31:27 +08:00 via Android
    @neptuno 可能是因为官方安卓客户端不支持 moon 。第三方客户端支持( zerotierfix )
    gam2046
        4
    gam2046  
    OP
       2022-06-30 13:11:37 +08:00
    @neptuno @yaott2020 #2 #3 一些个性化配置是一方面,另一方是具体使用设备上,并不是手机,而是定制设备,因此需要能够实现 CLI 。

    至于 zerotierfix ,也有关注到,其依旧通过 VpnService 实现,因此要转换成 CLI 工具比较困难,app_process 并不能提供较为完整的 Android 上下文环境,但依旧可以作为备选方案,毕竟各种 context 与 service 都是代理对象。

    ---
    再补充一些信息,通过打开调试信息后,可以得到一些 zerotier 的日志

    ```
    requesting configuration for network <NETWORK_ID>
    learned new path 47.254.39.171/9993 to 451e1bcd2d (packet 83c94f7455245fc1 local socket 24751240 network 0000000000000000)
    learned new path 47.254.39.171/9993 to 451e1bcd2d (packet 27f78687dc532c4c local socket 24752072 network 0000000000000000)
    learned new path 47.254.39.171/9993 to 451e1bcd2d (packet 3aace22563cf24c1 local socket 24761048 network 0000000000000000)
    learned new path 84.17.53.155/9993 to cafe04eba9 (packet 6206803e3b771efa local socket 24751240 network 0000000000000000)
    learned new path 50.7.252.138/9993 to 62f865ae71 (packet 62067fb9b5119d9a local socket 24752072 network 0000000000000000)
    learned new path 104.194.8.134/9993 to cafe9efeb9 (packet 62965da8502523c5 local socket 24751240 network 0000000000000000)
    trying unknown path 104.194.8.134/9993 to cafe9efeb9 (packet 62965da85025b36f verb 5 local socket 24761048 network 0000000000000000)
    requesting configuration for network <NETWORK_ID>
    learned new path 103.195.103.66/9993 to 778cde7190 (packet 624f26cab7985461 local socket 24761048 network 0000000000000000)
    trying unknown path 122.233.117.194/30356 to f4b7f79a0a (packet 5fd54282b47ffaab verb 8 local socket 24761048 network 0000000000000000)
    trying unknown path 122.233.117.194/30356 to f4b7f79a0a (packet 9350ccb5c20f1429 verb 8 local socket 24751240 network 0000000000000000)
    trying unknown path 122.233.117.194/30356 to f4b7f79a0a (packet b7cb5f1fc6e0c571 verb 8 local socket 24752072 network 0000000000000000)
    learned new path 84.17.53.155/9993 to cafe04eba9 (packet 6206803e3bb32355 local socket 24752072 network 0000000000000000)
    trying unknown path 104.194.8.134/9993 to cafe9efeb9 (packet 62965da85094d197 verb 5 local socket 24761048 network 0000000000000000)
    trying unknown path 104.194.8.134/9993 to cafe9efeb9 (packet 62965da850bbe285 verb 5 local socket 24761048 network 0000000000000000)
    trying unknown path 122.233.117.194/30356 to f4b7f79a0a (packet 2592f42b345e677b verb 8 local socket 24761048 network 0000000000000000)
    trying unknown path 122.233.117.194/30356 to f4b7f79a0a (packet c3430f29f87d3b50 verb 8 local socket 24751240 network 0000000000000000)
    ```

    有考虑过,是否为网络原因导致实际访问路径不通,但是在相同网络环境下,一台 Windows 主机可以快速的接入网络并访问,因此无法怀疑是网络问题。

    同时附上编译参数:
    make \
    ZT_STATIC=1 \
    ZT_DEBUG=1 \
    CC=arm-none-linux-gnueabihf-gcc \
    CXX=arm-none-linux-gnueabihf-g++ \
    CFLAGS="-Wall -O3" \
    CXXFLAGS="-Wall -O3" \
    LDFLAGS="-s" \
    $*
    ZiShuo
        5
    ZiShuo  
       2022-06-30 13:47:13 +08:00
    关注一下,前几个月也有楼主这个需求,自己倒腾了好久也没搞成。当然我纯小白,连交叉编译怎么搞都不会的那种,最后在安卓下面安装了个 optware 变相实现了这个需求。

    PS:很想楼主写个搭建 Arm 交叉编译的教程,然后一起折腾。
    gam2046
        6
    gam2046  
    OP
       2022-06-30 15:20:54 +08:00
    @ZiShuo #5 简单的编译环境并不困难,特别是借助 docker 以后。如果想玩,这里给你一个 arm 的参考样例,可以新建一个 dockerfile ,写入以下内容

    https://gist.github.com/Lua12138/940ba02c809a1f28416e10b0cfc9cfa9

    然后 docker build -t builder:arm . 构建镜像即可。编译的时候,参考命令:

    docker run --rm -it \
    -v $PWD/ZeroTierOne/:/code \ # <- 挂载进去代码,根据你的实际位置修改
    -w /code \
    builder:arm \
    make \ # <- 这里就是写各种编译参数了
    ZT_STATIC=1 \
    ZT_DEBUG=1 \
    CC=arm-none-linux-gnueabihf-gcc \
    CXX=arm-none-linux-gnueabihf-g++ \
    LDFLAGS="-s" \
    datocp
        7
    datocp  
       2022-07-01 05:17:40 +08:00 via Android
    神器可试试 gscript lite 或者 juicessh 。
    如果你对这软件从设置到路由都非常熟悉的话,其它可能就是被 iptables 挡了。android 10/12 用 android 该除的都除了,至少用的一个 sslsocks,stunnel 的 gui 实现正常 。

    iptables -F
    iptables -X
    iptables -t nat -F
    iptables -t nat -X
    #iptables -t mangle -F
    #iptables -t mangle -X
    iptables -t raw -F
    iptables -t raw -X
    iptables -t security -F
    iptables -t security -X
    # Apply and allow now your rules from here ...
    iptables -P INPUT ACCEPT
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -F fw_dozable
    iptables -X fw_dozable
    ZiShuo
        8
    ZiShuo  
       2022-07-01 09:34:32 +08:00
    @gam2046 感谢大佬,我现在就去搭建环境再倒腾下,我是想把 zerotier 扔到 4G 随身 wifi 里面使用。
    gam2046
        9
    gam2046  
    OP
       2022-07-01 10:11:58 +08:00
    @datocp #7 唔,还不一样。sslsocks 、stunnel 都是 7 层协议。而 zerotier 使用 tun/tap ,它需要的是二层。经过一些排查基本确定就是少了一步类似 VpnService.protect 的步骤。


    @ZiShuo #8 如果系统也是 Android 的话,还是优先考虑 zerotier one 自己的客户端吧。如果是 openwrt 或者其他 Linux 设备,可以直接用我编译好的程序(如果也是 arm 架构,其他架构官网上也有下载不用你自己编译)。
    ZiShuo
        10
    ZiShuo  
       2022-07-01 12:36:06 +08:00
    @gam2046 谢谢,主要是我要替换 zerotier 里面的根,换成自己的根,默认的根在境外我这有时候连不上,系统是安卓,处理器是骁龙 410 的,貌似是 Arm64 架构的,淘宝 20 多买的那种 4G 随身 wifi
    sbilly
        11
    sbilly  
       2022-07-03 22:38:24 +08:00
    @ZiShuo 你的随身 4G 是 Android 系统?
    ZiShuo
        12
    ZiShuo  
       2022-07-13 14:56:57 +08:00
    @sbilly 是的
    jeesk
        13
    jeesk  
       2022-12-21 22:57:19 +08:00
    zerotierfix 在 github 上面有入轨的版本。
    huazhaozhe
        14
    huazhaozhe  
       2023-04-14 01:39:12 +08:00
    楼主有什么解决方法了没,我在 Android 上通过 chroot 部署了 ubuntu22 arm64 ,然后在里边用官方的方法安装了 zerotier-one ,加入网络 OK ,也有虚拟网卡,一开始成功了,后边配了新的网络又不行了,感觉也是和 tun 以及 Android 网络这方面有关,不是特别懂就懵了😂
    huazhaozhe
        15
    huazhaozhe  
       2023-04-14 01:42:19 +08:00
    另外有个方法是内核支持 docker 的话,直接装个 docker 把 tun 挂进去就行了,手机内核需要重新编译可能不一定能支持 docker
    gam2046
        16
    gam2046  
    OP
       2023-04-14 10:13:40 +08:00
    @huazhaozhe #14 即使把 docker 移植到 Android 上也不是一件容易的事情。要移植许多工具链,肉眼可见的坑就是 libc 的差异以及 iptables
    huazhaozhe
        17
    huazhaozhe  
       2023-04-15 09:00:11 +08:00
    @gam2046 #16 这个倒是有的,我在 k40 上就是用的 docker 跑 zerotier-one ,编译内核开启几个选项就可以了
    gam2046
        19
    gam2046  
    OP
       2023-04-15 09:38:09 +08:00
    @huazhaozhe #16 这可不是一个玩意,你这个依托于 Termux ,并不能独立部署。我以前尝试过,把这类工具从 Termux 里摘出来,合并到 Android 主线上。

    但是没成功,需要我魔改的地方太多了。

    如果你用这个是可以用的话,那么应该问题不在 tun/tap 上,Termux 本身并没有魔法。

    那么我之前的问题可能是出在了本地路由表上,等我有空了,再回去看看。
    gam2046
        20
    gam2046  
    OP
       2023-10-27 14:17:23 +08:00
    @ZiShuo
    @datocp
    @huazhaozhe

    目前该问题已经解决,与 Zerotier 并无太大关系,经过大佬指点,主要问题出在 Android 使用 RPDB ( routing policy database )来决定应用程序的 IP 数据包路由,它不依赖于传统的主路由表(也就是 main ,table id 254 ),有自己的路由策略。

    因此解决方案也非常简单,只需要根据自己的实际情况,修改 RPDB 即可。
    newuser666
        21
    newuser666  
       2023-11-01 13:47:09 +08:00
    @gam2046 大佬大佬,可以给点 RPDB 样例吗,我在 github 上看你的回答说修改了一些代码,方便教一下怎么做到吗😅
    gam2046
        22
    gam2046  
    OP
       2023-11-01 19:29:28 +08:00
    @newuser666 #20 ,大概的意思就是这样,归根到底,其实就是因为没有走主路由表。

    https://gist.github.com/Lua12138/77252e88857f34432e297bfcde7adc74
    newuser666
        23
    newuser666  
       2023-11-01 22:28:29 +08:00
    @gam2046 打扰了大佬,小白一个,看不懂 C 代码😂,我表达的不清楚,我看了 git 上的回复,我需要的是这个命令的正确用法 `ip route add table $your_selected_table_id $cide/$prefix dev $zt_iface_name proto kernel scope link`,我看了那位大佬给的文档和你写的回复,但是还是不太清楚应该怎么写。我试着替换了命令中的变量为自己的网段、掩码和接口名,your_selected_table_id 写了个 252 ,但是并没有用处,希望大佬能给个正确的样例。
    另外不知道什么原因我用你的 dockerfile 编译了一个 1.12.1 版本,可以执行`zerotier-one -d $homepath` 但是无法执行 `zerotier-one -q $homepath`,也就是 cli 命令执行报错`./zerotier-cli: missing port and zerotier-one.port not found in /var/lib/zerotier-one`,读取的 home 路径并不是我指定的路径,只能通过 http 请求的形式加入网络,这个是我编译的代码问题吗。
    newuser666
        24
    newuser666  
       2023-11-06 17:53:51 +08:00
    #23 cli 报错从提案中找到了答案,有个隐藏选项文档没写,需要加上 `-Dhomepath`也就是`zerotier-one -q -D$homepath`,但是默认路由依然没生效
    gam2046
        25
    gam2046  
    OP
       2023-11-06 20:54:24 +08:00
    @newuser666 #22 原则上是关系不大的,只要不是 254 理论上都可以,试试看 table id 255 ,或者从 1 开始试试。

    作为 cli 使用如果你不使用软连接的话,根据 ZT 的代码( https://github.com/zerotier/ZeroTierOne/blob/1bd2fecbf6a0419740b33ce95ff6ec4ce33ebd88/one.cpp#L132 ),你需要这样手动指定工作目录,例如:

    ./zerotier-one -D$homepath -q info

    当然你也可以在编译时,直接修改其默认的工作目录

    https://github.com/zerotier/ZeroTierOne/blob/1bd2fecbf6a0419740b33ce95ff6ec4ce33ebd88/osdep/OSUtils.cpp#L447
    newuser666
        26
    newuser666  
       2023-11-08 16:37:50 +08:00
    @gam2046 #25 感谢大佬的回复,您给的方案有效,这几天逛 github 的时候发现个简单粗暴的方法,`ip rule add from all lookup main pref 1`,使用后连自定义路由都不需要添加了🤣🤣,不过暂时还不清楚提升 main 表优先级有没有弊端。
    ynkcc
        27
    ynkcc  
       356 天前 via Android
    安装楼主的方法,成功在部署了 zerotier 。结果有几台设备连不上默认的根节点。不打算折腾 moon 节点和自建 planet 。准备去试一下 tailscale 能不能编译在 Android 使用
    ynkcc
        28
    ynkcc  
       355 天前 via Android
    算了,还是自建 planet 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2716 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 14:32 · PVG 22:32 · LAX 06:32 · JFK 09:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.