Android Firewall mit VpnService

Ich versuche zu implementieren, die eine einfache firewall für android-mit VpnService für das BS-Projekt. Ich wähle VpnService, weil es das arbeiten auf nicht-gerooteten Geräten. Es werden verbindungen protokollieren und lassen Sie filter-Verbindung. (Basierend auf IP)

Es ist eine Anwendung, dies zu tun, so dass es möglich ist.

Google play app store

Ich Tat etwas Forschung und fand, dass VpnService schafft eine Tun-Schnittstelle. Nichts mehr. (Keine VPN-Implementierung nur ein tunnel), die Es Ihnen ermöglicht, eine Adresse zu dieser Schnittstelle und Routen hinzufügen. Es gibt einen file-Deskriptor. Lesen Sie ausgehende Pakete und schreiben Sie die eingehenden Pakete.

Erstellte ich eine VpnService-Klasse abgeleitete Klasse und ich begann service. Ich kann konfigurieren tun0 mit VpnService.Builder-Klasse. Wenn ich mir mobiwol's Verbindung mit adb shell netcfg es schafft eine tun0 Schnittstelle mit 10.2.3.4/32 Adresse. Es leitet alle Pakete, die zu diesem privaten Netzwerk und senden an internet. Ich versuche das gleiche. Erstellt eine Schnittstelle mit 10.0.0.2/32 Adresse. Hinzugefügt eine route mit addRoute Funktion. 0.0.0.0/0 also ich kann erfassen alle Pakete von allen Netzwerk-soweit ich das verstanden habe. (Ich bin ziemlich neu in diesem Thema und immer noch lernen. Ich fand Stücke über das internet, also bin ich nicht wirklich sicher. Korrigiert mich wenn ich falsch Liege.)

Erstellte ich 2 threads im service. Man liest von Datei-Deskriptor und schreibt es auf 127.0.0.1 mit geschützter Buchse. ( Ich bin nicht wirklich sicher, ob ich sollte Lesen/schreiben auf 127.0.0.1. Vielleicht ist das das problem. )

Habe ich analysiert Pakete, die ich Lesen aus Datei-Deskriptor. Zum Beispiel:

01000101    byte:69     //ipv4 20byte header
00000000    byte:0      //TOS
00000000    byte:0      //Total Length
00111100    byte:60     //Total Length
11111100    byte:-4     //ID
11011011    byte:-37    //ID
01000000    byte:64     //fragment
00000000    byte:0      //"
01000000    byte:64     //TTL
00000110    byte:6      //Protocol 6 -> TCP
01011110    byte:94     //Header checksum
11001111    byte:-49    //Header checksum
00001010    byte:10     //10.0.0.2
00000000    byte:0
00000000    byte:0
00000010    byte:2
10101101    byte:-83    //173.194.39.78 //google
00111110    byte:-62
00100111    byte:39
********    byte:78

10110100    byte:-76    //IP option
01100101    byte:101
00000001    byte:1
10111011    byte:-69
                //20byte IP haeder
01101101    byte:109
.       .       //40byte data (i couldnt parse TCP header, 
                    I think its not needed when I route this in IP layer)
.       .
.       .
00000110    byte:6

Ich nicht finden, alle anderen IP-header in den rest der Daten. Ich denke, es sollte eine Kapselung zwischen 10.0.0.2 Netzwerk zum lokalen Netzwerk (192.168.2.1) und internet. Ich bin mir nicht sicher.

Mein eigentliches problem ist, dass ich fest auf die eingehenden Pakete-thread. Ich kann nicht alles Lesen. Keine Antwort. Wie man sehen kann im screenshot keine eingehenden Daten:

Abbildung

Ich versuche zu Lesen, aus der gleichen Verbindung, die ich für das schreiben auf 127.0.0.1 mit geschützter Buchse.

Android <-> Tun-Interface (tun0) <-> Internet-Verbindung

