Hi All,
so here's my scenario. I'm trying to run a VPN on an android device so I can route all my traffic through it before it leaves the device. The goal is the ability to drop/allow traffic as needed with a switch or button press. I'm attempting to use the vpnService API from Google. I understand the builder to set the source IP address to a lan address that starts with 192.0.0.0 or 10.0.0.0 etc., and set the route to 0.0.0.0/0 so all traffic is routed through the TUN interface created by the VPN. I do not need to set a dns address since I will not be connecting to an external server. The problem I'm having is that I'm unsure where to go from here. From what I read, I need to run the server AND the client locally so I can control the flow of packets. I do not want to connect with an external server in any way. I also read something that perhaps I need to use the localhost address: 127.0.0.1 as the address for a server (tunnel) since the connection will remain local. Below is my work in progress code based on the example toyVpn code available from Google.

Currently, I cannot get to the internet when the route is set. If I disable the route it works fine, but that means the traffic is not going through the TUN interface.

Below is the code used to build the client. I'm not sure how I should if at all build a local version of a server to send the packets out.

Any help would be greatly appreciated.

NOTE: I did find a thread on stackoverflow that demonstrated having a client and server running on the same device. Those test methods are commented out below. Unfortunately, it only uses a string and bouncing back to the client as a demo.

Java Code:
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.toyvpn;

import android.app.Activity;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class ToyVpnService extends VpnService {
    private static final String TAG = "ToyVpnService";

    private String mServerAddress;
    private String mServerPort;
    private byte[] mSharedSecret;
    private PendingIntent mConfigureIntent;

    private Handler mHandler;
    private Thread mThread;

    private ParcelFileDescriptor mInterface;
    private String mParameters;
    private Button testWhile;

    public boolean whileFlag = true;

    private SharedPreferences blackOutPrefs;

    private Builder builder = new Builder();


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

//        startServer();
//        startSender();

        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //Configure  TUN and get the interface.
                    mInterface = builder.setSession("VPNService")
                            .setMtu(1500)
                            .addAddress("10.0.2.0", 24)
                            //.addDnsServer("8.8.8.8")
                            .addRoute("0.0.0.0", 0).establish();
                    // Packets to be sent are queued in this input stream.
                    FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

                    // Packets received need to be written to this output stream.
                    FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());

                    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;

                    //The UDP channel can be used to pass/get ip package
                    DatagramChannel tunnel = DatagramChannel.open();
                    tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
                    //Protect this socket, so package send by it will not be feedback to the vpn service.
                    protect(tunnel.socket());

                    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) {
                            // 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;
                            }
                        }

                        // Read the incoming packet from the tunnel.
                        length = tunnel.read(packet);
                        if (length > 0) {
                            // Ignore control messages, which start with zero.
                            if (packet.get(0) != 0) {
                                // Write the incoming packet to the output stream.
                                out.write(packet.array(), 0, length);
                            }
                            packet.clear();

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

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

                        // If we are idle or waiting for the network, sleep for a
                        // fraction of time to avoid busy looping.
                        if (idle) {
                            Thread.sleep(100);

                            // Increase the timer. This is inaccurate but good enough,
                            // since everything is operated in non-blocking mode.
                            timer += (timer > 0) ? 100 : -100;

                            // We are receiving for a long time but not sending.
                            if (timer < -15000) {
                                // Send empty control messages.
                                packet.put((byte) 0).limit(1);
                                for (int i = 0; i < 3; ++i) {
                                    packet.position(0);
                                    tunnel.write(packet);
                                }
                                packet.clear();

                                // Switch to sending.
                                timer = 1;
                            }

                            // We are sending for a long time but not receiving.
                            if (timer > 20000) {
                                throw new IllegalStateException("Timed out");
                            }
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (mInterface != null) {
                            mInterface.close();
                            mInterface = null;
                        }
                    } catch (Exception e) {

                    }
                }
            }

        }, "VpnServiceRunnable");

        //start the service
        mThread.start();
        return START_STICKY;

    }


    @Override
    public void  onRevoke (){
        Log.d(TAG, "revoked:");
    }

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

//    public static void startSender() {
//        (new Thread() {
//            @Override
//            public void run() {
//                try {
//                    Socket s = new Socket("localhost", 60010);
//                    BufferedWriter out = new BufferedWriter(
//                            new OutputStreamWriter(s.getOutputStream()));
//
//                    while (true) {
//                        out.write("Hello World!");
//                        out.newLine();
//                        out.flush();
//
//                        Thread.sleep(200);
//                    }
//
//                } catch (UnknownHostException e) {
//                    e.printStackTrace();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
//        }).start();
//    }
//
//    public static void startServer() {
//        (new Thread() {
//            @Override
//            public void run() {
//                ServerSocket ss;
//                try {
//                    ss = new ServerSocket(60010);
//
//                    Socket s = ss.accept();
//
//                    BufferedReader in = new BufferedReader(
//                            new InputStreamReader(s.getInputStream()));
//                    String line = null;
//                    while ((line = in.readLine()) != null) {
//                        System.out.println(line);
//                    }
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//        }).start();
//    }


}