CikLinas
CikLinas

Reputation: 242

VPN packet bypass

I'm working on creating a simulated VPN (Doesn't actually create a real connection to server) to get all incoming and outgoing network bytes (information).

For now i can get packets and parse them. What i get for example:

IP Version:4 Header Length:20 Total Length:60 Protocol:6 Source IP:10.0.2.0 Destination IP:5.20.5.59 Hostname:clients4.google.com

I would like to know what and how should i do to make connections to websites/applications (For now it doesn't connect).

In this website: http://www.thegeekstuff.com/2014/06/android-vpn-service/ writes that it is needed to make these steps:

  1. Get IP packet from TUN. Same as all VPN service does.
  2. Extract layer 4 information. Protocol type (e.g. TCP/UDP) and its payload is a must. As there is a handshake procedure in TCP, before getting actually payload data from it, we need to write back handshake packet first.
  3. Choose corresponding socket to send out the payload. As this step is working on layer 4, so we need to save the socket and try to get return data later. If there is any return data, we need to pass these packet to TUN.
  4. Get packet from socket, and build a layer 3 packet. First, we need to build a valid layer 4 packet. UDP is a bit easier as the 4 byte UDP header only contains source address, source port, destination address, destination port. TCP is more complex as it’s a state
  5. connection, the sequence number and acknowledge number should be properly set. Then, use the layer 4 packet as payload, we need to build a valid layer 3 packet. Write IP packet back to TUN. Same as all VPN service does.

At 2 step i get information from packet. But don't undearstand how it should be done further. Maybe someone can explain me in detail. Plus maybe can tell me how to get destinations Port when i have its IP address. Also there is the code:

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

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

    private Handler mHandler;
    private Thread mThread;

    private ParcelFileDescriptor mInterface;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mHandler == null) {
            mHandler = new Handler(this);
        }

        if (mThread != null) {
            mThread.interrupt();
        }
        mThread = new Thread(this, "VpnThread");
        mThread.start();
        return START_STICKY;
    }

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

    @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) {  }
            Message msgObj = mHandler.obtainMessage();
            msgObj.obj = "Disconnected";
            mHandler.sendMessage(msgObj);

        } finally {

        }
    }

    DatagramChannel mTunnel = null;


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

        mTunnel = DatagramChannel.open();

        if (!protect(mTunnel.socket())) {
            throw new IllegalStateException("Cannot protect the tunnel");
        }

        mTunnel.connect(server);

        mTunnel.configureBlocking(false);
        handshake();

        connected = true;
        Message msgObj = mHandler.obtainMessage();
        msgObj.obj = "Connected";
        mHandler.sendMessage(msgObj);



        new Thread ()
        {

            public void run ()
            {
                FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
                ByteBuffer packet = ByteBuffer.allocate(32767);

                DatagramChannel tunnel = mTunnel;
                FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());
                int length;
                String destIP;

                try
                {

                    while (true)
                    {
                        while ((length = in.read(packet.array())) > 0) {
                            packet.limit(length);
                            Log.d(TAG, "Total Length:" + mTunnel.socket().getInetAddress());

                            mTunnel.write(packet);
                            packet.flip();

                            TCP_IP TCP_debug = new TCP_IP(packet);
                            TCP_debug.debug();
                            destIP = TCP_debug.getDestination();

                          //  InetAddress address = InetAddress.getByName(destIP);
                          //  System.out.println(address.getHostAddress()); // Gaunamas IP (185.11.24.36)
                          //  System.out.println(address.getHostName()); // www.15min.lt



                            out.write(packet.array(), 0, length);
                            packet.clear();

                            Thread.sleep(100);

                        }
                    }

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

            }

        }.start();


        return connected;
    }

    private void makeConnection(String destination, int port) {
        try {
            run(new InetSocketAddress(destination, port));
        }
        catch (Exception e) {
            Log.d(TAG, "klaida jungiantis");
        }
    }
    private void handshake() throws Exception {

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

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

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

            mInterface = builder.setSession("VPN'as").establish();
        }
    }


}



public class TCP_IP extends VPN {

    private ByteBuffer packet;
    private String hostname;
    private String destIP;
    private String sourceIP;
    private int version;
    private int protocol;
    private int port;


    public TCP_IP(ByteBuffer pack) {
        this.packet = pack;
    }

    public void debug() {


        int buffer = packet.get();
        int headerlength;
        int temp;

        version = buffer >> 4;
        headerlength = buffer & 0x0F;
        headerlength *= 4;
        System.out.println("IP Version:"+version);
        System.out.println("Header Length:"+headerlength);
        String status = "";
        status += "Header Length:"+headerlength;

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

        System.out.println( "Total Length:"+buffer);

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

        protocol = buffer;
        System.out.println( "Protocol:"+buffer);

        status += "  Protocol:"+buffer;

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


        byte buff = (byte)buffer;

        sourceIP  = "";
        buff = packet.get();  //Source IP 1st Octet
        temp = ((int) buff) & 0xFF;
        sourceIP += temp;
        sourceIP += ".";

        buff = packet.get();  //Source IP 2nd Octet
        temp = ((int) buff) & 0xFF;
        sourceIP += temp;
        sourceIP += ".";

        buff = packet.get();  //Source IP 3rd Octet
        temp = ((int) buff) & 0xFF;
        sourceIP += temp;
        sourceIP += ".";

        buff = packet.get();  //Source IP 4th Octet
        temp = ((int) buff) & 0xFF;
        sourceIP += temp;

        System.out.println( "Source IP:"+sourceIP);

        status += "   Source IP:"+sourceIP;


        destIP  = "";


        buff = packet.get();  //Destination IP 1st Octet
        temp = ((int) buff) & 0xFF;
        destIP += temp;
        destIP += ".";

        buff = packet.get();  //Destination IP 2nd Octet
        temp = ((int) buff) & 0xFF;
        destIP += temp;
        destIP += ".";

        buff = packet.get();  //Destination IP 3rd Octet
        temp = ((int) buff) & 0xFF;
        destIP += temp;
        destIP += ".";

        buff = packet.get();  //Destination IP 4th Octet
        temp = ((int) buff) & 0xFF;
        destIP += temp;

        System.out.println( "Destination IP:" + destIP);
        status += "   Destination IP:"+destIP;




    }

    public String getDestination() {
        return destIP;
    }

    public int getProtocol() {
        return protocol;
    }

    public int getPort() {
        return port;
    }

    public String getHostname() {
        return hostname;
    }

    public int getIPversion() { return version; }

}

Upvotes: 12

Views: 4216

Answers (1)

Gorio
Gorio

Reputation: 1646

Change

private String mServerAddress = "127.0.0.1";

to

private String mServerAddress = "10.0.0.1";

I don't know the answer and explain what happened yet, but i saw in Android Monitor that we can't use localhost (127.0.0.1) into Server Address.

There is another problem, with SSL over HTTP (HTTPS). If you connect in a site like http://www.gorio.com.br it will work, but if you try https://www.google.com wont work.

Upvotes: 1

Related Questions