8

我正在尝试通过 VPN 将数据包从 VPN 发送到适当的硬件上,而无需使用任何真正的 VPN 服务器,因此我可以记录正在发送的数据包。

我能够获得一个我希望数据包实际到达InetAddresswlan0接口,但我不太确定这是否是正确的位置(它显示了我当前的 IP 地址)。

然后我在其上使用DatagramChannel(称为socketIntetAddressis uplink):

socket.connect(new InetSocketAddress(uplink, 0));

并向其写入数据包:

socket.write(packet);

但没有什么坚持,我只是得到

java.net.SocketException: sendto failed: EINVAL (Invalid argument)
4

3 回答 3

15

我正在尝试在为 Android 创建防火墙/过滤应用程序时做类似的事情。我在这中间,所以用适当大小的盐粒来接受我所说的话。:-)

您/我的情况的问题是您正在从 VpnService 提供给您的虚拟网络接口中取出数据包,但随后您正在取出这些数据包并使用套接字将它们写出。套接字旨在处理客户端和服务器之间的应用程序有效负载的传输,而不是数据包。

套接字将获取您提供的任何数据,并将该数据包装在它自己创建的数据包中(如果使用 Socket,则为 TCP,如果使用 DatagramSocket,则为 UDP)。在您的情况下,您正在处理套接字的数据本身就是一个数据包,因此您最终会得到一个数据包中的数据包(可能是 UDP 数据包中的 TCP 数据包)。

当打包的数据包到达服务器的套接字时,该端的网络接口和 ServerSocket 将打开有效负载并发现它是另一个数据包。可能不会工作,因为从服务器端套接字(例如 Web 服务器)读取的任何内容都需要应用程序有效负载(例如 HTTP 标头/等)。

现在,当您拥有一个真正的 VPN 隧道时,该隧道的服务器端可能会将您的“包装数据包”有效负载从它接收的 UDP 数据包中提取出来,然后将该数据包直接交给可以解释数据包本身的网络接口.

如果没有这个真正的 VPN 隧道,您的 VpnService 实现本质上必须成为一个虚拟网络接口本身,处理 TCP/UDP/等。虚拟网络接口和您的代码之间的协议。基本上,从您的 VPN 接口读取的数据包必须被视为应用程序数据流(数据包整理和重组),然后再写入您的传出套接字。然后,您必须以某种方式确认您刚刚从接口消耗的数据包。然后,您必须从您的 Socket(这是一个有效负载数据流)中获取传入数据,并将其分解为数据包,然后您可以将这些数据包发送回您的 VPN 接口的输出流。最后,您需要处理您的虚拟 VPN 接口为响应您发送的数据包而发送的确认流量。这并非易事。

我真的希望我对这一切都错了,有人有一个用 Java 编写的简单的“虚拟网络接口”,可以用来代替真正的 VPN 隧道。我一直没能找到它。

于 2013-03-15T19:04:21.583 回答
1

您可以使用NetworkInterface API以编程方式获取 wlan0 地址。

我也在尝试做类似的事情..我能够在虚拟接口上看到数据包..但我无法通过本地接口发送数据包..

我可以使用 DatagramChannel 连接到 wlan0,但是从 wlan0 到外部服务器的连接卡在 SYN_SEND 上。

于 2013-01-28T20:43:56.297 回答
0

你可以试试更高的端口。这对我有用: InetSocketAddress(uplink, 3022)

我不知道如何确保该端口未被使用。

你是怎么得到wlan0的地址的?我使用了 adb shell ifconfig 并粘贴了地址。

于 2012-09-17T20:48:17.957 回答