Alle Pakete <-> 10.0.0.2 <-> 127.0.0.1? <-> 192.168.2.1 <-> Internet?

Konnte ich nicht finden, alles, was hilfreich über VpnService. (ToyVPN Beispiel ist einfach nutzlos) ich lese die Dokumente über Linux Tun/Tap aber seine über Tunnelbau zwischen host und remote. Ich will host und remote, auf demselben Gerät. Nicht wie tunneling.

Wie kann ich dies tun?

Edit: Code angefordert. Es ist in einem sehr frühen Stadium. Wie ich bereits erwähnt, ist es ein VpnService-Klasse abgeleitete Klasse. 2 threads (Lesen und schreiben) erstellt, im service-thread.

package com.git.firewall;

public class GITVpnService extends VpnService implements Handler.Callback, Runnable {
    private static final String TAG = "GITVpnService";

    private String mServerAddress = "127.0.0.1";
    private int mServerPort = 55555;
    private PendingIntent mConfigureIntent;

    private Handler mHandler;
    private Thread mThread;

    private ParcelFileDescriptor mInterface;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //The handler is only used to show messages.
        if (mHandler == null) {
            mHandler = new Handler(this);
        }

        //Stop the previous session by interrupting the thread.
        if (mThread != null) {
            mThread.interrupt();
        }
        //Start a new session by creating a new thread.
        mThread = new Thread(this, "VpnThread");
        mThread.start();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        if (mThread != null) {
            mThread.interrupt();
        }
    }

    @Override
    public boolean handleMessage(Message message) {
        if (message != null) {
            Toast.makeText(this, (String)message.obj, Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    @Override
    public synchronized void run() {
        try {
            Log.i(TAG, "Starting");
            InetSocketAddress server = new InetSocketAddress(
                    mServerAddress, mServerPort);

            run(server);

              } catch (Exception e) {
            Log.e(TAG, "Got " + e.toString());
            try {
                mInterface.close();
            } catch (Exception e2) {
                //ignore
            }
            Message msgObj = mHandler.obtainMessage();
            msgObj.obj = "Disconnected";
            mHandler.sendMessage(msgObj);

        } finally {

        }
    }

    DatagramChannel mTunnel = null;


    private boolean run(InetSocketAddress server) throws Exception {
        boolean connected = false;

        android.os.Debug.waitForDebugger();

        //Create a DatagramChannel as the VPN tunnel.
        mTunnel = DatagramChannel.open();

        //Protect the tunnel before connecting to avoid loopback.
        if (!protect(mTunnel.socket())) {
            throw new IllegalStateException("Cannot protect the tunnel");
        }

        //Connect to the server.
        mTunnel.connect(server);

        //For simplicity, we use the same thread for both reading and
        //writing. Here we put the tunnel into non-blocking mode.
        mTunnel.configureBlocking(false);

        //Authenticate and configure the virtual network interface.
        handshake();

        //Now we are connected. Set the flag and show the message.
        connected = true;
        Message msgObj = mHandler.obtainMessage();
        msgObj.obj = "Connected";
        mHandler.sendMessage(msgObj);

        new Thread ()
        {
            public void run ()
                {
                    //Packets to be sent are queued in this input stream.
                    FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
                    //Allocate the buffer for a single packet.
                    ByteBuffer packet = ByteBuffer.allocate(32767);
                    int length;
                    try
                    {
                        while (true)
                        {
                            while ((length = in.read(packet.array())) > 0) {
                                    //Write the outgoing packet to the tunnel.
                                    packet.limit(length);
                                    debugPacket(packet);    //Packet size, Protocol, source, destination
                                    mTunnel.write(packet);
                                    packet.clear();

                                }
                            }
                    }
                    catch (IOException e)
                    {
                            e.printStackTrace();
                    }

            }
        }.start();

        new Thread ()
        {

            public void run ()
            {
                    DatagramChannel tunnel = mTunnel;
                    //Allocate the buffer for a single packet.
                    ByteBuffer packet = ByteBuffer.allocate(8096);
                    //Packets received need to be written to this output stream.
                    FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());

                    while (true)
                    {
                        try
                        {
                            //Read the incoming packet from the tunnel.
                            int length;
                            while ((length = tunnel.read(packet)) > 0)
                            {
                                    //Write the incoming packet to the output stream.
                                out.write(packet.array(), 0, length);

                                packet.clear();

                            }
                        }
                        catch (IOException ioe)
                        {
                                ioe.printStackTrace();
                        }
                    }
            }
        }.start();

        return connected;
    }

    private void handshake() throws Exception {

        if (mInterface == null)
        {
            Builder builder = new Builder();

            builder.setMtu(1500);
            builder.addAddress("10.0.0.2",32);
            builder.addRoute("0.0.0.0", 0);
            //builder.addRoute("192.168.2.0",24);
            //builder.addDnsServer("8.8.8.8");

            //Close the old interface since the parameters have been changed.
            try {
                mInterface.close();
            } catch (Exception e) {
                //ignore
            }


            //Create a new interface using the builder and save the parameters.
            mInterface = builder.setSession("GIT VPN")
                    .setConfigureIntent(mConfigureIntent)
                    .establish();
        }
    }

    private void debugPacket(ByteBuffer packet)
    {
        /*
        for(int i = 0; i < length; ++i)
        {
            byte buffer = packet.get();

            Log.d(TAG, "byte:"+buffer);
        }*/



        int buffer = packet.get();
        int version;
        int headerlength;
        version = buffer >> 4;
        headerlength = buffer & 0x0F;
        headerlength *= 4;
        Log.d(TAG, "IP Version:"+version);
        Log.d(TAG, "Header Length:"+headerlength);

        String status = "";
        status += "Header Length:"+headerlength;

        buffer = packet.get();      //DSCP + EN
        buffer = packet.getChar();  //Total Length

        Log.d(TAG, "Total Length:"+buffer);

        buffer = packet.getChar();  //Identification
        buffer = packet.getChar();  //Flags + Fragment Offset
        buffer = packet.get();      //Time to Live
        buffer = packet.get();      //Protocol

        Log.d(TAG, "Protocol:"+buffer);

        status += "  Protocol:"+buffer;

        buffer = packet.getChar();  //Header checksum

        String sourceIP  = "";
        buffer = packet.get();  //Source IP 1st Octet
        sourceIP += buffer;
        sourceIP += ".";

        buffer = packet.get();  //Source IP 2nd Octet
        sourceIP += buffer;
        sourceIP += ".";

        buffer = packet.get();  //Source IP 3rd Octet
        sourceIP += buffer;
        sourceIP += ".";

        buffer = packet.get();  //Source IP 4th Octet
        sourceIP += buffer;

        Log.d(TAG, "Source IP:"+sourceIP);

        status += "   Source IP:"+sourceIP;

        String destIP  = "";
        buffer = packet.get();  //Destination IP 1st Octet
        destIP += buffer;
        destIP += ".";

        buffer = packet.get();  //Destination IP 2nd Octet
        destIP += buffer;
        destIP += ".";

        buffer = packet.get();  //Destination IP 3rd Octet
        destIP += buffer;
        destIP += ".";

        buffer = packet.get();  //Destination IP 4th Octet
        destIP += buffer;

        Log.d(TAG, "Destination IP:"+destIP);

        status += "   Destination IP:"+destIP;
        /*
        msgObj = mHandler.obtainMessage();
        msgObj.obj = status;
        mHandler.sendMessage(msgObj);
        */

        //Log.d(TAG, "version:"+packet.getInt());
        //Log.d(TAG, "version:"+packet.getInt());
        //Log.d(TAG, "version:"+packet.getInt());

    }

}

InformationsquelleAutor der Frage fatihdurmus | 2013-11-27

Schreibe einen Kommentar