gpt4 book ai didi

android - 写入 VpnService 输出流没有响应

转载 作者:可可西里 更新时间:2023-11-01 02:32:28 25 4
gpt4 key购买 nike

我的应用程序实现 VpnService 来拦截网络流量并提供定制的响应。目标是处理到特定地址的流量,并丢弃其他请求。

目前,我已成功解析传入请求以及构建和发送响应。然而,问题是这些响应并不是作为对原始请求的实际响应到达的;使用套接字连接进行测试会超时。

为了做出这种区分,我目前正在解析来自 VpnService 输入流的原始 IP 数据包,如下所示:

VpnService.Builder b = new VpnService.Builder();
b.addAddress("10.2.3.4", 28);
b.addRoute("0.0.0.0", 0);
b.setMtu(1500);
...
ParcelFileDescriptor vpnInterface = b.establish();
final FileInputStream in = new FileInputStream(
vpnInterface.getFileDescriptor());
final FileOutputStream out = new FileOutputStream(
vpnInterface.getFileDescriptor());

// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);

// We keep forwarding packets till something goes wrong.
try {
while (vpnInterface != null && vpnInterface.getFileDescriptor() != null
&& vpnInterface.getFileDescriptor().valid()) {
packet.clear();
SystemClock.sleep(10);
// Read the outgoing packet from the input stream.
final byte[] data = packet.array();
int length = in.read(data);
if (length > 0) {
packet.limit(length);
/*
1. Parse the TCP/UDP header
2. Create an own socket with the same src/dest port/ip
3. Use protect() on this socket so it not routed over tun0
4. Send the packet body (excluding the header)
5. Obtain the response
6. Add the TCP header to the response and forward it
*/
final IpDatagram ip = IpDatagram.create(packet);
...
}
}

IpDatagram 是一个类,create() 通过该类将字节数组解析为 IP 数据包的表示形式,其中包含 IP header 、选项和主体。我继续根据协议(protocol)类型解析正文的字节数组。在这种情况下,我只对具有 TCP 有效负载的 IPv4 感兴趣——我在这里也创建了 TCP header 、选项和正文的表示。

在获得 IpDatagram 实例后,我可以确定源 IP 和目标 IP(来自 IP header )和端口(来自 TCP header )。我还确认请求的 TCP 标志(如 SYN、ACK 和 PSH)和序列号。在应用程序中:

Parsing incoming TCP/IP packet

随后我构造一个新的 IpDatagram 作为响应,其中:

  • 源和目标 IP 与传入请求相反;
  • 源端口和目标端口与传入请求相反;
  • TCP 确认号设置为传入请求的序列号;
  • 提供一个虚拟的 HTTP/1.1 负载作为 TCP 的主体。

我将生成的 IpDatagram 转换为字节数组并将其写入 VpnServer 的输出流:

TcpDatagram tcp = new TcpDatagram(tcpHeader, tcpOptions, tcpBody);
IpDatagram ip = new Ip4Datagram(ipHeader, ipOptions, tcp);
out.write(ip.toBytes());

我的应用程序按应有的方式显示传出数据报,但是所有连接仍然超时。

TCP/IP response

这是一个十六进制的传入 TCP/IP 数据包示例:

4500003c7de04000400605f10a0203044faa5a3bb9240050858bc52b00000000a00239089a570000020405b40402080a00bfb8cb0000000001030306

以及生成的十六进制传出 TCP/IP 数据包:

450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421

但是,一个简单的测试就会超时;我创建了一个新套接字并将其连接到上面的 IP,但上面提供的响应从未到达。

可能出了什么问题?有什么方法可以排查我的回复未送达的原因吗?

最佳答案

此 TCP/IP 响应不包含有效的 TCP header 校验和:

450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421

更一般地说,请求和响应机制是非常挑剔的。由于网络的本质,这当然是这种情况,并且由于内核负责确保响应良好以及应该将响应发送到哪个端口,任何不计算的东西都会被简单地丢弃为坏数据包.当您在网络层上操作时,从 VpnService 的输出流响应时也是如此。

回到上面的具体情况:IP 数据包正确(包括校验和)但 TCP 数据包不正确。您不仅需要计算 TCP 数据包的 TCP header 校验和,还需要以伪 header 为前缀,如下所示:

TCP pseudo-header
(来源:tcpipguide.com)

然后应该根据以下字节计算它:

TCP header checksum

关于android - 写入 VpnService 输出流没有响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20269283/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com