2

我正在尝试使用 java 和 jetty 创建代理服务器。我已经设法连接到 http(非安全),但 https 有问题。

我一直在做的是:

    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;
}

我的问题是:

  1. 代码不起作用(Error code: ssl_error_rx_record_too_long)
  2. 何时关闭套接字连接,以及使用什么类型的套接字。

提前致谢。

更新代码:

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;
}
4

2 回答 2

2

我已经通过使用ConnectHandler码头提供的解决了我的连接问题。

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

此代码解决了 Https + Http 连接问题。我也可以使用身份验证。

于 2013-06-04T13:34:59.323 回答
1

出于多种原因,您无法将适当的代理编写为 Servlet。一方面,您引入了太多延迟,因为在您创建上游连接之前,请求完全由 servlet 容器组装。

HTTP 代理是一件非常简单的事情,除非您需要查看请求和响应。您所要做的就是解析传入的 CONNECT 命令,形成上游连接,然后开始同时在两个方向复制字节。不管上游连接是HTTP还是HTTPS,代码都是一样的。

要回答您的具体问题:

  1. 在收到 EOS 之前,您应该从每个对等方读取。此时,您应该关闭与其他对等方的套接字以进行输出。如果您已经关闭了从中读取 EOS 的套接字,那么您应该关闭两个套接字。

  2. 纯文本。传入的 HTTP CONNECT 命令始终是纯文本的,您不必关心上游连接是什么,因为您只是在复制字节。如有必要,对等方将协商 SSL,但这与您无关。

于 2013-06-03T00:05:22.683 回答