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