web-dev-qa-db-fra.com

Android VpnService pour capturer les paquets ne capturera pas les paquets

Je cherche ma réponse depuis quelques heures maintenant et je ne peux pas le comprendre. Veuillez aider.

Ce que je veux faire, c'est utiliser le VpnService dans Android pour récupérer des paquets réseau comme l'application tPacketCapture

J'ai commencé par utiliser l'exemple de code ToyVpn de Google et à le modifier afin de ne pas envoyer les données à un serveur. Cependant, je ne suis pas sûr que ce soit correct.

Ma méthode de configuration utilise l'adresse IP WLAN pour binder.addAddress () avant d'appeler Establ (). J'utilise un nexus 7 et j'ai utilisé "adb Shell netcfg | grep wlan0" pour obtenir l'adresse:

wlan0 UP 192.168.0.6/24 0x00001043 10: bf: 48: bf: 5f: 9d

Et ajoutez-le dans ma méthode:

    private void configure() throws Exception {
    // If the old interface has exactly the same parameters, use it!
    if (mInterface != null) {
        Log.i(TAG, "Using the previous interface");
        return;
    }

    // Configure a builder while parsing the parameters.
    Builder builder = new Builder();
    builder.setMtu(1500);
    builder.addAddress("192.168.0.6", 24);

    try {
        mInterface.close();
    } catch (Exception e) {
        // ignore
    }

    mInterface = builder.establish();
}

Après avoir appelé cela, j'appelle la méthode run que j'ai modifiée pour passer une chaîne au lieu d'un InetSocketAddress et ce n'est pas important car je ne l'utilise nulle part:

    private void run(String run) throws Exception {
    configure();

    FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

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

    // We use a timer to determine the status of the tunnel. It
    // works on both sides. A positive value means sending, and
    // any other means receiving. We start with receiving.
    int timer = 0;

    // We keep forwarding packets till something goes wrong.
    while (true) {
        // Assume that we did not make any progress in this iteration.
        boolean idle = true;

        // Read the outgoing packet from the input stream.
        int length = in.read(packet.array());
        if (length > 0) {

            Log.i(TAG,"************new packet");
            while (packet.hasRemaining()) {
                Log.i(TAG,""+packet.get());
                //System.out.print((char) packet.get());
            }

            // Write the outgoing packet to the tunnel.
            packet.limit(length);
            //  tunnel.write(packet);
            packet.clear();

            // There might be more outgoing packets.
            idle = false;

            // If we were receiving, switch to sending.
            if (timer < 1) {
                timer = 1;
            }
        }
    }
}

Quand je fais adb logcat, rien ne se passe. Suis-je en train de faire ça correctement? J'ai l'impression de manquer quelque chose.

Je vous remercie!

ÉDITER:

Dans les journaux, je vois les lignes suivantes:

