尝试在java中处理来自浏览器的HTTP CONNECT请求

时间:2011-11-16 01:01:47

标签: java sockets ssl

我真的想更好地了解如何处理CONNECT HTTP请求流程。我在我正在构建的HttpServer中陷入困境,希望其他人可以帮助我煽动我应该如何处理下一个挑战。到目前为止我的代码的一些信息。我有一个类HTTPServer侦听端口8080上的套接字(最初是非SSL套接字)。我有一个名为DefaultHttpRequestHandler的类,它包含一个HTTPClient实例,它处理服务器需要进行的所有请求,HttpServer内的工作线程处理调度浏览器发送到端口8080的所有请求。

我的问题如下:

  1. 当CONNECT请求进入并发送到DefaultHttpRequestHandler时,它会被传递给句柄(HttpRequest请求,HttpResponse响应,HttpContext上下文)方法。在这一点上,我偷看了请求,如果我看到它是一个CONNECT接下来的什么?我想我然后在端口8080上建立SSL套接字连接,这是在普通套接字之前?或者我总是把两个插座作为标准插座,一个作为ssl而不是切换到ssl。这部分让我非常沮丧,我很困惑如何编码这个吸盘!
  2. 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 - 这是我的http服务器中处理调度请求的运行方法

     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 个答案:

答案 0 :(得分:4)

接收CONNECT请求(并接受它)的代理不执行任何SSL / TLS初始化或处理(如果确实如此,它将是潜在的MITM攻击者)。它只是来回传递目标HTTPS主机和初始客户端之间的所有流量。

这些答案中可能更详细:

您需要的是能够获取底层套接字(或输入/输出流)并写入您在另一侧读取的每个字节。