CSNet与Android VPN Service的研究

@Ta 01-18 10:06发布,01-18 10:08修改 2538点击
Android VPN Service实测会拦截magisk版本root进程csnet流量和解析。
产生一个问题:vpn -> csnet -> vpn -> csnet产生死循环然后网络错误。
-----------------------------------------------------------------
目前我个人还在研究的可能可行的解决思路:
1. csnet客户端启动的时候绑定网络接口,强制走固定接口,不走vpn的接口。
2. 打一个android.apk隐藏图标的空包,然后使用这个包的uid运行csnet进程。
3. 使用适用于android的防火墙规则,尝试对csnet进程的流量强制直连处理。
-----------------------------------------------------------------
1. 关于ipv6,有段时间服务器是开启了AAAA记录支持ipv6的,后来迁移的服务商不支持ipv6所以去掉解析。
2. 关于udp,现在的版本是csnet v3,v2是实现了udp的,然而并没有什么用,很多软件对socks5的udp支持不好。
回复列表(36)
  • @Ta / 01-18 10:12

    @爱特,添加路由规则的时候不用0.0.0.0/0,产生一个绕过csnet服务器IP的规则就可以了。我的CSNet VPN Service app今天已经基本上完成了,包括排除国内ip等所有功能都可用。

    绕过规则产生代码:

    https://github.com/SwimmingTiger/CSNetDroid/blob/csnet/app/src/main/java/net/typeblog/socks/util/Routes.java#L44

    apk下载:
    https://hu60.cn/q.php/bbs.topic.98170.html

  • @Ta / 01-18 10:14
    @老虎会游泳,csnet本身会通过cidr来判断ip范围,如果ip范围是国内,会直接作为http\https\socks5服务端 直接发起请求。所以仅绕过服务端地址是有问题的,要根据进程实现直连才行。
  • @Ta / 01-18 10:20

    @爱特

    1. china_network_direct = off (csnet.xml#L60)
    2. 把路由表取反(从排除国内变为转发国外),然后在VPN Service创建时添加 (simpleroute.xml)
    3. 如果服务器IP在路由表的某个网段内,生成规则排除 (Routes.java#L35)

    目前运行的非常好。

  • @Ta / 01-18 10:27

    不过我的simpleroute.xml并不是你路由表的取反,因为我没有你的源代码。
    这个simpleroute.xml是从SocksDroid项目继承的,所以有点老,但是大体上是准确的。

  • @Ta / 01-18 10:32
    @老虎会游泳assets.zip(33.86 KB)
    这个是昨晚打包的ip cidr范围,每次打包自动从apnic.net拉取最新ip范围,china包含了香港。
  • @Ta / 01-18 10:34

    @爱特,关于udp,你在服务器上运行一个badvpn-udpgw如何,SocksDroid通过它实现UDP透明代理。

    通过CSNet将UDP数据包转发到badvpn-udpgw。该功能需要远程服务器运行badvpn-udpgw才能生效(监听在127.0.0.1:7300即可)。

    app默认的远程UDP网关是127.0.0.1:7300

  • @Ta / 01-18 10:34
    被锁定
    层主 @爱特 于 2021-01-18 11:00 删除了该楼层。
  • @Ta / 01-18 11:01
    @老虎会游泳,udp windows客户端proxifier4不支持,不太好测试,proxycap对高版本windows10支持又不好。
  • @Ta / 01-18 10:41

    @爱特,badvpn-udpgw应该不是标准的socks5 udp实现,客户端通过代理连接badvpn-udpgw的时候走的还是socks5 TCP,但是该TCP socks会被用于转发UDP数据包。

    所以只需要一个支持socks5 TCP的代理,再加上一个独立的badvpn-udpgw监听在服务器7300端口,就可以用了。

    我不知道这个方案在Windows上怎么用。我只是看到SocksDroid实现了这个东东,所以提一下。

    https://github.com/PeterCxy/SocksDroid#udp-forwarding

    UDP Forwarding
    As tun2socks does not support UDP associate but has its own implementation of UDP forwarding badvpn-udpgw, so it is needed that the udpgw daemon run on remote server to use UDP forwarding.

    On remote server

    badvpn-udpgw --listen-addr 127.0.0.1:7300
    And set UDP Gateway in this app to 127.0.0.1:7300

  • @Ta / 01-18 10:47

    @爱特,有没有什么现成的工具找出一个路由表的互补路由表?我实在不想自己写程序计算啊,感觉好复杂。

    计算排除单个IP的路由表的方法,我也是想了很久才想出来的。

  • @Ta / 01-18 10:49
    @老虎会游泳,给你csnet ci的cidr生成命令,应该足够了,不需要写程序。
    wget -c http://ftp.apnic.net/stats/apnic/delegated-apnic-latest
    cat delegated-apnic-latest | awk -F '|' '/CN/&&/ipv4/ {print $4 "/" 32-log($5)/log(2)}' > china_ipv4_cidr.txt
    cat delegated-apnic-latest | awk -F '|' '/HK/&&/ipv4/ {print $4 "/" 32-log($5)/log(2)}' >> china_ipv4_cidr.txt
    cat delegated-apnic-latest | awk -F '|' '/CN/&&/ipv6/ {printf("%s/%d\n", $4, $5)}' > china_ipv6_cidr.txt
    cat delegated-apnic-latest | awk -F '|' '/HK/&&/ipv6/ {printf("%s/%d\n", $4, $5)}' >> china_ipv6_cidr.txt
  • @Ta / 01-18 10:53

    @爱特,但我要的cidr是所有不属于中国的cidr。这样才能直接添加到安卓vpn路由表。

    如果得到的是所有属于中国的cidr,就必须写一个程序计算它的逆,才能得到可以添加到安卓vpn路由表中的条目。

    我还不知道怎么计算,没有思路。

    所以问题就是:从0.0.0.0/0中减去一系列cidr,把最后剩下的那些导出。怎么做?或者有什么工具做?

  • @Ta / 01-18 10:54
    @老虎会游泳,vpn service不能收到一个请求,拿到ip地址动态判断吗?直接看ip在不在范围内就行了啊。
  • @Ta / 01-18 11:09

    @爱特,是可以,但是这样一来vpnservice就必须自行处理连接,因为连接到达vpnservice的时候它已经没有机会再让其直连了,只能自己代理。而我不想编写TCP通信代码。

    此外这种方法也会增加耗电,本来设好路由规则就能直出的流量还需要经过vpnservice。当然要优雅的实现,然后我自己不写tcp通信代码,其实也可以,但这样的话csnet就需要和vpnservice通信,在想直连的时候把自己创建的套接字发给vpnservice,然后vpnservice调用安卓提供的函数把该套接字设为直连。VpnService.protect(Socket)

    相比之下我还是觉得写个算法计算出路由表更好,因为cidr本来就是静态的,在能用路由实现的情况下没有必要在运行时判断。

  • @Ta / 01-18 11:14
    @老虎会游泳,我现在csnet中就是动态计算的,因为流量全局过来了我必须自己处理请求,我简单测试了下,正常都在1-2毫秒左右计算出结果,对于用户基本是无感知的。用路由表来做这个东西就做不到全平台通用,而且还需要系统级权限,取反的路由表目测挺大的,放系统中性能应该也不会太好。
  • @Ta / 01-18 11:26

    @爱特,但我要实现的是安卓VpnService,并且只是安卓VpnService,所以我不需要考虑跨平台。

    此外我不认为计算出来的路由表会很大,因为 simpleroute.xml 并不大,它只是不够新。

    还有,相比于在应用层匹配cidr+创建新连接+数据收发,在内核匹配一下路由表的开销显然小的多。想想有多少时间浪费在数据收发循环中就知道了,本来只需要收发数据1次,但一代理,就变成了3次。

    而socks代理之所以不能操作路由表,只是因为它是socks代理,它天生就没有这个条件。但我要实现的是Vpn,我当然应该充分利用Vpn的全部功能。而且真的要谈可移植性的话,那么这些功能、方法和思路在其他平台的VpnService中显然也可用,因为路由是VpnService实现的基础,只要是个VpnService编程接口,那肯定可以操作路由的。

  • @Ta / 01-18 11:32
    @老虎会游泳,有道理,取反应该要自己写个工具,找了下网上没有现成的可用。
  • @Ta / 01-18 11:35

    @爱特,嗯,我现在在想算法应该是什么样的。看起来基本上是先给网段排序,然后找空隙,再把空隙用cidr表达出来。

  • @Ta / 01-18 11:39
    试图打断
添加新回复
回复需要登录

[聊天-网站建设_网页设计] a676774305:我现在只能等老虎帮忙下一步了。