2014-10-20 3 views
0

이 경우 SSL 데이터 (HTTPS)를 프록시하고 싶습니다.루비 SSL 프록시 (MITM)

여기 내 코드입니다 :

begin 
     server = TCPServer.open(on_demand_port) 
rescue Exception => e 
     sleep 5 
     retry 
end 
sslContext = OpenSSL::SSL::SSLContext.new 
sslContext.verify_mode = OpenSSL::SSL::VERIFY_NONE 
begin 
    sslContext.cert = OpenSSL::X509::Certificate.new(File.open("#{Dir.pwd}/Cert/cert.pem")) 
    sslContext.key = OpenSSL::PKey::RSA.new(File.open("#{Dir.pwd}/Cert/key.pem"), "1234") 

rescue Exception => e 
     sleep 5 
     retry 
end 
begin 
    sslServer = OpenSSL::SSL::SSLServer.new(server, sslContext) 
rescue Exception => e 
     sleep 5 
     retry 
end 

while true 

    begin 
     threads << Thread.new(sslServer.accept) do |client| # Putting new connections into the thread pool 
     tcp_proxy(client, db_name, db_user, db_password, remote_host, remote_port, patterns) 
     end 
    rescue Exception => e 
    end 



    threads = threads.select { |t| t.alive? ? true : (t.join; false) } 
     while threads.size >= on_demand_max_threads 
      sleep 1 
      threads = threads.select { |t| t.alive? ? true : (t.join; false) } 
    end 
end 

그리고 이것은 실제 SSL 프록시

begin 
begin 
    ssl_context = OpenSSL::SSL::SSLContext.new 
    ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE 
    cert_store = OpenSSL::X509::Store.new 
    cert_store.set_default_paths 
    ssl_context.cert_store = cert_store 
    tcp_socket = TCPSocket.new(remote_host, remote_port) 
    server_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context 
    server_socket.sync_close = true 
    server_socket.connect 
rescue Exception => e 
      client.close 
end   
while true 
    # Wait for data to be available on either socket. 
    (ready_sockets, dummy, dummy) = IO.select([client, server_socket]) 
    begin 
     ready_sockets.each do |socket| 
      data = socket.readpartial(4096) 
      if socket == client 
       # Read from client, write to server. 
       server_socket.write data 
       server_socket.flush 
      else 
       # Read from server, write to client. 
       client.write data 
       client.flush 
      end 
    end 
    rescue Exception => e 
    end 
end 
    rescue StandardError => e 
    end 
    begin 
     client.close 
     server_socket.close 
    rescue Exception => e 
    end 

인 "tcp_proxy"지금이 정상적인 TCP와 HTTP에 큰 작동되지만, 소켓을 업그레이드 할 때 SSL \ HTTPS에서 사용하면 정말 느리게 시작되고 때로는 제한 시간이 시작됩니다.

왜 그런가?

답변

1

select가 TCP 레벨 인 동안 읽기가 SSL 레벨에서 수행되기 때문에 읽기와 선택에주의해야합니다.

SSL은 데이터를 프레임에 넣습니다. 각 프레임에는 최대 16384 바이트를 포함 할 수 있습니다. SSL 소켓의 읽기가 프레임의 데이터를 반환하기 전에 기본 TCP 소켓에서 전체 프레임을 읽어야합니다. 즉, 페이로드가 4097 바이트 인 프레임이있는 경우 SSL 소켓에서 아무 것도 읽을 수 없으면 TCP 소켓에서 전체 프레임을 읽어야합니다. 그런 다음 SSL 소켓에서 4096 바이트 만 읽으면 첫 번째 4096 바이트가 반환되고 나머지는 SSL 버퍼에 그대로 둡니다. 그런 다음 TCP 레벨에서 새 데이터를 선택하도록 선택하면 TCP 레벨에 읽지 않은 데이터가 없으므로 차단할 수 있습니다. SSL 버퍼 내에 여전히 1 바이트가 있더라도 차단할 수 있습니다. 여전히 SSL 버퍼에 데이터가있는 경우 pending

  • 확인 :

    이 문제를 해결하는 방법은 두 가지가 있습니다. 있다면, 선택을하는 대신 읽으십시오.

  • 또는 각 읽기와 함께 적어도 16384 바이트를 읽으려고합니다. 즉 SSL 프레임의 최대 크기입니다. 나는 루비에서 구현에 대해 잘 모르겠지만, 펄에서는이 부분은 단지 SSL_read을 호출 할 것이고 이것은 하나의 프레임에서 데이터를 읽는다. 따라서 16384 바이트의 읽기 크기로 보류중인 데이터가 없을 수 있으며 지금처럼 선택을 호출 할 수 있습니다.
+0

IO.select를 사용하고 "read"를 16384로 설정하는 것이 효과가있는 것처럼 보일지 모르겠습니다. 그러나 지금 당장은 속임수를 사용합니다. – Ba7a7chy