2013-06-02 3 views
1

java 및 jetty를 사용하여 프록시 서버를 만들려고합니다. https (비보안 HTTP)에 연결하려면 managet을 사용했지만 https에는 문제가 있습니다. 어떤 종류의 코드는 소켓 연결을 닫습니다 (Error code: ssl_error_rx_record_too_long) 입니다 Java에서 SSL을 사용하는 HTTP 프록시

  • 작동하지 않습니다

    1. 및 :
      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; 
      } 
      

      내 질문

      은 다음과 같습니다

      은 내가 해왔 던 것은 같다 사용할 소켓.

    미리 감사드립니다.

    업데이트 된 코드 :

    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; 
    } 
    
  • +0

    다음은 Jetty 9에서 배포 한 것입니다. http://download.eclipse.org/jetty/stable-9/xref/org/eclipse/jetty/proxy/ProxyServlet.html –

    답변

    2

    나는 부두가 제공 한 ConnectHandler을 사용하여 연결 문제를 해결했습니다.

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

    이 코드는 Https + Http 연결 문제를 해결합니다. 그리고 인증도 사용할 수 있습니다.

    1

    당신은 여러 가지 이유로, 서블릿으로 적절한 프록시를 쓸 수 없습니다. 우선, 업스트림 연결을 생성하기 전에 요청이 서블릿 컨테이너에 의해 완전하게 어셈블되므로 대기 시간이 너무 길어집니다.

    HTTP 프록시는 요청과 응답을 조사 할 필요가없는 한 매우 간단한 것입니다. 들어오는 CONNECT 명령을 구문 분석하고 업스트림 연결을 작성한 다음 양방향으로 동시에 바이트를 복사하기 만하면됩니다. 업스트림 연결이 HTTP 또는 HTTPS인지 여부는 중요하지 않습니다. 코드는 동일합니다.

    는 특정 질문에 대답하려면, 당신은 EOS을받을 때까지 당신은 각 피어에서 읽어야

    1. . 이 시점에서 출력을 위해 다른 피어와의 소켓을 종료해야합니다. EOS를 읽은 소켓을 이미 종료했다면 두 소켓을 모두 닫아야합니다.

    2. 일반 텍스트. 들어오는 HTTP CONNECT 명령은 항상 일반 텍스트로되어 있으므로 바이트 만 복사하는 것처럼 업스트림 연결이 무엇이든 상관하지 않습니다. 필요한 경우 동료가 SSL을 협상하지만 이는 사용자와 관련이 없습니다.

    +0

    셧다운이란 무엇입니까? 출력을 위해 다른 피어에 소켓을 연결하면됩니다. ' 샘플 코드? – progrrammer

    +0

    'Socket.shutdownOutput()'. – EJP

    +0

    그리고 Handler를 사용하여 부두에서 프록시 역할을합니다. 좋은가요? – progrrammer