Question

I am trying to create a proxy server using java and jetty. I've managet to connect to http (non secured one) but there is problem with https.

What I've been doing is as:

    private boolean handleConnect(HttpServletRequest req,HttpServletResponse response){
    String uri=req.getRequestURI();
    System.out.println("--Handle--Connect-");
    String port="";
    String host="";
    int c=uri.indexOf(":");
    if (c >= 0){
        port = uri.substring(c + 1);
        host = uri.substring(0,c);
        if (host.indexOf('/') > 0)
            host = host.substring(host.indexOf('/') + 1);
    }
    boolean isBlocked;
    isBlocked=false;
    SocketChannel sock = null;
    InputStream in=null;
    OutputStream out=null;
    try {
        sock = SocketChannel.open();
        in=req.getInputStream();
        out=response.getOutputStream();

    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    try{
         InetSocketAddress inetAddress = new InetSocketAddress(host,req.getRemotePort());
         sock.connect(inetAddress);
         InputStreamReader inputstreamreader = new InputStreamReader(req.getInputStream());
         BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

         OutputStreamWriter outputstreamwriter = new OutputStreamWriter(sock.socket().getOutputStream());
         BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
         response.setStatus(200);
         response.setHeader("Connection", req.getHeader("Connection"));
         String string = null;

         while ((string = bufferedreader.readLine()) != null) {
                bufferedwriter.write(string );
                bufferedwriter.flush();
         }


        sock.configureBlocking(false);
        sock.connect(new InetSocketAddress(host,Integer.parseInt(port)) );
        while(!sock.finishConnect()){
            // Wait for connecting
        }

            response.setStatus(200);
            response.setHeader("Connection", req.getHeader("Connection"));
            response.flushBuffer();

        ByteBuffer bb=ByteBuffer.allocate(1024*1024);
        bb.clear();
        in.mark(0);

        if(in.available()>0){

             byte by[]=new byte[in.available()];
             bb.put(by);
                if(sock.isConnected()){
                    sock.write(bb);
                }

        }

    }
    catch(Exception ex){
        ex.printStackTrace();
        isBlocked=true;
        try {
        //  sock.close();
            throw new IOException("Hello World");
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }
    finally{
        try {
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return true;
}

My Questions are:

  1. The code is not working (Error code: ssl_error_rx_record_too_long)
  2. When is to close the socket connection, and what type of socket to use.

Thanks in Advance.

UPDATED CODE:

private boolean handleConnect(HttpServletRequest req,HttpServletResponse response){
    String uri=req.getRequestURI();
    System.out.println("--Handle--Connect-");
    String port="";
    String host="";
    int c=uri.indexOf(":");
    if (c >= 0){
        port = uri.substring(c + 1);
        host = uri.substring(0,c);
        if (host.indexOf('/') > 0)
            host = host.substring(host.indexOf('/') + 1);
    }
    boolean isBlocked;
    isBlocked=false;
    Socket sock = null;
    IORedirect c2s, s2c;

    // Make Asyncronous connection
    try{
            sock=new Socket(host,Integer.parseInt(port));

            OutputStream os = response.getOutputStream();

            byte[] msg = new String("HTTP/1.0 200 Connection established\r\nProxy-agent: RPS-Proxy/1.0\r\n\r\n").getBytes();
            os.write(msg);
            os.flush();

            c2s=new IORedirect(req.getInputStream(),sock.getOutputStream());
            c2s.setName("Client to Server");
            c2s.start();
            Thread.sleep(500);

            s2c=new IORedirect(sock.getInputStream(), os);
            s2c.setName("Server to Client");
            s2c.start();
            Thread.sleep(500);
            System.err.println("A");

    }
    catch(Exception ex){
        ex.printStackTrace();
        isBlocked=true;
        try {
            sock.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
    while(c2s.isAlive() || s2c.isAlive()){

    }
    try {
        sock.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return true;
}
Was it helpful?

Solution

I've Solved my connect problem by using ConnectHandler provided by jetty.

    HandlerCollection coll=new HandlerCollection();
    ConnectHandler aa=new ConnectHandler();
    coll.addHandler(aa);
    server.addConnector(http);
    server.setHandler(coll);

This code solves Https + Http connection problem. And I can use authentication too.

OTHER TIPS

You can't write a proper proxy as a Servlet, for a number of reasons. For one thing, you are introducing far too much latency, as the request is completely assembled by the servlet container before you get to create the upstream connection.

An HTTP proxy is a very simple thing, unless you need to look into the requests and responses. All you have to do is parse the incoming CONNECT command, form the upstream connection, and then start copying bytes in both directions simultaneously. It doesn't matter whether the upstream connection is HTTP or HTTPS, the code is the same.

To answer your specific questions:

  1. You should read from each peer until you receive EOS. At that point you should shutdown the socket to the other peer for output. If you have already shutdown the socket you read the EOS from, you should then close both sockets.

  2. Plaintext. The incoming HTTP CONNECT command is always in plaintext, and you don't care what the upstream connection is, as you are just copying bytes. The peers will negotiate SSL if necessary, but that's nothing to do with you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top