I created a local proxy server to intercept all the network traffic. The code intercepts http/https traffic. The proxy works properly in Eclipse but when I integrate it with my android project it only works for http traffic.

Originally it was not working for http traffic also because the socket was not protected from VpnService in Android. Once the Socket of the channel was protected for http, it worked fine.

import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.regex.Pattern;

public class Server extends Thread {

public static void main(String[] args) {
    (new Server()).run();
}

@Override
public void run() {

    try (ServerSocket serverSocket = new ServerSocket(9999)) {
        Socket socket;
        try {
            while ((socket = serverSocket.accept()) != null) {
                (new Handler(socket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }
}

public static class Handler extends Thread {
    public static final Pattern CONNECT_PATTERN = Pattern.compile("CONNECT (.+):(.+) HTTP/(1\\.[01])", Pattern.CASE_INSENSITIVE);
    public int port = 80;
    private final Socket clientSocket;

    public Handler(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {

            byte[] buffer = new byte[4096];
            InputStream browserInputStream = clientSocket.getInputStream();

            int n = browserInputStream.read(buffer);

            String browserRequest = new String(buffer, 0, n);
            String[] requestLines = browserRequest.split("\r\n");

            if (requestLines[0].startsWith("CONNECT")) {
                //HTTPS TRAFFIC
                //Browser Request Received
                String[] connectRequest = requestLines[0].split(" ");
                String urlAndPort = connectRequest[1];
                String url = urlAndPort.split(":")[0];
                int port = Integer.parseInt(urlAndPort.split(":")[1]);

                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(clientSocket.getOutputStream());

                final Socket forwardSocket;

                try {
                    forwardSocket = new Socket(url, port);
                } catch (IOException | NumberFormatException e) {
                    e.printStackTrace();
                    outputStreamWriter.write("HTTP/" + "1.1" + " 502 Bad Gateway\r\n");
                    outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
                    outputStreamWriter.write("\r\n");
                    outputStreamWriter.flush();
                    return;
                }


                try {
                    //OK Response sent to browser
                    outputStreamWriter.write("HTTP/" + "1.1" + " 200 Connection established\r\n");
                    outputStreamWriter.write("Proxy-agent: Simple/0.1\r\n");
                    outputStreamWriter.write("\r\n");
                    outputStreamWriter.flush();

                    Thread remoteToClient = new Thread() {
                        @Override
                        public void run() {
                            forwardData(forwardSocket, clientSocket);
                        }
                    };

                    remoteToClient.start();

                    try {
                        forwardData(clientSocket, forwardSocket);
                    } finally {
                        try {
                            remoteToClient.join();
                        } catch (InterruptedException e) {
                            e.printStackTrace(); // TODO: implement catch
                        }
                    }
                } finally {
                    forwardSocket.close();
                }
            } else {
                //HTTP TRAFFIC
                int start = browserRequest.indexOf("Host: ") + 6;
                int end = browserRequest.indexOf('\n', start);
                String host = browserRequest.substring(start, end - 1);

                SocketChannel proxyToServerChannel = SocketChannel.open();
                Socket proxyToServerSocket = proxyToServerChannel.socket();
                //VpnServiceHelper.protect(proxyToServerSocket) //Protect the socket from VPNSERVICE

                InetSocketAddress serverAddress = new InetSocketAddress(host, port);
                proxyToServerChannel.configureBlocking(false);
                proxyToServerChannel.connect(serverAddress);

                while (!proxyToServerChannel.finishConnect());

                ByteBuffer buf = ByteBuffer.wrap(buffer);
                proxyToServerChannel.write(buf);

                try {
                    InputStream inputStream = proxyToServerSocket.getInputStream();
                    try {
                        OutputStream outputStream = clientSocket.getOutputStream();
                        try {

                            int read = 0;
                            do {

                                if (read == 0)
                                    try {
                                        Thread.sleep(500);
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }

                                read = proxyToServerChannel.read(ByteBuffer.wrap(buffer));

                                if (read > 0) {
                                    clientSocket.getOutputStream().write(buffer);

                                    if (inputStream.available() < 1) {
                                        outputStream.flush();
                                    }
                                }
                            } while (read >= 0);

                        } finally {
                            if (!clientSocket.isOutputShutdown()) {
                                clientSocket.shutdownOutput();
                            }
                        }
                    } finally {
                        if (!proxyToServerSocket.isInputShutdown()) {
                            proxyToServerSocket.shutdownInput();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void forwardData(Socket inputSocket, Socket outputSocket) {
        try {
            InputStream inputStream = inputSocket.getInputStream();
            try {
                OutputStream outputStream = outputSocket.getOutputStream();
                try {
                    byte[] buffer = new byte[4096];
                    int read;
                    do {
                        read = inputStream.read(buffer);
                        if (read > 0) {
                            outputStream.write(buffer, 0, read);
                            if (inputStream.available() < 1) {
                                outputStream.flush();
                            }
                        }
                    } while (read >= 0);

                } finally {
                    if (!outputSocket.isOutputShutdown()) {
                        outputSocket.shutdownOutput();
                    }
                }
            } finally {
                if (!inputSocket.isInputShutdown()) {
                    inputSocket.shutdownInput();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
}

0 Answers