tags:

views:

156

answers:

0

Hi

i'm trying to write a proxy for simple services like http and smtp using java. so far i've got this:

class Main {

public static final int listenPort = 465, // port to listen on
        remotePort = 465;   // port to connect to
public static final String remoteH = "";// my mail server hostname here

public static void main(String[] args) {
    ExecutorService tm = Executors.newCachedThreadPool();
    try {
        ServerSocket ss = new ServerSocket(listenPort);
        while (true) {
            try {
                Socket client = ss.accept();
                tm.submit(new ProxyWorker(client));
            } catch (Exception e) {
                System.out.println("error " + e);
            }
        }
    } catch (Exception e) {
        System.out.println("error " + e);
    }
}

}

class ProxyWorker implements Runnable {

Socket client, server;
OutputStream serverOut = null, clientOut = null;
InputStream serverIn = null, clientIn = null;
private static SSLSocketFactory sslSocketFactory;

/**
 * Returns a SSL Factory instance that accepts all server certificates.
 * <pre>SSLSocket sock =
 *     (SSLSocket) getSocketFactory.createSocket ( host, 443 ); </pre>
 * @return  An SSL-specific socket factory.
 **/
public static final SSLSocketFactory getSocketFactory() {
    if (sslSocketFactory == null) {
        try {
            TrustManager[] tm = new TrustManager[]{new NaiveTrustManager()};
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(new KeyManager[0], tm, new SecureRandom());
            sslSocketFactory = (SSLSocketFactory) context.getSocketFactory();
        } catch (KeyManagementException e) {
            System.err.println("No SSL algorithm support: " + e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            System.err.println("Exception when setting up the Naive key management.");
        }
    }
    return sslSocketFactory;
}

ProxyWorker(Socket c) {
    client = c;
    try {


        try {
            server = (SSLSocket) getSocketFactory().createSocket(Main.remoteH, Main.remotePort);
            ((SSLSocket)server).startHandshake();
            serverOut = server.getOutputStream();
            serverIn = server.getInputStream();
        } catch (Exception e) {
            System.err.println("SSL FAIL!\n" + e.toString());
            server = new Socket(Main.remoteH, Main.remotePort);
            serverOut = server.getOutputStream();
            serverIn = server.getInputStream();
        }

        clientOut = client.getOutputStream();
        clientIn = client.getInputStream();
    } catch (Exception e) {
        System.out.println("error\n" + e.toString());
        System.exit(0);
    }
}

public void run() {
    System.out.println("listening runner activated");
    try {
        byte[] b = new byte[0];
        BufferedOutputStream bos = new BufferedOutputStream(System.out);
        while (true) {
            int clientReady = clientIn.available();
            while (clientReady > 0) {
                b = new byte[clientReady];
                clientIn.read(b, 0, clientReady);
                serverOut.write(b);
                bos.write(b);
                bos.flush();
                clientReady = clientIn.available();
            }
            Thread.sleep(100);
            int serverReady = serverIn.available();
            while (serverReady > 0) {
                b = new byte[serverReady];
                serverIn.read(b, 0, serverReady);
                clientOut.write(b);
                bos.write(b);
                bos.flush();
                serverReady = serverIn.available();
            }
            if(server.isClosed()||client.isClosed()){
                break;
            }
        }
    } catch (NullPointerException e) {
        System.err.println("NPE:\n"+e.getMessage());
        System.err.println(e.toString());
        e.printStackTrace();
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        try {
            server.close();
            client.close();
        } catch (IOException ex) {
            System.out.println("could not close sockets");
        }
    }
    System.out.println("Thread Exiting Now");
}

}

n.b. the naive trust manager accepts all certs cos my mailserver is using a self signed cert and this is only for personal/my own educational use so i'm not worrying about security at all.

it seems to be working ~ok for non ssl connections - i have tested esmtp which creates a connection and exchanges greetings and stuff, but my server doesn't support authentication over non ssl connections, so i can't test sending of any messages.

i've also tested for non ssl http connections - which it can handle ok - though i think the threads don't like handling images very well as only some immages get through.

i suspect i've done some not too wonderful code in there, but at the moment i'm trying to get it to work on ssl so i can understand it.

when using it in ssl mode i have worked out that the ProxyWorker thread gets to the while true loop, but then just keeps looping. so for esmtp while it waits for the greeting i get no output at all, and when using http i see the get request from firefox, but again nothing from the server.

any pointers/things i do wrong/recommended reading would be appreciated

thanks matt