I/ActivityManager(  460): START u0 {act=Android.intent.action.MAIN cat=[Android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.Android.toyvpn/.ToyVpnClient} from pid 10247
I/ActivityManager(  460): Start proc com.example.Android.toyvpn for activity com.example.Android.toyvpn/.ToyVpnClient: pid=10287 uid=10122 gids={50122, 3003, 1028}
I/ActivityManager(  460): Displayed com.example.Android.toyvpn/.ToyVpnClient: +1s144ms
I/Vpn     (  460): Switched from [Legacy VPN] to com.example.Android.toyvpn
D/Vpn     (  460): setting state=IDLE, reason=prepare
I/ToyVpnService(10287): running vpnService
D/Vpn     (  460): setting state=CONNECTING, reason=establish
D/VpnJni  (  460): Address added on tun0: 192.168.0.6/24
I/Vpn     (  460): Established by com.example.Android.toyvpn.ToyVpnService on tun0
W/ContextImpl(  460): Calling a method in the system process without a qualified user: Android.app.ContextImpl.bindService:1406 com.Android.server.connectivity.Vpn.establish:289 com.Android.server.ConnectivityService.establishVpn:3263 Android.net.IConnectivityManager$Stub.onTransact:504 Android.os.Binder.execTransact:351 
D/Vpn     (  460): setting state=AUTHENTICATING, reason=establish

Il semble donc se connecter.

Source complète:

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

    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, "ToyVpnThread");
        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, message.what, Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    @Override
    public synchronized void run() {
        Log.i(TAG,"running vpnService");
        try {
            runVpnConnection();
        } catch (Exception e) {
            e.printStackTrace();
            //Log.e(TAG, "Got " + e.toString());
        } finally {
            try {
                mInterface.close();
            } catch (Exception e) {
                // ignore
            }
            mInterface = null;

            mHandler.sendEmptyMessage(R.string.disconnected);
            Log.i(TAG, "Exiting");
        }
    }

    private boolean runVpnConnection() throws Exception {

        configure();

        FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

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

        // We keep forwarding packets till something goes wrong.
        while (true) {
            // Assume that we did not make any progress in this iteration.
            boolean idle = true;

            // Read the outgoing packet from the input stream.
            int length = in.read(packet.array());
            if (length > 0) {

                Log.i(TAG,"************new packet");
                System.exit(-1);
                while (packet.hasRemaining()) {
                    Log.i(TAG,""+packet.get());
                    //System.out.print((char) packet.get());
                }
                packet.limit(length);
                //  tunnel.write(packet);
                packet.clear();

                // There might be more outgoing packets.
                idle = false;
            }
            Thread.sleep(50);
        }
    }

    public String getLocalIpAddress()
    {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    Log.i(TAG,"****** INET ADDRESS ******");
                    Log.i(TAG,"address: "+inetAddress.getHostAddress());
                    Log.i(TAG,"hostname: "+inetAddress.getHostName());
                    Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
                    if (!inetAddress.isLoopbackAddress()) {
                        //IPAddresses.setText(inetAddress.getHostAddress().toString());
                        Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
                        return inetAddress.getHostAddress().toString();
                    } else{
                        Log.i(TAG,"It is a loopback address");
                    }
                }
            }
        } catch (SocketException ex) {
            String LOG_TAG = null;
            Log.e(LOG_TAG, ex.toString());
        }

        return null;
    }

    private void configure() throws Exception {
        // If the old interface has exactly the same parameters, use it!
        if (mInterface != null) {
            Log.i(TAG, "Using the previous interface");
            return;
        }

        // Configure a builder while parsing the parameters.
        Builder builder = new Builder();
        builder.setMtu(1500);
        builder.addAddress("192.168.0.6", 24);
        try {
            mInterface.close();
        } catch (Exception e) {
            // ignore
        }

        mInterface = builder.establish();
    }
}
32
Juan Acevedo

Ok, ce n'était pas facile du tout mais j'ai compris comment capturer des paquets. Comme je ne suis pas très familier avec le réseautage (mais ce nouveau travail demande que je le sois), j'ai eu du mal à tout configurer correctement. Fondamentalement, après avoir défini la bonne route dans le VpnService.builder, j'ai pu recevoir correctement les paquets.

Alors:

builder.addAddress("192.168.0.6", 24); // was wrong, you need to put an internal IP (10.0.2.0 for example)

et

builder.addRoute("0.0.0.0", 0); // needs to be this.

vous n'avez pas besoin de configurer un DnsServer via builder.addDnsServer () pour le faire fonctionner. J'espère que cela aide n'importe qui!

24
Juan Acevedo

Ma méthode configure utilise l'adresse IP WLAN pour binder.addAddress () avant d'appeler Establ (). J'utilise un Nexus 7 et j'ai utilisé "adb Shell netcfg | grep> wlan0" pour obtenir l'adresse:

wlan0 UP 192.168.0.6/24 0x00001043 10: bf: 48: bf: 5f: 9d

J'ai écrit un script simple en python pour vous montrer graphiquement netcfg depuis adb. Il se met à jour toutes les secondes.

enter image description herehttps://github.com/ilanben/graphical_netcfg

Prendre plaisir :)

4
Ilan.b