A gravação no fluxo de saída do VpnService não fornece resposta

Meu aplicativo implementa o VpnService para interceptar o tráfego de rede e fornecer respostas personalizadas. O objetivo é manipular o tráfego para endereços específicos e descartar outras solicitações.

Atualmente sou bem sucedido em analisar solicitações recebidas e construir e enviar respostas. O problema, no entanto, é que essas respostas não chegam como a resposta real à solicitação original; Testar com uma conexão de soquete simplesmente expira.

Para fazer essa distinção, estou atualmente analisando os pacotes IP brutos do fluxo de entrada do VpnService da seguinte maneira:

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 é uma classe através da qualcreate() analisa a matriz de bytes em uma representação do pacote IP, contendo o cabeçalho IP, opções e corpo. Eu prossigo para analisar a matriz de bytes do corpo de acordo com o tipo de protocolo. Nesse caso, estou interessado apenas no IPv4 com uma carga útil TCP - aqui também crio uma representação do cabeçalho TCP, das opções e do corpo.

Depois de obter uma instância do IpDatagram, posso determinar o IP de origem e de destino (do cabeçalho IP) e a porta (do cabeçalho TCP). Eu também reconheço as bandeiras TCP do pedido (como SYN, ACK e PSH) e o número de sequência. No aplicativo:

Posteriormente construo um novo IpDatagram como resposta, onde:

O IP de origem e destino são revertidos da solicitação recebida;As portas de origem e destino são invertidas a partir do pedido recebido;O número de confirmação do TCP é configurado para o número de sequência da solicitação de entrada;Uma carga HTTP / 1.1 fictícia é fornecida como o corpo do TCP.

Eu converto o IpDatagram resultante em uma matriz de bytes e escrevo no fluxo de saída do VpnServer:

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

Meu aplicativo exibe o datagrama de saída como deveria ser, mas, no entanto, todas as conexões ainda estão expirando.

Aqui está um exemplo de pacote TCP / IP recebido em hexadecimal:

4500003c7de04000400605f10a0203044faa5a3bb9240050858bc52b00000000a00239089a570000020405b40402080a00bfb8cb0000000001030306

E o pacote TCP / IP de saída resultante em hexadecimal:

450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421

No entanto, um teste simples simplesmente expira; Eu criei uma nova tomada e conectei-a ao IP acima, mas a resposta fornecida acima nunca chega.

O que poderia dar errado? Existe alguma maneira de solucionar o motivo pelo qual minha resposta não está chegando?

questionAnswers(1)

yourAnswerToTheQuestion