VpnService 能否原样将三层的 IP 报文发出去?

2019-08-05 17:28:27 +08:00
 gam2046

需要开发一款流量统计的软件( Android ),于是乎就想到了 VpnService,天然适合。

但是呢,由于 VpnService 收到的是三层的 IP 报文,而我本身没有对于数据修改的需求,只是想简单的记录。

参考了一下部分开源软件的实现,各种代理类软件(比如 SS ),都是将收到的三层报文解析后,发向远程端。 当然这类软件需要修改数据内容。

而我现在不需要修改任何数据,只想单纯的统计发向每个服务端的数据量、时间等,并不关心数据内容。

由于 RawSocket 肯定没法用,设备不存在 root。Java 似乎本身也未提供能够工作在三层的网络通讯方式。

那么是否有什么尽可能简单的方法(或大佬的轮子),可以把三层报文转换成四层,发出去后,再返还给应用的方法?

这里还有一个疑问,由于 Java 中没有找到直接操作三层网络协议的方法,对于非 TCP/UDP 报文(例如 ICMP/IGMP 等),又如何实现直接出口呢?

14876 次点击
所在节点    Android
25 条回复
CrazyBoyFeng
2021-03-24 19:07:02 +08:00
至于为什么 tun2socks 使用用户态协议栈 lwip,那是因为它把包发给 socks 服务器了,而不是传输修改了 header 的 tcp 和 udp 。jvm 上并不能修改包头并重新发送。如果能直接发的话,题目的要求(转发)将变得十分简单。
所以 jvm 要转发只有俩实现方案:
1. 本地起个 socks 服务器,tun2socks 转给 socks 服务器。socks 往外的连接要传给 android protect() 一下。
2. nat 实现。各自缓存一套 tcp 和 udp 的 natsession map 。收到来自 lan 的包,检查一下有没有 session,有的话直接取出来往 wan 传送 data 。没有的话建立一个 protect() wan 连接并存入 session map 。tcp 要处理握手和挥手,收到 lan 握手包建立外部连接,lan 挥手包关闭连接清除 session,如果是 wan 关闭连接则向 lan 发送挥手包。wan udp 连接设置个 timeout,超时自动关闭,关闭时清除 session 。
9ttttttt
2021-04-08 14:24:16 +08:00
@CrazyBoyFeng 请问 Android 上面只能发 TCP 和 UDP 包么?那如果我实现一个基于 VPNService 的 Android VPN 应用,是不是除了 TCP 和 UDP 包的其他数据包会被截断呢?想问一下可以对 IP 包里面有没有可以自定义的标志位或信息字段呢,我想基于 IP 包里面自定义的标志位或信息字段来在 Android 上实现是否向 VPN 发数据的判断,类似于 PAC 那种想法。谢谢大佬!
CrazyBoyFeng
2021-04-23 01:49:02 +08:00
@9ttttttt java 层无法建立除 tcp 和 udp 以外的通信。VPNService 可以收到 icmp 包,以字节数组的形式,但是无法在不 root 的情况下发出去,只能丢弃。
你的第二个问题,大概是想实现类似 iptables 这类的东西? iptables 打标记的原理并不是修改数据包,而是建立数据表。而 java 层也不能改包,所以就不能发送自定义内容的数据包。
jeesk
2022-12-21 23:08:39 +08:00
问题解决了吗? 这个恐怕需要创建一张网卡来操作?
lysShub
234 天前
四年了,请问解决了吗?

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

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

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

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

© 2021 V2EX