Escribir en el flujo de salida de VpnService no responde

Mi aplicación implementa VpnService para interceptar el tráfico de red y proporcionar respuestas personalizadas. El objetivo es manejar el tráfico a direcciones específicas y descartar otras solicitudes.

Actualmente tengo éxito en analizar las solicitudes entrantes y construir y enviar respuestas. El problema, sin embargo, es que estas respuestas no llegan como la respuesta real a la solicitud original; La prueba con una conexión de socket simplemente se apaga.

Para hacer esta distinción, actualmente estoy analizando los paquetes de IP sin procesar del flujo de entrada de VpnService de la siguiente manera:

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 es una clase a través de la cualcreate() analiza la matriz de bytes en una representación del paquete IP, que contiene el encabezado IP, las opciones y el cuerpo. Procedo a analizar la matriz de bytes del cuerpo según el tipo de protocolo. En este caso, solo me interesa IPv4 con una carga de TCP; aquí también creo una representación del encabezado, las opciones y el cuerpo de TCP.

Después de obtener una instancia de IpDatagram, puedo determinar la IP de origen y destino (desde el encabezado de IP) y el puerto (desde el encabezado de TCP). También reconozco los indicadores de solicitud TCP (como SYN, ACK y PSH) y el número de secuencia. En la aplicación:

Posteriormente construyo un nuevo IpDatagram como respuesta, donde:

La IP de origen y de destino se invierte de la solicitud entrante;Los puertos de origen y destino se invierten de la solicitud entrante;El número de confirmación de TCP se establece en el número de secuencia de la solicitud entrante;Se proporciona una carga útil HTTP / 1.1 ficticia como cuerpo del TCP.

Convierto el IpDatagram resultante en una matriz de bytes y lo escribo en el flujo de salida de VpnServer:

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

Mi aplicación muestra el datagrama saliente como debería ser, pero sin embargo, todas las conexiones aún están fuera de tiempo.

Aquí hay un ejemplo de un paquete TCP / IP entrante en hexadecimal:

4500003c7de04000400605f10a0203044faa5a3bb9240050858bc52b00000000a00239089a570000020405b40402080a00bfb8cb0000000001030306

Y el paquete TCP / IP saliente resultante en hexadecimal:

450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421

Sin embargo, una simple prueba simplemente se agota; Creo un nuevo socket y lo conecto a la IP anterior, pero la respuesta proporcionada anteriormente nunca llega.

¿Qué podría salir mal? ¿Hay alguna manera de solucionar por qué mi respuesta no llega?

Respuestas a la pregunta(1)

Su respuesta a la pregunta