能否使用VpnService实现捕获和发送数据包?

12

我正在考虑使用新的Android (4.0) VpnService接口来实现简单的数据包捕获和分析。有人知道在VpnService实现中是否可以将收到的数据包直接写入活动/默认网络设备吗?当然,要接收数据,我也必须能够从网络设备读取数据。如果可以的话,可以使用哪些API来写入网络设备?


你在这方面有什么进展了吗? - brianestey
@brianestey - 我自己无法使用VpnService实现这一点,但是在谷歌市场上有一个应用程序(https://play.google.com/store/apps/details?id=jp.co.taosoftware.android.packetcapture)似乎正在使用这种技术。我仍然不知道如何在捕获VpnService实现后将数据包写入网络,但也许这个应用程序的作者已经解决了这个问题。 - Mike Ellery
是的,我看到了那个应用程序,想知道他们是如何做到的。你有没有看过Google在API示例中提供的ToyVpnService示例?他们提供了一个VpnServer的代码,以及Android VpnService应用程序的代码。我目前正在尝试弄清楚是否可以将该代码用于设备本身来转发数据包(即,Android应用程序连接到本地运行的VPN服务器,只需代理数据包来回传递)。 - brianestey
此应用程序的功能是:https://play.google.com/store/apps/details?id=jp.co.taosoftware.android.packetcapture - rupello
请参考此示例:http://www.thegeekstuff.com/2014/06/android-vpn-service/ - Gorio
2个回答

8

tPacketCapture创建第二个套接字连接到远程计算机以转发数据包。我使用adb shell netstat查看了tPacketCapture

Proto Recv-Q Send-Q Local Address              Foreign Address            State 
tcp        0      0 192.168.1.126:49828        97.74.42.79:80             ESTABLISHED
tcp6       0      0 ::ffff:127.0.0.1:5000      :::*                       LISTEN
tcp6       0    522 ::ffff:10.8.0.1:50294      ::ffff:97.74.42.79:80      ESTABLISHED
tcp6       0      0 ::ffff:192.168.1.126:34210 ::ffff:74.125.141.188:5228 ESTABLISHED
tcp6       0      1 ::ffff:192.168.1.126:43379 ::ffff:74.125.224.174:80   CLOSE_WAIT
tcp6       0      1 ::ffff:192.168.1.126:60217 ::ffff:74.125.239.14:443   CLOSE_WAIT

注意 97.74.42.79:80 出现了两次。

除非有更好的办法,否则我也得这样做。


1
我目前正在努力让它正常工作。经过仔细检查,创建隧道的是VpnService,而不是编写tPacketCapture的人。 - Juan Acevedo

6
我使用过VPN API。您可以在其中指定路由的tun设备上工作。但是,阅读后,您需要自己处理数据包。通常,这意味着将它们交给VPN服务器。Android SDK提供了一个简单的ToyVPNServer示例。
但是实现类似于pcap的接口很难(甚至可能不可能)而不实现VPN。
可以解析TCP / UDP头并创建具有相同src / dest端口/ IP的自己的套接字,在此套接字上使用protect()以便它不会路由到tun0。由于tPacketCapture仅支持udp / tcp而不支持icmp,因此他们可能会使用此方法。

确实,tPacketCapture使用VpnService工作。出于好奇,我尝试重新创建其功能,但我卡在如何处理生成的文件描述符上。我从VpnService.Builder.establish()获取一个ParcelFileDescriptor并将其包装在FileInputStream中。读取流只会不断产生字节69('E')。我正在努力找出如何正确地与文件描述符进行交互,但迄今为止没有成功。 - Paul Lammertsma
我不完全确定Java的作用。但在C世界中,您只需执行read()/write()调用并每次获取/写入一个数据包即可。 - plaisthos
我用C语言编写了一些代码,但它只简单地给我返回字符'E'。我将VPN接口的getFD()提供给JNI函数。简而言之,C代码所做的是:char buf[1024]; while (long n = read(fd, buf, 1024)) { LOGV("readFd: %s", buf); }; - Paul Lammertsma
2
LOGV 将在第一个零字节处停止。对于 IPv4,如果 TOS 为 0(这很可能是),那么你会在那里有一个 0x0 字节。 - plaisthos
1
我知道这是一个旧答案,但对于任何遇到标题解析问题的新手,您可以在此处查看我的解决方案-https://stackoverflow.com/a/51876540/984830 - Nick Cardoso
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接