Das Schreiben in den VpnService-Ausgabestream liefert keine Antwort

Meine Anwendung implementiert VpnService, um den Netzwerkverkehr abzufangen und maßgeschneiderte Antworten bereitzustellen. Ziel ist es, den Datenverkehr an bestimmte Adressen zu verarbeiten und andere Anforderungen zu verwerfen.

Derzeit bin ich erfolgreich darin, eingehende Anfragen zu analysieren und Antworten zu erstellen und zu senden. Das Problem ist jedoch, dass diese Antworten nicht als tatsächliche Antwort auf die ursprüngliche Anforderung eingehen. teste mit einer buchsenverbindung einfach mal aus.

Um diese Unterscheidung zu treffen, analysiere ich derzeit die rohen IP-Pakete aus dem Eingabestream des VpnService wie folgt:

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 ist eine Klasse, durch diecreate() Analysiert das Byte-Array in eine Darstellung des IP-Pakets, die den IP-Header, die Optionen und den Hauptteil enthält. Ich fahre fort, das Byte-Array des Körpers gemäß dem Protokolltyp zu analysieren. In diesem Fall interessiert mich nur IPv4 mit einer TCP-Nutzlast - auch hier erstelle ich eine Darstellung des TCP-Headers, der Optionen und des Hauptteils.

Nachdem ich eine Instanz von IpDatagram erhalten habe, kann ich die Quell- und Ziel-IP (aus dem IP-Header) und den Port (aus dem TCP-Header) ermitteln. Ich bestätige auch die Anforderungs-TCP-Flags (wie SYN, ACK und PSH) und die Sequenznummer. In der App:

Anschließend konstruiere ich ein neues IpDatagram als Antwort, wobei:

Die Quell- und Ziel-IP werden von der eingehenden Anforderung umgekehrt.Der Quell- und der Zielport sind gegenüber der eingehenden Anforderung umgekehrt.Die TCP-Bestätigungsnummer wird auf die Sequenznummer der eingehenden Anforderung gesetzt.Als TCP-Body wird eine Dummy-HTTP / 1.1-Payload bereitgestellt.

Ich konvertiere das resultierende IpDatagram in ein Byte-Array und schreibe es in den Ausgabestream des VpnServers:

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

Meine Anwendung zeigt das ausgehende Datagramm so an, wie es sein sollte, aber trotzdem laufen alle Verbindungen nach wie vor aus.

Hier ist ein Beispiel für ein eingehendes TCP / IP-Paket in hexadezimaler Schreibweise:

4500003c7de04000400605f10a0203044faa5a3bb9240050858bc52b000000a00239089a570000020405b40402080a00bfb8cb000000000001030306

Und das resultierende ausgehende TCP / IP-Paket in hexadezimaler Schreibweise:

450000bb30394000800613194faa5a3b0a0203040050b92400a00000858bc52b501820001fab0000485454502f312e3120323030204f4b0a446174653a205475652c203139204e6f7620323031332031323a32333a303320474d540a436f6e74656e742d547970653a20746578742f68746d6c0a436f6e74656e742d4c656e6774683a2031320a457870697265733a205475652c203139204e6f7620323031332031323a32333a303320474d540a0a48656c6c6f20776f726c6421

Bei einem einfachen Test tritt jedoch einfach eine Zeitüberschreitung auf. Ich erstelle einen neuen Socket und verbinde ihn mit der obigen IP, aber die oben angegebene Antwort kommt nie an.

Was könnte schief gehen? Gibt es eine Möglichkeit zur Fehlerbehebung, warum meine Antwort nicht eingeht?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage