Попытка обработать запрос HTTP CONNECT из браузера в Java - PullRequest
3 голосов
/ 16 ноября 2011

Я действительно пытаюсь лучше понять, как обрабатывается запрос HTTP CONNECT. Я застрял на этом этапе моего HttpServer, который я создаю, и надеялся, что другие могут помочь мне подсказать, как я должен подходить к этим следующим вызовам. Пока немного информации о моем коде. У меня есть класс HTTPServer, прослушивающий сокет на порте 8080 (изначально он не является сокетом SSL). У меня есть класс DefaultHttpRequestHandler, который содержит экземпляр HTTPClient, который обрабатывает все запросы, которые должны быть сделаны сервером, и рабочий поток внутри HttpServer обрабатывает все запросы, отправляемые браузером на порт 8080.

У меня следующий вопрос:

  1. Когда приходит запрос CONNECT и отправляется в DefaultHttpRequestHandler, он передается методу (запрос HttpRequest, ответ HttpResponse, контекст HttpContext). В этот момент я просматриваю запрос, и если я вижу, что это СОЕДИНЕНИЕ, что дальше? Я думал, что тогда я устанавливаю соединение сокета SSL на порту 8080, который был до нормального сокета? или я всегда держу два сокета один как стандартный сокет и один как ssl, чем переключиться на один ssl. Эта часть действительно расстраивает меня, очень смущенный, как закодировать эту присоску!

DefaultHttpServer.java - сервер

 public class DefaultHttpServer {

public static void main(String[] args) throws Exception {

    Thread t = new RequestListenerThread(8080);
    t.setDaemon(false);
    t.start();

    //send a request to proxy server for testing
    testSendReqFromClient() ;
}

public static void testSendReqFromClient() throws Exception
{

    SSLContext sslCtx = SSLContext.getInstance("TLS");

    //  sslCtx.init(null,new TrustManager[] { new EasyX509TrustManager() }, null);


        sslCtx.init(null, new TrustManager[] { new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            System.out.println("getAcceptedIssuers =============");
                            return null;
                    }

                    public void checkClientTrusted(X509Certificate[] certs,
                                    String authType) {
                            System.out.println("checkClientTrusted =============");
                    }

                    public void checkServerTrusted(X509Certificate[] certs,
                                    String authType) {
                            System.out.println("checkServerTrusted =============");
                    }

                    @Override
                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] arg0,
                            String arg1) throws CertificateException {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] arg0,
                            String arg1) throws CertificateException {
                        // TODO Auto-generated method stub

                    }
        } }, new SecureRandom());

    Thread.sleep(5000);
    SSLSocketFactory sf = new SSLSocketFactory(sslCtx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    Scheme https = new Scheme("https", 443, sf);
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(https);
    Scheme http = new Scheme("http", 80, PlainSocketFactory.getSocketFactory());
    schemeRegistry.register(http);
    BasicHttpRequest req = new BasicHttpRequest("GET","https://www.yahoo.com");
    ThreadSafeClientConnManager tm = new ThreadSafeClientConnManager(schemeRegistry);
    HttpClient httpClient = new DefaultHttpClient(tm);
    ConnRouteParams.setDefaultProxy(req.getParams(), new HttpHost("localhost",8080,"http"));
    httpClient.execute(new RequestWrapper(req));
}

 }

DefaultRequestHandler.java - клиент, который отправляет запросы на сервер с моего прокси-сервера

 public class DefaultHttpRequestHandler implements HttpRequestHandler {

private static String sslType = "TLS";
private HttpClient httpClient = null;
private ThreadSafeClientConnManager tm;
public DefaultHttpRequestHandler() {
    super();
    init();

}

private void init() {
    try {
        SSLContext sslCtx = SSLContext.getInstance(sslType);

    //  sslCtx.init(null,new TrustManager[] { new EasyX509TrustManager() }, null);


        sslCtx.init(null, new TrustManager[] { new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            System.out.println("getAcceptedIssuers =============");
                            return null;
                    }

                    public void checkClientTrusted(X509Certificate[] certs,
                                    String authType) {
                            System.out.println("checkClientTrusted =============");
                    }

                    public void checkServerTrusted(X509Certificate[] certs,
                                    String authType) {
                            System.out.println("checkServerTrusted =============");
                    }

                    @Override
                    public void checkClientTrusted(
                            java.security.cert.X509Certificate[] arg0,
                            String arg1) throws CertificateException {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void checkServerTrusted(
                            java.security.cert.X509Certificate[] arg0,
                            String arg1) throws CertificateException {
                        // TODO Auto-generated method stub

                    }
        } }, new SecureRandom());

    SSLSocketFactory sf = new SSLSocketFactory(sslCtx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);


        Scheme https = new Scheme("https", 443, sf);
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(https);

        Scheme http = new Scheme("http", 80, PlainSocketFactory.getSocketFactory());
        schemeRegistry.register(http);

        tm = new ThreadSafeClientConnManager(schemeRegistry);
        //httpClient = new  ContentEncodingHttpClient(tm);
        httpClient = new DefaultHttpClient(tm);
        httpClient.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true); 
        //httpClient.getConnectionManager().getSchemeRegistry()         .register(https);

    } catch (Exception e) {
        System.err.println(e.getMessage());
        e.printStackTrace();
    }

}

public void handle(HttpRequest request, HttpResponse response,
        HttpContext context) throws HttpException, IOException {

    System.out.println(request);
    RequestLine reqLine = request.getRequestLine();
    if(reqLine.getMethod().equalsIgnoreCase("CONNECT"))
    {

        response.setEntity(new BufferedHttpEntity(new StringEntity("HTTP/1.0 200 Connection established\r\nProxy-agent: proxy client\r\n\r\n")));
        //do i switch the socket to sslsocketconnection in defaulthttpserver here?
    }
    else
    {
        try {

            HttpResponse clientResponse = null;

            HttpEntity entity = null;

            clientResponse = httpClient.execute(new RequestWrapper(request));

            entity = clientResponse.getEntity();

            if (entity != null) {
                response.setEntity(new BufferedHttpEntity(entity));
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
        } 

    }

}

}

RequestListenerThread - это метод run внутри моего httpserver, который обрабатывает запросы

 class RequestListenerThread extends Thread {

    private static ServerSocket sslServersocket = null;
    private static ServerSocket serversocket = null;
     static ServerSocketFactory ssocketFactory  = null;
    private final HttpParams params;
    private final HttpService httpService;
    Selector selector ;

    public RequestListenerThread(int port) throws Exception {


        KeyStore ks = KeyStore.getInstance("JKS");  
        ks.load(new FileInputStream("privateKey2.store"), "whitehatsec123".toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, "whitehatsec123".toCharArray());

        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(), null, null);


        ssocketFactory = context.getServerSocketFactory();
        //serversocket =  ssocketFactory.createServerSocket(port);
        serversocket = new ServerSocket(port);
        this.params = new SyncBasicHttpParams();
        this.params.setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true).setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 50000)
                .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE,
                        8 * 1024)
                .setBooleanParameter(
                        CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
                .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
                .setParameter(CoreProtocolPNames.ORIGIN_SERVER,
                        "HttpComponents/1.1");
        // Set up the HTTP protocol processor
        HttpProcessor httpproc = new ImmutableHttpProcessor(
                new HttpResponseInterceptor[] { new ResponseDate(),
                        new ResponseServer(), new ResponseContent(),
                        new ResponseConnControl() });

        // Set up request handlers
        HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry();
        reqistry.register("*", new DefaultHttpRequestHandler());

        // Set up the HTTP service
        this.httpService = new HttpService(httpproc,
                new DefaultConnectionReuseStrategy(),
                new DefaultHttpResponseFactory(), reqistry, this.params);
    }


    public void run() 
    {
        System.out.println("Listening on port "
                + serversocket.getLocalPort());
        while (!Thread.interrupted()) 
        {
            try 
            {
                // Set up HTTP connection
                Socket socket = serversocket.accept();
                DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
                System.out.println("Incoming connection from "
                        + socket.getInetAddress());
                conn.bind(socket, this.params);

                // Start worker thread
                Thread t = new WorkerThread(this.httpService, conn);
                t.setDaemon(true);
                t.start();
            } catch (InterruptedIOException ex) {
                break;
            } catch (IOException ex) {
                System.err
                        .println("I/O error initialising connection thread: "
                                + ex.getMessage());
                ex.printStackTrace();
                break;
            }
        }
    }


}




class WorkerThread extends Thread {

    private final HttpService httpservice;
    private final HttpServerConnection conn;

    public WorkerThread(final HttpService httpservice,
            final HttpServerConnection conn) {
        super();
        this.httpservice = httpservice;
        this.conn = conn;
    }

    public void run() {
        System.out.println("New connection thread");
        HttpContext context = new BasicHttpContext(null);

        try {
            while (!Thread.interrupted() && this.conn.isOpen()) {
                this.httpservice.handleRequest(this.conn, context);

            }
        } catch (ConnectionClosedException ex) {
            System.err.println("Client closed connection");
        } catch (IOException ex) {
            System.err.println("I/O error: " + ex.getMessage());
            ex.printStackTrace();
        } catch (HttpException ex) {
            System.err.println("Unrecoverable HTTP protocol violation: "
                    + ex.getMessage());
        } finally {
            try {
                this.conn.shutdown();
            } catch (IOException ignore) {
            }
        }
    }

}

1 Ответ

4 голосов
/ 16 ноября 2011

Прокси, получающий запрос CONNECT (и принимающий его), не выполняет инициализацию или обработку SSL / TLS (в противном случае это был бы потенциальный злоумышленник MITM). Он просто передает весь трафик между целевым узлом HTTPS и исходным клиентом туда и обратно.

Более подробно в этих ответах возможно:

То, что вам нужно, - это иметь возможность захватить базовый сокет (или потоки ввода / вывода) и записывать каждый байт, который вы читаете, на другой стороне.

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