Я пытаюсь написать прокси для простых сервисов, таких как http и smtp, используя Java.
пока у меня есть это:
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.
* SSLSocket sock =
* (SSLSocket) getSocketFactory.createSocket ( host, 443 );
* @return Специфичная для SSL фабрика сокетов.
** /
public static final SSLSocketFactory getSocketFactory () {
if (sslSocketFactory == null) {
пытаться {
TrustManager [] tm = new TrustManager [] {new NaiveTrustManager ()};
SSLContext context = SSLContext.getInstance ("SSL");
context.init (новый KeyManager [0], tm, новый SecureRandom ());
sslSocketFactory = (SSLSocketFactory) context.getSocketFactory ();
} catch (KeyManagementException e) {
System.err.println («Без поддержки алгоритма SSL:» + e.getMessage ());
} catch (NoSuchAlgorithmException e) {
System.err.println («Исключение при настройке управления наивным ключом.»);
}
}
return sslSocketFactory;
}
ProxyWorker (Socket c) {
клиент = с;
пытаться {
пытаться {
server = (SSLSocket) getSocketFactory (). createSocket (Main.remoteH, Main.remotePort);
((SSLSocket) сервер) .startHandshake ();
serverOut = server.getOutputStream ();
serverIn = server.getInputStream ();
} catch (исключение e) {
System.err.println ("SSL FAIL! \ N" + e.toString ());
сервер = новый сокет (Main.remoteH, Main.remotePort);
serverOut = server.getOutputStream ();
serverIn = server.getInputStream ();
}
clientOut = client.getOutputStream ();
clientIn = client.getInputStream ();
} catch (исключение e) {
System.out.println ("error \ n" + e.toString ());
System.exit (0);
}
}
public void run () {
System.out.println («прослушивающий бегун активирован»);
пытаться {
byte [] b = новый байт [0];
BufferedOutputStream bos = new BufferedOutputStream (System.out);
while (true) {
int clientReady = clientIn.available ();
while (clientReady> 0) {
b = новый байт [clientReady];
clientIn.read (b, 0, clientReady);
serverOut.write (б);
bos.write (б);
bos.flush ();
clientReady = clientIn.available ();
}
Thread.sleep (100);
int serverReady = serverIn.available ();
while (serverReady> 0) {
b = новый байт [serverReady];
serverIn.read (b, 0, serverReady);
clientOut.write (б);
bos.write (б);
bos.flush ();
serverReady = serverIn.available ();
}
если (server.isClosed () || client.isClosed ()) {
перерыв;
}
}
} catch (NullPointerException e) {
System.err.println ( "NPE: \ п" + e.getMessage ());
System.err.println (e.toString ());
e.printStackTrace ();
} catch (исключение e) {
System.out.println (е);
} в конце концов {
пытаться {
server.close ();
client.close ();
} catch (IOException ex) {
System.out.println («не удалось закрыть сокеты»);
}
}
System.out.println («Выход из потока сейчас»);
}
}
n.b. Наивный доверительный менеджер принимает все сертификаты, потому что мой почтовый сервер использует самозаверяющий сертификат, и это только для личного / моего собственного образовательного использования, поэтому я не беспокоюсь о безопасности вообще.
похоже, что это работает ~ хорошо для не ssl-соединений - я протестировал esmtp, который создает соединение и обменивается приветствиями и прочим, но мой сервер не поддерживает аутентификацию через не ssl-соединения, поэтому я не могу проверить отправку любые сообщения.
Я также проверил HTTP-соединения не по протоколу ssl, которые он может нормально обрабатывать, хотя я думаю, что потоки не любят обрабатывать изображения очень хорошо, так как только некоторые изображения проходят.
Я подозреваю, что я сделал там не слишком замечательный код, но в данный момент я пытаюсь заставить его работать на ssl, чтобы я мог его понять.
при использовании его в режиме ssl я выяснил, что поток ProxyWorker попадает в цикл while true, но затем просто продолжает цикл. поэтому для esmtp, пока он ожидает приветствия, я вообще ничего не получаю, а при использовании http вижу запрос get от firefox, но опять ничего от сервера.
Любые указатели / вещи, которые я делаю неправильно / рекомендуемое чтение, будут оценены