Написание прокси tcp (для http, smtp или аналогичного) в Java работает не ssl, но не работает ssl - PullRequest
1 голос
/ 26 апреля 2010

Я пытаюсь написать прокси для простых сервисов, таких как 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, но опять ничего от сервера.

Любые указатели / вещи, которые я делаю неправильно / рекомендуемое чтение, будут оценены

1 Ответ

1 голос
/ 23 мая 2013

Если вы пишете полностью прозрачный прокси, вам вообще не нужно рассматривать SSL. Просто скопируйте байты.

Если вы пишете приложение прокси, такое как HTTP, вам придется иметь дело с командой установки. Например, HTTP-прокси получит команду HTTP CONNECT, которая сообщает ему, к чему подключаться, и должен ответить соответствующим HTTP-ответом в виде открытого текста, прежде чем он начнет смещать байты в обоих направлениях.

В любом случае нет необходимости реализовывать SSL в прокси.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...