Tyc*_*aco 5 java sockets android tcp packet-capture
我想使用 androidVpnService来捕获数据包并根据 IP 地址过滤它们。我可以很好地从“tun”接口获取数据包,但之后我不确定如何将它们转发到原始目的地。根据这个答案的评论,我似乎只需要:
我尝试像这样发送数据:
Socket socket = new Socket();
socket.bind(new InetSocketAddress(0));
if (protect(socket)){
Log.e(TAG, "Socket protected");
}else{
Log.e(TAG, "Socket NOT protected");
}
socket.connect(new InetSocketAddress(ipPacket.getDestinationIp(), ipPacket.getDstPort()));
Log.e(TAG, "Socket connected: " + socket.isConnected());
socket.getOutputStream().write(getTCPHeader(getIpHeader(packet)[1])[1].array());
Run Code Online (Sandbox Code Playgroud)
getTCPHeader(ByteArray packet)这些方法getIpHeader(ByteArray packet)简单地将数据包分成两个,ByteArray如下所示:
private ByteBuffer[] getIpHeader(ByteBuffer packet){
packet.position(0);
ByteBuffer ipHeader = ByteBuffer.allocate(20);
ByteBuffer data = ByteBuffer.allocate(packet.limit() - 20);
packet.get(ipHeader.array(), 0, 20);
packet.get(data.array(), 0, packet.limit() - 20);
return new ByteBuffer[]{ipHeader, data};
}
private ByteBuffer[] getTCPHeader(ByteBuffer packet){
packet.position(20);
ByteBuffer tcpHeader = ByteBuffer.allocate(20);
ByteBuffer data = ByteBuffer.allocate(packet.limit() - 20);
packet.get(tcpHeader.array(), 0, 20);
packet.get(data.array(), 0, packet.limit() - 40);
return new ByteBuffer[]{tcpHeader, data};
}
Run Code Online (Sandbox Code Playgroud)
现在为了从服务器获取响应,我使用以下代码:
ByteBuffer responsePacket = ByteBuffer.allocate(65535);
InputStream socketInputStream = socket.getInputStream();
try{
int responseLength = socketInputStream.read(responsePacket.array());
if (responseLength > 20){
Log.e(TAG, "===Server Response===");
Log.e(TAG, "Length: " + responseLength);
ByteBuffer trimmedResponseData = ByteBuffer.allocate(responseLength);
System.arraycopy(responseData.array(), 0, trimmedResponseData.array(), 0, responseLength);
String resp = "";
for (int i = 0; i < responseLength; i++){
resp += String.valueOf(responseData.get(i) + " ");
}
Log.e(TAG, "Response data: " + resp);
ByteBuffer finalPacket = ByteBuffer.allocate(40 + responseLength);
ByteBuffer swappedIpHeader = swapSrcDstAddress(getIpHeader(packet)[0]);
ByteBuffer swappedTcpHeader = swapTCPSrcDst(getTCPHeader(getIpHeader(packet)[1])[0]);
finalPacket.put(swappedIpHeader.array());
finalPacket.put(swappedTcpHeader.array());
finalPacket.put(serverResponseData.array());
Packet finPack = debugPacket(finalPacket);
Log.e("VPN", "Final packet --> Packet size: " + finPack.getTotalLength() + " from " + finPack.getSourceIp() + " src port: " + finPack.getSrcPort() + " going to " + finPack.getDestinationIp() + " dst port: " + finPack.getDstPort());
out.write(finalPacket.array());
}
}catch (Exception e){
//Log.e(TAG, "EXCEPTION: " + e);
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
这段代码似乎运行得非常慢,或者根本不运行。有时,如果我访问www.google.com它,加载速度会很慢,但大多数时候不会。有时我也会收到以下错误int responseLength = socketInputStream.read(serverResponse.array());
java.net.SocketException:recvfrom失败:ECONNRESET(连接由对等方重置)
是什么导致了此错误,我如何正确地将这些数据包转发到适当的目的地?任何帮助是极大的赞赏!
是什么导致了这个错误?
recvfrom failed异常意味着服务器已关闭客户端套接字,但客户端仍在读取输入数据(在您的情况下)serverResponse.array()。有关详细信息,请参阅此。
我怎样才能正确地将这些数据包转发到适当的目的地?
这里有一个来自 google-sources 的示例代码,用于转发可用的数据包。请仔细阅读代码和相关注释。根据谷歌消息来源:
该应用程序由 Android 客户端和服务器的示例实现组成。它执行 IP over UDP,只要接收到相同的 VPN 参数,就能够在不同网络之间进行无缝切换。它展示了如何使用 API 级别 14 中引入的 VpnService 类构建 VPN 客户端。
服务器端实现的示例代码是特定于 Linux 的,可以在
server目录中找到。要运行服务器或将其移植到另一个平台,请参阅代码中的注释以了解详细信息。
这里还有一个有用的应用程序链接
| 归档时间: |
|
| 查看次数: |
3097 次 |
| 最近记录: |