title: Android VpnService Packet Sniffing
body: <p>I'm working on a school project and have hit a road block and wanted to see if anyone can help point me in the right direction. We are trying to capture packets from an Android phone without rooting the phone. The only option that I have found was to use Android's VPNService to use it as a middle man to capture the packets. 
  The idea that I had was to create a button to capture the packets, on a onclick event.</p>
  
  <pre><code>package cybutech.com.datacapture;
  
  import android.app.ActionBar;
  import android.content.Intent;
  import android.graphics.Color;
  import android.net.VpnService;
  import android.preference.PreferenceFragment;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.support.v7.widget.Toolbar;
  import android.view.Menu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.View;
  import android.widget.Button;
  import android.widget.Toast;
  
  public class MainActivity extends AppCompatActivity {
      private int capture = 1;
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
          setSupportActionBar(myToolbar);
  
          final Button captureData = (Button)findViewById(R.id.capture);
          captureData.setOnClickListener(new View.OnClickListener() {
              public void onClick(View v) {
                  if (capture == 1) {
                      captureData.setBackgroundColor(Color.RED);
                      captureData.setText("Stop Capture!");
                      Intent intent = VpnService.prepare(getApplicationContext());
                      if (intent != null) {
                          startActivityForResult(intent, 0);
                      } else {
                          onActivityResult(0, RESULT_OK, null);
                      }
                      capture *= -1;
                  } else {
                      captureData.setBackgroundColor(Color.GREEN);
                      captureData.setText("Start!");
                      capture *= -1;
                  }
  
              }
          });
      }
  
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
          if (resultCode == RESULT_OK) {
              Intent intent = new Intent(this, MyVpnService.class);
              startService(intent);
          }
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.action, menu);
          return true;
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          switch (item.getItemId()) {
              case R.id.action_settings:
                  startActivity(new Intent(this, Settings.class));
  
                  break;
              default:
                  break;
          }
  
          return true;
      }
  
  }
  
  
      package cybutech.com.datacapture;
  
      import android.content.Intent;
      import android.net.VpnService;
      import android.os.ParcelFileDescriptor;
      import android.support.v7.app.AppCompatActivity;
      import android.os.Bundle;
  
      import java.io.BufferedReader;
      import java.io.FileInputStream;
      import java.io.FileOutputStream;
      import java.io.InputStreamReader;
      import java.net.InetSocketAddress;
      import java.nio.channels.DatagramChannel;
  
      public class MyVpnService extends VpnService {
  
          private Thread mThread;
          private ParcelFileDescriptor mInterface;
          //a. Configure a builder for the interface.
          Builder builder = new Builder();
  
          // Services interface
          @Override
          public int onStartCommand(Intent intent, int flags, int startId) {
              // Start a new session by creating a new thread.
              mThread = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          //a. Configure the TUN and get the interface.
                          mInterface = builder.setSession("MyVPNService")
                                  .addAddress("192.168.0.1", 24)
                                  .addDnsServer("8.8.8.8")
                                  .addRoute("0.0.0.0", 0).establish();
                          //b. Packets to be sent are queued in this input stream.
                          FileInputStream in = new FileInputStream(
                                  mInterface.getFileDescriptor());
                          //b. Packets received need to be written to this output stream.
                          FileOutputStream out = new FileOutputStream(
                                  mInterface.getFileDescriptor());
                          //c. The UDP channel can be used to pass/get ip package to/from server
                          DatagramChannel tunnel = DatagramChannel.open();
                          // Connect to the server, localhost is used for demonstration only.
                          tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
                          //d. Protect this socket, so package send by it will not be feedback to the vpn service.
                          protect(tunnel.socket());
                          //e. Use a loop to pass packets.
                          while (true) {
                              BufferedReader reader  = new BufferedReader(new InputStreamReader(in));
                              while(true) {
                                  String line = reader.readLine();
                                  if (line == null) {
                                      System.out.print("NULLLLLLL");
                                      break;
                                  } else {
                                      System.out.println("line is " + line);
                                  }
                                  // I am guessing that here after reading the packets, I need to forward them to the actual server.
  
                                  Thread.sleep(100);
                              }
                          }
  
                      } catch (Exception e) {
                          // Catch any exception
                          e.printStackTrace();
                      } finally {
                          try {
                              if (mInterface != null) {
                                  mInterface.close();
                                  mInterface = null;
                              }
                          } catch (Exception e) {
  
                          }
                      }
                  }
  
              }, "MyVpnRunnable");
  
              //start the service
              mThread.start();
              return START_STICKY;
          }
  
          @Override
          public void onDestroy() {
              // TODO Auto-generated method stub
              if (mThread != null) {
                  mThread.interrupt();
              }
              super.onDestroy();
          }
      }
  </code></pre>